| Binäre BLOB Felder Lesen Schreiben SQL - von RGH aus dem Thread [...] .
RGH
Lesen und Schreiben binärerer BLOB-Felder mit XProfanUnd hier das komplette Beispiel mit binären BLOB-Feldern. (Für Blobfelder mit langen Texten müßte es etwas umgeschrieben werden.) Im Beispiel wird eine Bild-Datei als BLOB gespeichert, wieder ausgelesen und auf die Festplatte zurückgeschrieben. (Natürlich können hier beliebige Dateitypen verwandt werden.) KompilierenMarkierenSeparieren
{ ========================================
KONSTANTEN UND API FUNKTIONEN DEFINIEREN
========================================
DEF &SQL_PARAM_INPUT 1
DEF &SQL_SUCCESS 0
DEF &SQL_HANDLE_STMT 3
DEF &SQL_C_DEFAULT 99
DEF &SQL_CHAR 1
DEF &SQL_NUMERIC 2
DEF &SQL_DECIMAL 3
DEF &SQL_INTEGER 4
DEF &SQL_SMALLINT 5
DEF &SQL_FLOAT 6
DEF &SQL_REAL 7
DEF &SQL_DOUBLE 8
DEF &SQL_VARCHAR 12
DEF &SQL_DATE 9
DEF &SQL_TIME 10
DEF &SQL_TIMESTAMP 11
DEF &SQL_LONGVARCHAR -1
DEF &SQL_BINARY -2
DEF &SQL_VARBINARY -3
DEF &SQL_LONGVARBINARY -4
DEF &SQL_BIGINT -5
DEF &SQL_TINYINT -6
DEF &SQL_BIT -7
def SQLAllocHandle(3) !odbc32,SQLAllocHandle
def SQLFreeHandle(2) !odbc32,SQLFreeHandle
def SQLPrepare(3) !odbc32,SQLPrepare
def SQLBindParameter(10) !odbc32,SQLBindParameter
def SQLExecute(1) !odbc32,SQLExecute
def SQLExecDirect(3) !odbc32,SQLExecDirect
def SQLGetData(6) !odbc32,SQLGetData
def SQLFetch(1) !odbc32,SQLFetch
}
================
BLOB-Funktionen:
================
proc SQLPutBlob
parameters Exec$, DATA#
declare stmt&, size&, ret%, error$
SQLAllocHandle(&SQL_HANDLE_STMT, &SQLDBC, addr(stmt&))
size& = SizeOf(Data#)
Ret% = SQLBindParameter(stmt&, 1, &SQL_PARAM_INPUT, &SQL_BINARY, &SQL_LONGVARBINARY,
SizeOf(Data#), 0, Data#, 0, Addr(size&))
If LoWord(Ret%) = &SQL_SUCCESS
Ret% = SQLPrepare(stmt&,addr(Exec$),len(Exec$))
If LoWord(Ret%) = &SQL_SUCCESS
Ret% = SQLExecute(stmt&)
Case LoWord(Ret%) <> &SQL_SUCCESS : Error$ = SQLExecute
Else
error$ = SQLPrepare
EndIf
Else
error$ = SQLBindParameter
EndIf
Case Len(error$) : MessageBox(error$ + fehlgeschlagen!, ODBC-Fehler, 16)
SQLFreeHandle(&SQL_HANDLE_STMT, stmt&)
endproc
proc SQLGetBlob
parameters Exec$
declare Data#, size&, stmt&, ret%, error$
SQLAllocHandle(&SQL_HANDLE_STMT, &SQLDBC, addr(stmt&))
SQLExecDirect(stmt&, addr(Exec$), len(Exec$))
dim Data#, 1 Dummy-DIM zur Größenermittlung
Ret% = SQLFetch(stmt&)
If LoWord(Ret%) = &SQL_SUCCESS
Ret% = SQLGetData(stmt&, 1, &SQL_BINARY, Data#, 0, addr(size&))
if Size& > 0
dim Data#, size&
SQLGetData(stmt&, 1, &SQL_BINARY, Data#, SizeOf(Data#), addr(size&))
endif
Else
error$ = SQLFetch
endif
SQLFreeHandle(&SQL_HANDLE_STMT, stmt&)
Case Len(error$) : MessageBox(error$ + fehlgeschlagen!, ODBC-Fehler, 16)
Return Data#
endproc
=============================
Das eigentliche Testprogramm:
=============================
declare db&, sql$, bild#, sbild$, datei$, startpos&, teil$, teilnr%, ergebnis$, bildnr%
cls
db& = sqlinit(DSN=KursDB;UID=SYSDBA;PWD=masterkey;DBNAME=D:\Dokumente\FireBird\KURSDB.GDB)
If db& > 0
=================
TABELLEN ERZEUGEN
=================
Tabellen löschen, wenn schon vorhanden
Set(Errorlevel,0)
SQLExec DROP TABLE bilderliste,0
SQLExec DROP TABLE bild,0
Set(Errorlevel,1)
Tabelle für die Bilder neu erzeugen
SQLExec CREATE TABLE bilderliste (name CHAR(40), fotograf CHAR(40), bildnr INTEGER, bild BLOB),1
=========================
BILD IN TABELLE SPEICHERN
=========================
Da für eine Bild zwei Schreibvorgänge nötig sind, werden wir diese in eine Transaktion
zusammmenfassen.
Zunächst also die automatische Bestätigung einzelner SQL-Befehle ausschalten. Die folgenden
SQL-Befehle werden also erst mal zwischengespeichert ohne wirklich in die Datenbank zu gehen
sqlexec #AUTOCOMMIT_OFF, 0
Tabelle Bilderliste füllen: Bild 1 hinzufügen, das Bild selbst noch weg lassen
sql$ = INSERT INTO bilderliste VALUES (Helloween Muffins,Jasmin Hülsmann,1,)
sqlexec sql$,0
Nun das Bild in Bild# einlesen
datei$ = HELLOWEEN.JPG
Dim Bild#, FileSize(datei$)
BlockRead(datei$, Bild#, 0, FileSize(datei$))
Und das Bild in die Tabelle einfügen
ACHTUNG: Das SQL-Statement darf nur ein Feld enthalten und zwar das BLOB-Feld (nur INSERT oder UPDATE)
SQLPutBlob(UPDATE bilderliste SET bild = ? WHERE bildnr = 1, Bild#)
Wenn bis hierher alles glatt gegangen ist, konnte alle Felder in den Satz geschrieben
werden. Es erfolgt also die Bestätigung, dass es nun wirklich in die Datenbank kann:
sqlexec #COMMIT, 0
Für die folgenden Befehle benötigen wir die Transaktionskontrolle nicht mehr, so dass
jede SQL-Anweisung automatisch bestätigt werden soll:
sqlexec #AUTOCOMMIT_ON, 0
=========================
BILD AUS TABELLE AUSLESEN
=========================
Ein Bild aus der Tabelle Bilderliste auswählen, dabei das BLOB-Feld bild nicht anzeigen
sql$ = SELECT name, fotograf, bildnr FROM bilderliste
clearlist
sqlexec sql$,1
Überschrift und Trennzeile entfernen
DeleteString(0,0)
DeleteString(0,0)
ergebnis$ = listbox$(Bild auswählen und mit OK bestätigen:,2)
if ergebnis$ >
Die Nummer des gewählten Bildes steht im dritten Feld
bildnr% = Int(Val(SubStr$(ergebnis$,3,|)))
Jetzt das Bild laden
Wir benötigen jetzt nur das BLOB-Feld bild
ACHTUNG: Das SQL-Statement darf nur ein Feld enthalten und zwar das BLOB-Feld (nur SELECT)
sql$ =SELECT bild FROM bilderliste WHERE bildnr = + Str$(bildnr%)
Clear Bild#
Bild# = SQLGetBlob(sql$)
Bild auf Festplatte speichern
blockwrite GelesenesBild.jpg, Bild#, 0, SizeOf(Bild#)
Bild zur Kontrolle anzeigen
DrawSizedPic GelesenesBild.jpg, 0, 0 - 400, 300, 0
EndIf
SQLDone
Else
Print Datenbank konnte nicht geöffnet werden!
Endif
waitinput
end
Ein technischer Hinweis noch: Auch nach der oben erwähnten Korrektur in XProfan wird das Lesen binärer Blobs mit SQLExec nicht direkt möglich sein. Dort ging es um lange Text-Blobs. |
|