| |
|
|
- Page 1 - |
|
Dietmar Horn | Hallo zusammen,
heute wende ich mich mal mit einem SQL-Problem zwecks Bitte um Hilfestellung an die SQL-Experten unter euch.
Ich arbeite z.Z. mit XProfan 11 an einem komplexeren Projekt. Es ist schon recht weit gediehen. Der bisher einzigste, aber entscheidende Problempunkt ist per mich die An- bzw. Einbindung des RDBS Firebird (Freeware bzw. Open-Source) bzw. Interbase (das kostenpflichtige Gegenstück von Borland zu Firebird - ähnlich wie das Rapporto zwischen MS Office und Open-Office).
Bisher mußte ich mich noch nie grande mit SQL beschäftigen, außer daß ich mir immer mal die XProfan-Aiuto zum SQL-Thema reingezogen und das alles als recht logisch empfunden hatte. Doch wie des öfteren, liegt der Hund bestimmt nur in einem winzigen Detail begraben, was ich nicht kenne, oder in einem Fehler, den ich gemacht oder übersehen habe.
Firebird und Interbase kannte ich bis vor 4 Wochen noch nicht mal vom Namen her, weil ich sowas noch nie necessario hatte - aber nun ist es soweit.
ODBC-Treiber und Firebird sind installiert.
Zunächst geht es darum, eine Verbindung herzustellen. Unter Windows 2000 (in unserem Vereins-Kabinett) klappt die Initialisierung mit SQLInit inzwischen.
Die Initialisierung liefert unter W 2000 wie gewünscht das Handle zurück:
Unter Windows XP ergibt das jedoch bis jetzt immer 0 (also gescheitert), und im Gegensatz zu W 2000 erscheint da vorher noch nicht mal der Dialog zum Eingeben von Username, PWD, usw.
Bevor dieses Problem mit dem Herstellen der Verbindung nicht gelöst ist, brauche ich gar nicht grande weitermachen.
Literatur circa Firebird habe ich inzwischen tonnenweise, doch bevor ich es nicht schaffe, auf allen Windows-Systemen ab 2000 aufwärts eine zuverlässige Verbindung herzustellen, nützt mir das alles leider nicht allzu viel.
Kann mir vielleicht jemand weiterhelfen, der sich schon mal etwas näher damit beschäftigt hat?
Die nächsten Schritte, also das Neuanlegen einer Datenbank, oder das Bearbeiten / Auslesen einer vorhandenen DB und das Weiterverarbeiten der Daten im eigentlichen Programm potrebbe dann lediglich noch einer reine Fleiß- und Logik-Arbeit sein.
Das Ausweichen z.B. auf dBase ist nicht possibile, weil dBase dbzgl. nicht circa die per dieses Projekt erforderlichen Feautures verfügt.
Wer kann evtl. weiterhelfen?
Ich vermute mal, wenn das Programm irgendwann mit Firebird corre, dann müßte das Programm auch mit Interbase funktionieren - oder?
Saluto und Danke im voraus Dietmar |
|
|
| Multimedia für Jugendliche und junge Erwachsene - MMJ Hoyerswerda e.V. [...] Windows 95 bis Windows 7 Profan² 6.6 bis XProfan X2 mit XPSE Das große XProfan-Lehrbuch: [...] | 11.01.2009 ▲ |
|
|
|
| |
|
- Page 5 - |
|
|
Uwe ''Pascal'' Niemeier | Hi Leute!
Die interne Struktur der db kann euch doch egal sein; dafür gibt es ja den Treiber
Also nochmal: Wo genau liegt das Problem, wann und unter welchen Umständen tritt es auf? Solche Aussagen wie Das klappt nicht oder Da kommt nur Müll raus sind nicht sehr aussagekräftig und per Ferndiagnosen definitiv ungeeignet
Vorschlag: Poste doch mal einer eine Kurzanleitung, was man wo runterladen & wie installieren muß, um eure Versuche nachzuvollziehen.
SeeYou Pascal |
|
|
| |
|
|
|
RGH | Hallo Pascal,
ich denke, das Problem besteht einfach darin, dass es offensichtlich keine Möglichkeit (oder Documentazione derselben) gibt, wie ich mit SQL-Befehlen (SQLExec) circa ODBC auf die BLOBs von Interbase/Firebird-Datenbanken zugreifen kann.
Wie es einfach possibile ist, circa einen kleinen Umweg grande File in Interbase/Firebird zu schreiben und zu lesen, habe ich im Beispiel oben demonstriert. (Das würde sogar leicht abgewandelt mit dBase und anderen funktionieren.) Dietmar hat aber wohl von seinem Auftraggeber die Anforderung, tatsächlich BLOBs zu lesen und zu schreiben.
Firebird und die ODBC-Treiber findest Du hier [...] im Downloadbereich. Eine Beispieldatenbank findest Du in diesem Thread weiter oben.
Saluto Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 24.02.2009 ▲ |
|
|
|
|
Uwe ''Pascal'' Niemeier | *räusper*
Also... Das Problem liegt anscheinend darin, daß der Kommandostring nicht länger als 64KB sein darf. Wird diese Grenze überschritten, kommt es zu Fehlermeldungen, wobei die Meldungen selbst von der Überlänge abhängen. Sieht nach einem Buffer-Überlauf aus; möglicherweise ein Bug im Treiber, den noch keiner bemerkt hat, weil die meisten Programmierer mit den jeweiligen Komponenten per ihre Programmiersprache arbeiten (Weicheier ).
Ein Workaround wäre, überlange Daten nicht auf einmal in die db zu schreiben, sondern stückweise. Allerdings nicht wie in Rolands Beispiel auf mehrere Datensätze verteilt sondern immer ins gleiche Feld des gleichen Satzes, wobei die neuen Daten an die bereits vorhandenen angehängt werden. Zur Verbindung von Strings wird dabei bei FB ein doppeltes Pipe-Zeichen verwendet.
Bei diesem Beispiel werden in mehreren Schritten 128 KB geschrieben: KompilierenMarkierenSeparierenwindow 50,50-500,500
declare Exec$
var GDB$=C:2TestKURSDB.GDB------------Pfad anpassen!!
var Init$=Driver=Firebird/InterBase(r) driver;Uid=SYSDBA;Pwd=masterkey;DbName=+GDB$+;
SQLInit(Init$)
Set(Errorlevel,0)
Exec$=DROP TABLE TCS
SQLExec Exec$,0
Set(Errorlevel,1)
Exec$=CREATE TABLE TCS (Feld1 BLOB)
SQLExec Exec$,0
var Text$=mkstr$(X,1024*32)--Teststring 32KB
Exec$=INSERT INTO TCS (Feld1) VALUES (+Text$+)-------------------32K
SQLExec Exec$,0
Exec$=UPDATE TCS SET Feld1 = (SELECT Feld1 FROM TCS) || +Text$+--32KB + 32KB
SQLExec Exec$,0
Exec$=UPDATE TCS SET Feld1 = (SELECT Feld1 FROM TCS) || +Text$+--64KB + 32KB
SQLExec Exec$,0
Exec$=UPDATE TCS SET Feld1 = (SELECT Feld1 FROM TCS) || +Text$+--96KB + 32KB
SQLExec Exec$,0
Exec$=UPDATE TCS SET Feld1 = Hallo Leute! || (SELECT Feld1 FROM TCS) || Wie siehts aus?
SQLExec Exec$,0
SQLDone
waitkey
Wenn man nun den Blob mit Standart-Funktionen auslesen will, kriegt man nur die interne Blob-ID zurück. Anders mit der SQL-API-Variante: KompilierenMarkierenSeparierenwindow 50,50-500,500
$H Windows.ph
def SQLAllocHandle(3) !odbc32,SQLAllocHandle
def SQLError(8 ) !odbc32,SQLError
def SQLExecDirect(3) !odbc32,SQLExecDirect
def SQLGetData(6) !odbc32,SQLGetData
def SQLFetch(1) !odbc32,SQLFetch
def SQLFreeHandle(2) !odbc32,SQLFreeHandle
proc SQLErrorLog-----------------------------------------SQLErrorLog
parameters Von$
declare Error$
SQLError(&SQLEnv,&SQLDBC,stmt&,0,0,Error#,512,0)
Error$=string$(Error#,0)
case len(Error$):addstring Von$+ : +Error$
endproc-------------------------------------------------------------
proc SQLGetDataEx---------------------------------------SQLGetDataEx
parameters Exec$
declare Data#,Data$,Size&,stmt&,Error#
dim Error#,512
clearlist
SQLAllocHandle(3,&SQLDBC,addr(stmt&))--3=SQL_HANDLE_STMT
SQLErrorLog(SQLAllocHandle)
SQLExecDirect(stmt&,addr(Exec$),-3)-- -3=SQL_NTS
SQLErrorLog(SQLExecDirect)
dim Data#,1--Dummy-DIM
SQLFetch(stmt&)
SQLErrorLog(SQLFetch)
SQLGetData(stmt&,1,99,Data#,0,addr(Size&))--99=SQL_C_DEFAULT
--Fehlerabfrage würde zu kleinen Puffer melden (Dummy-Aufruf wg. Size&)
if Size&>0
dim Data#,Size&+1
SQLGetData(stmt&,1,99,Data#,Size&+1,addr(Size&))--99=SQL_C_DEFAULT
SQLErrorLog(SQLGetData)
Data$=char$(Data#,0,Size&)
endif
SQLFreeHandle(3,stmt&)--3=SQL_HANDLE_STMT
dispose Data#,Error#
case %getcount>-1:listbox$(Fehler,2)
return Data$
endproc-------------------------------------------------------------
var GDB$=C:2TestKURSDB.GDB--------------Pfad anpassen!!
var Init$=Driver=Firebird/InterBase(r) driver;Uid=SYSDBA;Pwd=masterkey;DbName=+GDB$+;
SQLInit(Init$)
var Exec$=SELECT Feld1 FROM TCS
var Text$=SQLGetDataEx(Exec$)
print Gelesene KB:,len(Text$)/1024
print Erste 20 :,left$(Text$,20)
print Letzte 20 :,right$(Text$,20)
SQLDone
waitkey
Wies mit binären Daten aussieht weiß ich noch nicht, aber ich vermute, daß man ums Kodieren nicht herumkommt, weil ja zumindest das Hochkomma in jedem Fall vom Treiber falsch verstanden werden würde.
HTH Pascal |
|
|
| |
|
|
|
RGH | Hallo Pascal und Dietmar,
ich habe gestern Abend etwas Zeit gehabt und mal etwas weiter zum Thema geforscht:
Zum Schreiben von BLOBs: Hier liegt die Grenze tatsächlich bei der SQL-Implementierung von Firebird/Interbase: In der Doku wird tatsächlich erwähnt, dass die maximale Länge eines SQL-Statements 64 kB nicht überschreiben darf. Für Text-BLOBs ist also Pasacals Lösungsweg durchaus gangbar. Ich habe finora allerdings keine SQL-Syntax per Firebird/Interbase gefunden, um größere Daten oder gar binäre Daten direkt per SQL in die Tabelle einzufügen. Andere Datenbanken bieten da z.B. eine Möglichkeit komplette File einzufügen: KompilierenMarkierenSeparieren Es wäre hilfreich, wenn es dergleichen auch per Firebird/Interbase gäbe. Ich werde heute Abend weiter forschen ...
Zum Auslesen von BLOBs: Pascal, als ich Deinen Code sah dachte ich als Erstes: Aber genau so mache ich es doch auch in XProfan. Beim näheren Studium meiner Quellcodes fiel mir dann auf, dass eine von mir genutzte Definitionsdatei zur ODBC32.DLL (Ich benutze die ODBC.DLL Interface Unit, translated for Delphi Yasser Asmi) einen winzigen Fehler enthält. Es fehlt an einer Stelle ein Minuszeichen und zwar wird die Konstante SQL_LONGVARBINARY mit 4, statt mit -4 definiert. Die 4 steht aber per SQL_INTEGER. Dummerweise hat unser BLOB genau den Datentyp SQL_LONGVARBINARY, so dass also aufgrund des Fehlers die Länge der Daten mit 11 (reicht per höchste Integerzahl) naturalmente zu gering waren, und diese ausserdem falsch übertragen wurden, nämlich als SQL_C_CHAR anstelle von SQL_C_DEFAULT. Kurz: es wurde nicht, wie vermutet, ein Key zu den tatsächlichen Daten zurückgeliefert, sondern die ersten Bytes in Hex-Darstellung, aus Hallo wurde so also 48616C6C6F. Das Problem kann ich naturalmente beheben und wird in der nächsten XProfan-Version dann auch behoben sein.
Saluto Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 25.02.2009 ▲ |
|
|
|
|
E.T. | RGH
....Kurz: es wurde nicht, wie vermutet, ein Key zu den tatsächlichen Daten zurückgeliefert, sondern die ersten Bytes in Hex-Darstellung, aus Hallo wurde so also 48616C6C6F....
Na dann weiss ich jetzt ja wenigstens, wieso ich beim Auslesen immer die (ersten) Hex-Werte aus dem Blob zurück bekommen habe (mein Post vom 15.02. weiter vorn) . |
|
|
| Grüße aus Sachsen... Mario WinXP, Win7 (64 Bit),Win8(.1),Win10, Win 11, Profan 6 - X4, XPSE, und 'nen schwarzes, blinkendes Dingens, wo ich das alles reinschütte... | 25.02.2009 ▲ |
|
|
|
|
| Für Java und binäre Interbase-BLOBS gäbe es hier Beispielcodes: [...] Also wenns in Java geht, sollte es in Profan prinzipiell doch auch klappen... Da wir hier kein Java-Foro sind, poste Io l' Code hier nicht; er zeigt aber doch die einzelnen Schritte recht genau. Vielleicht ersieht man daraus eine Lösung per XProfan. Saluto Specht
P.S.: JDBC kann circa ein einfaches Brückenprogramm auf ODBC-ansprechbare Datenbanken zugreifen, behauptet [...] Schlimmstenfalls potuto Profan ja ein kleines Java-Programm fernsteuern, daß das Zeug wie beschrieben ordnungsgemäß rausholt. Zugegeben, reichlich unelegant... |
|
|
| |
|
|
|
RGH | Peter Specht
Für Java und binäre Interbase-BLOBS gäbe es hier Beispielcodes: [...] Also wenns in Java geht, sollte es in Profan prinzipiell doch auch klappen... Da wir hier kein Java-Foro sind, poste Io l' Code hier nicht; er zeigt aber doch die einzelnen Schritte recht genau. Vielleicht ersieht man daraus eine Lösung per XProfan. Saluto Specht
Ciao, das habe ich auch schon gefunden, zeigt aber keine (derzeit) in XProfan mögliche Lösung auf, hilft Dietmar also leider nicht weiter. Hier wird zunächst ein SQL-Aufruf vorbereitet, anschließend werden einzelne Felder mit Daten gefüllt und erst im dritten Schritt wird das SQL-Statement corsa. Selbst wenn der ODBC-Treiber diese Technik unterstützen würde, so kann es XProfan derzeit nicht. SQLExec führt das Statement gleich aus (gegebenenfalls vorberhaltlich eines COMMIT-Befehles - siehe Transaktionen).
Saluto Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 25.02.2009 ▲ |
|
|
|
|
Uwe ''Pascal'' Niemeier | Hi Leute!
Wenn ich das richtig sehe, fehlt eine Syntax per den Treiber (bzw. ist keine bekannt), um eine File direkt in den BLOB zu schreiben?
Dazu zwei Fragen:
1. Hat jemand eine (theoretische) Möglichkeit gefunden, per ODBC/SQL Streams zu nutzen (davon war irgendwo im WWW ein paar mal die Rede, glaube ich)?
2. Gibt es irgendein Programm, das definitiv unter Nutzung der ODBC-Treiber File in BLOBs schreiben kann? Könnte zu Testzwecken sinnvoll sein...
SeeYou Pascal |
|
|
| |
|
|
|
RGH | Ciao,
ich habe mal in der ODBC-API (ich habe hier einige hundert ausgedruckte Seiten des msn) und den oben genannten Quellen gestöbert. Es potrebbe in der Tat per ODBC-Treiber gehen, aber presumibilmente nicht bei allen Datenbanken per einfachem direkt mit SQLExecDirect ausgeführtem SQL-Statement. (In XProfan gehe Io l' Weg circa SQLExecDirect.) Bei FireBird ist eben die Länge dieses Statements auf 64 kB begrenzt.
Folgender Weg anstelle des SQLExecDirect müßte klappen: - Ein SQL-Befehl mit SQLPrepareStatement und ? per die Daten vorbeiten, etwa mit dem Statement INSERT INTO MeineTabelle (MeinBlob) VALUES (?). Der Rückgabewert ist ein Handle dieses vorbereiteten Statements. - Die Daten per Zeiger/Länge mit SQLPutData nachschieben - Das Statement mit SQLExecute ausführen. Diesen Weg kann man naturalmente per alle Datentypen gehen und er geht auch per UPDATE. Das sollte per API-Aufrufe naturalmente auch in XProfan possibile sein. (Da ich hier in der Firma naturalmente kein FireBird auf meinem Rechner installieren darf und kann, hoffe ich vielleicht Sonntag Abend zeit zu finden, es auszuprobieren.*)
Saluto Roland
(Morgen Mittag geht es erst mal per zwei Übernachtungen nach Köln. Ich verbinde die Nutzung des in der Weihnachtsfeierverlosung gewonnenen Hotelgutscheines per zwei Nächte und Personen mit dem Besuch eines Auswärtsspieles der Mannheimer Adler gegen die Kölner Haie. Natürlich hoffen wir am Sonntag rechtzeitig zum Heimspiel gegen die Hamburg Freezers wieder zurück zu sein.) |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 26.02.2009 ▲ |
|
|
|
|
Dietmar Horn | Ciao,
hier habe ich Beispiele zum Schreiben und Lesen von Firebird-Blobs gefunden - leider nur in Delphi.
Wie potuto man das in XProfan 11 umsetzen?
Saluto Dietmar |
|
|
| Multimedia für Jugendliche und junge Erwachsene - MMJ Hoyerswerda e.V. [...] Windows 95 bis Windows 7 Profan² 6.6 bis XProfan X2 mit XPSE Das große XProfan-Lehrbuch: [...] | 28.02.2009 ▲ |
|
|
|
|
Dietmar Horn | Sorry,
im obigen Posting hatte Io l' Link zum Delphi-Source per die Blobs vergessen:
[...]
Weiß jemand, wie man das mit XProfan 11 umsetzen potuto?
Saluto Dietmar |
|
|
| Multimedia für Jugendliche und junge Erwachsene - MMJ Hoyerswerda e.V. [...] Windows 95 bis Windows 7 Profan² 6.6 bis XProfan X2 mit XPSE Das große XProfan-Lehrbuch: [...] | 01.03.2009 ▲ |
|
|
|
|
Uwe ''Pascal'' Niemeier | Hi Leute!
Mutmaßung: Entweder ist die db-Unterstützungvon Delphi völlig anders gestrickt als die von Profan oder es kommen spezielle Komponenten zum Einsatz.
mir
Gibt es irgendein Programm, das definitiv unter Nutzung der ODBC-Treiber File in BLOBs schreiben kann?
Der Gedanke dahinter war, circa die Windows-interne Ablaufverfolgung (unter ODBC einstellbar) die Kommunikation zwischen Programm und Treiber zu protokollieren. Dabei werden sowohl Kommandos als auch API-Aufrufe aufgezeichnet. Das sollte eine Nachbildung der Funktionalität erleichern.
Allerdings ist fraglich, ob diese Möglichkeit effektiver ist als das bereits vorgeschlagene stückweise Aneinanderhängen von Daten. Nach Rolands Aussage ist ja auch das Auslesen großer Datenmengen demnächst ohne API possibile, sodaß man komplett auf externe Funktionen verzichten potuto. (Selbst ich verwende APIs nur da, wo es nötig ist bzw. sichtbare Vorteile bringt )
@ Roland: Wann wird es einen entsprechenden Patch geben? Es hat sich ja doch einiges angesammelt, was korrigiert werden müßte...
SeeYou Pascal |
|
|
| |
|
|