Entwickler-Ecke

Datenbanken - Firebird und BLOB-Felder


Anateus - Mi 09.02.11 20:04
Titel: Firebird und BLOB-Felder
Hallo,
ich habe eine Firebird-Datenbank Version 2.0, arbeite mit Delphi 7 und dbExpress.

Ich möchte in der Firbird-Tabelle


SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
/* Bilder, Dokumente und Memos (Telefonnotizen)                      ==>050622 */
CREATE TABLE BILDMEM
 (GUID bigint NOT NULL,                   /* ID-Nummer (forlaufend)           */
  FIRM SMALLINT,                          /* Mandant-Nummer                   */
  NUMMER VARCHAR(20),                     /* Adressen-Nummer                  */
  ADRNUMMER VARCHAR(20),                  /* Adressen-Nummer2                 */
  STATUS INTEGER NOT NULL,                /* 1=Kunde 2=Lieferant 3=Vertreter 4=Sonstiges */
  SBEGRIFF1 VARCHAR(80),                  /* Suchbegriff 1                    */
  SBEGRIFF2 VARCHAR(80),                  /* Suchbegriff 2                    */
  SBEGRIFF3 VARCHAR(80),                  /* Suchbegriff 3                    */
  LISTE VARCHAR(20),                      /* Listenbezeichnung z.B. LIS0001   */
  ART VARCHAR(10),                        /* Anwendungskurzzeichen z.B.DOC,XLS*/
  ANWEND VARCHAR(50),                     /* Anwendung z.B. MS Word           */
  BETREFF VARCHAR(80),                    /* Betreffszeile Geschäftsbrief     */
  VNAME VARCHAR(50),                      /* Vorlage-Name                     */
  ABTEILUNG VARCHAR(20),                  /* Abteilung                        */
  VERSION VARCHAR(20),                    /* Versions-Nummer der Vorlage      */
  DART VARCHAR(2NOT NULL,               /* DokArt M=Memo, B=Binär           */
  TEXT BLOB,                              /* Memo-Text                        */
  BILD BLOB sub_type binary,              /* Bild                             */
  bmdaed integer,                         /* Satz-Änderungs-Datum             */
  bmaeui VARCHAR(20),                     /* Änderung durch Benutzer          */
  bmaeuz integer,                         /* Änderung Uhrzeit                 */
  bmdand integer,                         /* Satz-Anlagedatum                 */
  bmanui VARCHAR(20),                     /* Anlage durch Benutzer            */
  bmanuz integer,                         /* Anlage Uhrzeit                   */
PRIMARY KEY(GUID));

in dem Tabellenfeld "BILD" eine PDF-Datei hinterlegen, wie folgt:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
// Datenbankfelder werden versorgt
function TLiefer.DB_Versorgen_Doku : Boolean;
var erfolg : Boolean;
    MyPDF  : TFileStream;
    BelegArtBezeichnung : TCaption;
    AuftragsBereich : TCaption;
begin
  try
   Result := false;
   MyPDF:=TFileStream.Create('c:\temp\beleg.pdf', fmOpenRead);
   MyPDF.Position:=0;
   erfolg := Beleg_Art(AuftragsArt, BelegArtBezeichnung);
   erfolg := Beleg_Bereich(AuftragsArt, AuftragsBereich);
   with DM101.IBILDMEM do
   begin
      Params[0].asInteger  := DM001.getNextBildMemNumber;
      Params[1].asInteger  := Mandant;
      Params[2].asString   := ' ';
      Params[3].asString   := ' ';
      Params[4].asInteger  := 4;
      Params[5].asString   := BelegArtBezeichnung;
      Params[6].asString   := BNr.Text;
      Params[7].asString   := DateToStr8(BDatum);
      Params[8].asString   := BelegArtBezeichnung;
      Params[9].asString   := 'PDF';
      Params[10].asString  := 'Acrobat Reader';
      Params[11].asString  := ' ';
      Params[12].asString  := UpperCase(BelegArtBezeichnung);
      Params[13].asString  := Auftragsbereich;
      Params[14].asString  := '1';
      Params[15].asString  := 'B';
      Params[16].asString  := ' ';                         // Memo wird hier nicht geladen
      ParamByName('BILD').LoadFromStream(MyPDF,ftBlob);
      Params[18].asInteger := 0;
      Params[19].asString  := ' ';
      Params[20].asInteger := 0;
      Params[21].asInteger := Datum_DB(DateToStr8(BDatum));
      Params[22].asString  := Usernr;
      Params[23].asInteger := Time_DB(TimeToStr(Now));
   end;
   Result := true;
  finally
   MyPDF.free;
  end
end;

function TLiefer.SpeicherRechnung : Boolean;
var
    TD : TTransactionDesc;
begin
     // Der Ausdruck wird nun in der BILDMEM-Datenbank gespeichert
     TD.TransactionID := getNextTransactionID;
     TD.IsolationLevel := xilREADCOMMITTED;
     DM101.SQLConnection1.StartTransaction(TD);
    try
     // Dokument speichern
     erfolg := DB_Versorgen_Doku;
     DM101.IBILDMEM.ExecSQL;

     // Durch die Commit-Steuerung werden die Änderungen in der DB resistend
     DM101.SQLConnection1.Commit(TD);
     Result := True;
    except
     // Fehler aufgetreten - es erfolgen keine Änderungen in der DB
     DM101.SQLConnection1.Rollback(TD);
     MessageDlg('Datei zu groß oder fehlende Angaben', mtInformation, [mbOk], 0);
     Result := False;
    end;

   Result := true
  end
end;


Es erscheint dann folgende Fehlermeldung:
"Im Projekt WWS.exe ist eine Exception der Klasse EDatabasError aufgetreten. Meldung: 'feature is not supported BLOB and array data types are not supported for move operation'. Prozess wurde angehalten."

Kann mir jemand weiterhelfen, wie ich eine PDF ordentlich in eine Firebird-Tabelle hineinbekomme?

Gruß
Anateus

Moderiert von user profile iconNarses: Code- durch Delphi-Tags ersetzt


Nersgatt - Do 10.02.11 09:05

Moin,

ich speicher u.A. Bilder in BLOB-Feldern. Das sieht dann so aus:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure TMySQLQuery.SetBlobParameterValue(AParamName: String;
  AValue: TPersistent);
begin
  if (AValue = nilthen
  begin
    self.ParamByName(AParamName).Clear;
    self.ParamByName(AParamName).DataType := ftBlob;
    self.ParamByName(AParamName).Bound := True;
  end
  else
  begin
    self.ParamByName(AParamName).Assign(AValue);
  end;

end;

Aufgerufen sieht es dann so aus:

Delphi-Quelltext
1:
q.SetBlobParameterValue('BILD', imgHelfer.Picture);                    


Andersrum siehts dann so aus:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
        pic := TPicture.Create;
        try
          pic.Assign(q.FieldByName('BILD'as TBlobField);
          imgHelfer.Picture := pic;
        finally
          pic.Free;
        end;


Anateus - Do 10.02.11 15:41

Danke für Deine Antwort.

Ich habe aber das Problem, ob ich das BLOB-Feld zur Aufnahme von PDF-Dateien richtig im "Create Table" der Firebird-Datenbank richtig definiert habe und dann auch wiederum richtig versorge.

Gruß
Anateus


haentschman - Sa 16.04.11 19:19

Crosspost:
http://forum.delphi-treff.de/showthread.php?30358-Firebird-und-BLOB-Felder


hansa - So 17.04.11 01:54

Da gibts ja noch prinzipielle Überlegungen. Z.B.: wie oft werden diese PDF-Dateien geändert ? Die brauchen sehr viel Platz, zumindest im Verhältnis zu integer + Co. Die DB selbst wird sich schon oft ändern. Da stellt sich aber die Frage, ob es sinnvoll ist diese PDFs in der DB zu speichern, denn Alternative wäre, das schon in Dateien zu lassen und nur den Dateinamen in der DB zu speichern.


Anateus - Di 17.05.11 07:19

Hallo,

ich habe es jetzt rausbekommen. Es lag doch an der Zuweisung von Parametern, die
ich mit "asBLOB" (z.B. Params[16].asBlob) zuweisen musste und dann hatte ich
Params[16] nicht nochmal angegeben, weil ich das gleich mit "ParamByName"
befüllen wollte.
Hier nochmal die richtigen Zuweisungen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
// Datenbankfelder werden versorgt
function TLiefer.DB_Versorgen_Doku : Boolean;
var erfolg : Boolean;
    MyPDF  : TFileStream;
    BelegArtBezeichnung : TCaption;
    AuftragsBereich : TCaption;
begin
  try
   Result := false;
   MyPDF:=TFileStream.Create('c:\temp\beleg.pdf', fmOpenRead);
   MyPDF.Position:=0;
   erfolg := Beleg_Art(IAuftragsArt, BelegArtBezeichnung);
   erfolg := Beleg_Bereich(IAuftragsArt, AuftragsBereich);
   with DM101.IBILDMEM do
   begin
      Params[00].asInteger  := Mandant;
      Params[01].asString   := ' ';
      Params[02].asString   := ' ';
      Params[03].asInteger  := 4;
      Params[04].asString   := BelegArtBezeichnung;
      Params[05].asString   := BNr.Text;
      Params[06].asString   := DateToStr8(BDatum);
      Params[07].asString   := BelegArtBezeichnung;
      Params[08].asString   := 'PDF';
      Params[09].asString  := 'Acrobat Reader';
      Params[10].asString  := ' ';
      Params[11].asString  := UpperCase(BelegArtBezeichnung);
      Params[12].asString  := Auftragsbereich;
      Params[13].asString  := '1';
      Params[14].asString  := 'B';
      Params[15].asBlob  := '';                         // Memo wird hier nicht geladen
      Params[16].asBlob  := '';                         // PDF-Dokuemnt
      ParamByName('BILD').LoadFromStream(MyPDF,ftBlob);
      Params[17].asInteger := 0;
      Params[18].asString  := ' ';
      Params[19].asInteger := 0;
      Params[20].asInteger := Datum_DB(DateToStr8(BDatum));
      Params[21].asString  := Usernr;
      Params[22].asInteger := Time_DB(TimeToStr(Now));
   end;
   Result := true;
  finally
   MyPDF.free;
  end
end;


Ich danke Euch allen für Eure Hilfe.
Gruß
Anateus