Blobs ins DB Speichern



  • Kann es sein, das in Deiner Tabelle keine Primärschlüsselspalte existiert?



  • Ne!

    Die Primärschlusselspalte ist "BLOBX"



  • Damit es hier icht zu langweilig wird, und es auch mal etwas positives zu erzählen gibt. Ichhabe zwar immer nich nicht mein Problem mit dem Speichern gelöst, aber einen recht einfachen Weg gefunden BLOBS aus einer DB in Files zu speichern.

    AnsiString SQL1 = "select BLOB from TABLE where BLOBX =";
      AnsiString UserName = "Username";
      AnsiString Password = "Password";
      AnsiString DokuX = Edit1->Text;
      AnsiString Path = "c:\\temp\\";
      AnsiString File ="\0";
      AnsiString Query1 = SQL1 + DokuX;
    
      if (SQLComponents == NULL)
      	{
        SQLComponents = new TSQLComponents(NULL);
        }
    
      SQLComponents->SQLConnection->Params->Values["User_Name"] = UserName.c_str();
      SQLComponents->SQLConnection->Params->Values["Password"] = Password.c_str()
    
      // Blob Auslesen!!
      SQLComponents->SQLClientDataSet->CommandText = Query1.c_str();
      SQLComponents->SQLConnection->Connected = true;
      SQLComponents->SQLClientDataSet->Active = true;
    
      SQLComponents->SQLClientDataSet->SaveToFile(File,dfBinary);
    
      SQLComponents->SQLConnection->Connected = false;
      SQLComponents->SQLClientDataSet->Active = false;
    
      delete SQLComponents;
    

    Ich habe dann natürlich gleich die Methode LoadFromFile() ausprobiert. ( keine Ahnung warum ich die nicht früher gefunden hatte ...) Exeptions gab es zwar nicht, Änderungen in der DB aber auch nicht 😞 In der Hilfe stand zusätzlich folgender denkwürdiger Satzt zu:
    void __fastcall LoadFromFile(const AnsiString FileName = "");

    "Hinweis: Die in FileName angegebene Datei muß Daten enthalten, die zuvor durch einen Aufruf der Datenmengenmethode SaveToFile gespeichert wurden"

    Toll!
    Heißt das, daß ich mit der Funktion nur Files in die DB schreiben darf die da eigentlich schon drinne liegen?? Wäre ja super ...... *mit dem kopf vor die wand schlag*



  • Dein Problem ist also immer noch die Save-Funktion. Hm. Irgendwie ist das da SELECT-Statement noch nicht das richtige. Leider habe ich keine Zeit mich so richtig damit zu beschäftigen. Vielleich ist ja hier noch jemand anderes, der sich damit auskennt.



  • Ich glaube ich werde es jetzt einmal streng nach "Vorschrift" aus dem Entwickler Forum probieren:

    void __fastcall TForm1::SaveImageBtnClick(TObject *Sender) 
    { 
        if (OpenPictureDlg->Execute() == false) return; 
        Table->Active = true; 
        Table->Append(); 
        Table->FieldByName("Name")->AsString = ExtractFileName(OpenPictureDlg->FileName); 
        TBlobField* blobField = dynamic_cast <TBlobField*> (Table->FieldByName("PICTURE")); 
        if (blobField == NULL) return; 
        blobField->LoadFromFile(OpenPictureDlg->FileName); 
        Table->Post(); 
    }
    

    Allerdings weiß ich nicht was "Table" für ein Objekt sein soll 😞
    Was könnte das sein?



  • Clip schrieb:

    Allerdings weiß ich nicht was "Table" für ein Objekt sein soll 😞
    Was könnte das sein?

    Hast Du schon geklärt, ob Dein Problem überhaupt mit dem Blob zusammenhängt?
    Versuch doch erstmal, irgend etwas anderes als ein Blob abzuspeichern ... geht das?



  • Ja, das geht völlig Problemlos.

    Prügel mich gerade mit SQLTable und SQLQuery. Sah erst alles ganz toll aus.
    Dann habe ich bemerkt, dass CanModify von SQLTable immer auf false steht......

    Ich glaub ich geh wieder mir Papierflugzeugen spielen oder so... 😡

    Es muss doch eine Möglichkeit geben Blobs mit dbExpress zu speichern!
    Ich werds weiter probieren!



  • Soooooooo 🕶

    also Blobs aus der DB anzeigen:

    AnsiString SQL1 = "select BLOB from TABLE where BLOBX =";
      AnsiString SQL2 = "select * from BLOBINFO where BLOBX =";
      AnsiString UserName = "username";
      AnsiString Password = "passwort";
      AnsiString DokuX = Edit1->Text;
      AnsiString Path = "c:\\temp\\";
      AnsiString File ="\0";
      AnsiString Query1 = SQL1 + DokuX;
    
      if (SQLComponents == NULL)
      	{
        SQLComponents = new TSQLComponents(NULL);
        }
    
      // Username & Passwort setzten
      SQLComponents->SQLConnection->Params->Values["User_Name"] = UserName.c_str();
      SQLComponents->SQLConnection->Params->Values["Password"] = Password.c_str();
    
      // DateiINfos Auslesen!!
      SQLComponents->SQLClientDataSet->CommandText = Query2.c_str();
      SQLComponents->SQLConnection->Connected = true;
      SQLComponents->SQLClientDataSet->Active = true;
    
      File = SQLComponents->SQLClientDataSet->FieldByName("DATEINAME")->AsString;
    
      File = Path + File;
    
      SQLComponents->SQLConnection->Connected = false;
      SQLComponents->SQLClientDataSet->Active = false;
    
      // Connecten
      SQLComponents->SQLClientDataSet->CommandText = Query1.c_str();
      SQLComponents->SQLConnection->Connected = true;
      SQLComponents->SQLClientDataSet->Active = true;
    
      // Blob wird ausgelesen
      TBlobField* blobField = dynamic_cast <TBlobField*> (SQLComponents->SQLClientDataSet->FieldByName("BLOB"));
      if (blobField == NULL) return;
      blobField->SaveToFile(File);
    
      // disconnect
      SQLComponents->SQLConnection->Connected = false;
      SQLComponents->SQLClientDataSet->Active = false;
    
      // File Anzeigen
      WideString WFile;
      WFile = WideString(File);
      CppWebBrowser1->Navigate(WFile, NULL, NULL, NULL, NULL);
    
      delete SQLComponents;
    

    Blobs in die DB schreiben:

    AnsiString SQL1 = "select * from TABLE where BLOBX =";
      AnsiString DokuX = Edit1->Text;
      const AnsiString BrowserFile = "c:\\temp\\test.pdf";
      AnsiString Query1 = SQL1 + DokuX;
      AnsiString Query2 = SQL2 + DokuX;
      AnsiString UserName = "username";
      AnsiString Password = "passwort";
      // Hilfsvariablen für Locate()
      Variant SearchKey = DokuX;
      TLocateOptions Opts;
    
      //Klasse mit benötigten SQL Komponenten
      if (SQLComponents == NULL)
      	{
        SQLComponents = new TSQLComponents(NULL);
        }
    
      // Username & Passwort setzten
      SQLComponents->SQLConnection->Params->Values["User_Name"] = UserName.c_str();
      SQLComponents->SQLConnection->Params->Values["Password"] = Password.c_str();
    
      // Query setzten
      SQLComponents->SQLClientDataSet->CommandText = Query1.c_str();
    
      // connecten
      SQLComponents->SQLConnection->Connected = true;
      SQLComponents->SQLClientDataSet->Active = true;
    
      // Datensatzt wird ausgewählt
      Opts.Clear();
      Opts << loCaseInsensitive;
      SQLComponents->SQLClientDataSet->Locate("BLOBX", SearchKey, Opts);
    
      // Edit Modus
      SQLComponents->SQLClientDataSet->Edit();
    
      // Blob wird in den selektierten Datensatzt copiert.
      TBlobField* blobField = dynamic_cast <TBlobField*> (SQLComponents->SQLClientDataSet->FieldByName("BLOB"));
      if (blobField == NULL) return;
      blobField->LoadFromFile(BrowserFile);
    
      // Änderungen werden an die DB übertragen
      SQLComponents->SQLClientDataSet->ApplyUpdates(-1);
    
      // disonnect
      SQLComponents->SQLConnection->Connected = false;
      SQLComponents->SQLClientDataSet->Active = false;
    
      delete SQLComponents;
    

    🤡

    @admins, evtl. ist das in gekürzter Form ja was für die die FAQs?



  • Äääh ... und was war letztlich das Problem?



  • Zum laden von Daten reicht scheinbar eine Select Anweisung im CommandText um auf ein bestimmtes Datenfeld zuzugrifen. Dies reicht aber nicht wenn etwas gespeichert werden soll. Daher muss nocheinmal der Datensatz ausgewählt werden.

    Variant SearchKey = DokuX; 
      TLocateOptions Opts; 
      Opts << loCaseInsensitive; 
      SQLComponents->SQLClientDataSet->Locate("BLOBX", SearchKey, Opts);
    

    Das ist eigentlich alles.

    und Vielen Dank für Deine Hilfe noch!!!!!



  • Soviel Aufwand für eine Funktionalität, von deren Anwendung üblicherweise abgeraten wird. 😉

    Wenn du das in der FAQ sehen möchtest solltest du aber auch noch den Code deiner SQLComponents-Klasse dazupacken, damit man das 1:1 nachvollziehen kann.



  • Soviel Aufwand für eine Funktionalität, von deren Anwendung üblicherweise abgeraten wird

    Warum denn?

    Die spezielle Umsetzung die ich jetzt verwendet habe, oder Blobs generell?



  • Generell, weil BLOBs die Datenbank sinnlos aufblähen. Dateien gehören in's Dateisystem, in die DB gehören Links auf die Dateien.



  • Generell stimme ich Dir da zu. Allerdings ist es manchmal notwendig Dateien zu schützen. Und steht genug Datenbanlplatz zur Verfügung ist es halt ein guter weg dies zu tun wenn man sich zusätzlichen administrativen Aufwand sparen will.

    Ich werde die Tage die Einstellungen der verwendeten SQL Komponenten zusammenfassen und den Code noch Exeptionsave machen. Danach poste ich dann alles für die FAQs (ich hätte mich gefreut wenns das schon gegeben hätte, daher wirds sicher noch andere geben. Schaden kann es nicht denke ich).



  • Ich weiß das Thema ist schon ziemlich alt, aber ich muss jetzt auch Dateien in eine Datenbank speichern und wieder auslesen und finde einfach nichts brauchbares im Internet, deswegen wollt ich wissen ob es hier (oder woanders) was neues gibt.

    So long.


Anmelden zum Antworten