Anfängerfrage: Mehrere SQL-Befehle nacheinander ausführen

Datenbanklösungen mit AOO/LO

Moderator: Moderatoren

Benutzeravatar
lorbass
********
Beiträge: 4116
Registriert: Mo, 01.05.2006 21:29
Wohnort: Bonn

Re: Anfängerfrage: Mehrere SQL-Befehle nacheinander ausführe

Beitrag von lorbass »

Vielleicht hilft dir das Base-Handbuch Entwurf einer Beispieldatenbank beim Einstieg. Weitere Base-Handbücher sowie die Dokumentation zu allen anderen OOo-Modulen findest du im Dokumentationsportal.

Gruß
lorbass
RobertG
********
Beiträge: 2069
Registriert: Fr, 13.04.2012 19:28
Kontaktdaten:

Re: Anfängerfrage: Mehrere SQL-Befehle nacheinander ausführe

Beitrag von RobertG »

Hallo Parcival,
Parcival hat geschrieben:Wie kann ich in Openoffice Base mehrere SQL-Befehle (quasi wie Programmcode) nacheinander ausführen lassen? Z.B.: Erst Daten einlesen aus CSV-Datei (geht glaub ich schonmal nicht), dann bestimmte Datentypen ändern, dann neue Variable einführen, dann Select auf die "aufbereitete" Datenbank.
Datein aus einer CSV-Datei einlesen geht per SQL-Code in die eingebaute HSQLDB schon einmal nicht. Es steht kein Kommando wie z.B. unter MySQL (LOAD DATA INFILE) zur Verfügung. Die Daten musst Du also anderweitig aufbereieten.
Parcival hat geschrieben: Wenn ich z.B. versuche, eine Abfrage in der SQL-Ansicht mit mehreren SQL-Befehlen zu erstellen, erhalte ich einen Syntax Error. Auch scheint Base in der Abfage bestimmte SQL-Befehle wie ALTER TABLE nicht zu erkennen.
Eigentlich sagt das schon der Begriff, der dort erwartet wird: Über diese Schnittstelle gehen nur Abfragen, also SELECT, aber kein INPUT oder UPDATE und noch viel weniger Tabellenänderungen.
Parcival hat geschrieben: Ich weiß, ich könnte die Befehle auch sequenziell unter Extras -> SQL eingeben, aber das kann doch keine Lösung sein für Datenbanken, die ich immer wieder neu einlesen und aufbereiten muss.
Du kannst natürlich unter Extras - SQL verschiedenen Kommandos hintereinander mit einem Semikolon auf einmal eingeben. Das ist für mich z.B. eine Lösung, wenn ich Beispieldatenbanken wieder auf zurück auf die Startposition mit Autoinkrementwerten ab 0 setzen will. Dann habe ich eine einfache Textdatei, die ich kopiere und in Extras → SQL einfüge.
Für das, was Du erreichen willst, musst Du Dich mit Makros auseinandersetzen. Dafür reicht die grafische Benutzeroberfläche so nicht aus.
Ich empfehle Dir als Einstieg einmal bei den LibreOffice- Handbüchern (http://de.libreoffice.org/hilfe-kontakt/handbuecher/ zu gucken. Da gibt es in dem Base-Handbuch ein Kapitel zu Makros, das zumindest den Einstieg klar macht und auch den Zugriff mittels SQL-Befehlen auf die Datenbank klärt. CSV-Dateien musst Du natürlich über Makros dann einlesen und entsprechend aufbereiten, damit die Daten zeilenweise eingelesen werden können. Einfacher wäre es da sicher, eine Datenbank zu nutzen, die so eine Funktion eingebaut hat - wie z.B. MySQL.

Gruß

Robert
RobertG
********
Beiträge: 2069
Registriert: Fr, 13.04.2012 19:28
Kontaktdaten:

Re: Anfängerfrage: Mehrere SQL-Befehle nacheinander ausführe

Beitrag von RobertG »

Hallo Parcival,

Harald hat ja bereits einen entprechenden Link weiter gegeben, wie es auch mit dem Import von *.csv-Dateien klappen kann. Da dürfte es dann auch nicht mehr so weit sein, das über Makros entsprechend geregelt zu bekommen.

Ich nutze hier Linux - MySQL gehört bei mir neben Apache und PHP zur Standardinstallation, weil ich Datenbanken über PHP ansteuere.
MySQL ist aber auf jeden Fall eine Serverdatenbank, aber auch nutzbar ohne PHP und Apache - eben kein kleines Tool.
Was vielleicht eine kleiner Lösung wäre: Die aktuelle HSQLDB in der Version 2.2.x. Mit einem Blick auf die Beschreibung sehe ich, dass "... a HyperSQL database may link to any formatted
text files, such as CSV lists, anywhere on the disk." Mit der neuen Version habe ich allerdings noch nicht weiter gearbeitet. Es reicht bei der HSQLDB aber aus, die hsqldb.jar irgendwo in den classpath zu legen - du musst keinen Server installieren.

Gruß

Robert
RobertG
********
Beiträge: 2069
Registriert: Fr, 13.04.2012 19:28
Kontaktdaten:

Re: Anfängerfrage: Mehrere SQL-Befehle nacheinander ausführe

Beitrag von RobertG »

Hallo Parcival,

ich habe den Link mal verfolgt, den Code etwas überarbeitet, so dass er für mich in einem Formular läuft:

Code: Alles auswählen

SUB CSV_Import
	DIM oDatenquelle AS OBJECT
	DIM oVerbindung AS OBJECT
	DIM oSql_Anweisung AS OBJECT
	DIM oDoc AS OBJECT
	DIM oDrawpage AS OBJECT
	DIM oForm AS OBJECT
	DIM oFeld AS OBJECT
	DIM stFeld AS STRING
	DIM stDaten AS STRING
	DIM inNumber AS INTEGER
	REM Der Kontakt zur Datenbank wird gegebenenfalls hergestellt
	oDatenquelle = ThisComponent.Parent.CurrentController
	If NOT (oDatenquelle.isConnected()) THEN
		oDatenquelle.connect()
	END IF
	REM Die Eingabe einer SQL-Anweisung wird vorbereitet
	oVerbindung = oDatenquelle.ActiveConnection()
	oSQL_Anweisung = oVerbindung.createStatement()
	REM Das Formular wird aufgesucht
	oDoc=thisComponent
	oDrawpage=oDoc.Drawpage
	REM Lage des Feldes in dem entsprechenden Formular aufsuchen
	oForm=oDrawpage.Forms.getByName("Formular")
	oFeld=oForm.getByName("Dateiauswahl")
	REM Den Text aus der Dateiauswahl auslesen
	stFeld=oFeld.Text
    inNumber = FreeFile()	'die nächste freie Dateinummer wird ermittelt und anschließend genutzt
    OPEN stFeld FOR INPUT AS inNumber
    	WHILE NOT EOF(#inNumber)	'solange das Ende der Datei nicht erreicht ist, wird jetzt jede Zeile ausgelesen
    		LINE INPUT #inNumber, stDaten
			aDaten() = Split(stDaten, ",")	'Alle Daten einer Zeile werden ausgelesen. Das erste Feld wird mit aDaten(0) ausgelesen.
			REM Die Daten einer Zeile werden in die Tabelle übertragen
'   	 	oSQL_Anweisung.executeUpdate("INSERT INTO ""Tabelle""(""Spalte1"",""Spalte2"") VALUES('" + aDaten(0) + "','" + aDaten(1) + "')"
    	WEND
    CLOSE #inNumber
END SUB
Die SQL-Anweisung habe ich erst einmal als Kommentar gesetzt.
Das Makro läuft aus einem Formular heraus, in dem ein Dateieingabefeld liegt. Die Namen der beiden Felder siehst Du im Makro. Die *.csv-Datei wird ausgewählt und eingelesen. Habe ich mir mit msgbox aDaten(1) anzeigen lassen. Folgender Fehler ist jetzt nicht abgefangen: Existieren nicht genug Einträge in der CSV-Datei, so werden eventuell mehr Indizes eines Arrays aufgerufen als vorhanden sind. Da sollte vorher ein Test hin mit Ubound(aDaten) - dann wird die oberere Begrenzung ausgelesen, die auf jeden Fall durch den SQL-Befehl abgedeckt sein muss. Angenommen Du hast 10 Datenspalten, so muss Ubound(aDaten) '9' ergeben, da aDaten(9) die letzte Spalte bedient.

Gruß

Robert
RobertG
********
Beiträge: 2069
Registriert: Fr, 13.04.2012 19:28
Kontaktdaten:

Re: Anfängerfrage: Mehrere SQL-Befehle nacheinander ausführe

Beitrag von RobertG »

Ich lege einmal noch etwas drauf.
Die vorher beschriebene Prozedur verarbeitet nämlich +.csv-Dateien nicht sauber, sobald ein Komma in einem Text vorkommt. Außerdem lässt sie die Anführungszeichen stehen.
Auch die Überprüfung, ob die *.csv-Datei genug Felder hat, fand bisher nicht statt. Hier der erweiterte Code:

Code: Alles auswählen

SUB CSV_Import
	DIM oDatenquelle AS OBJECT
	DIM oVerbindung AS OBJECT
	DIM oSql_Anweisung AS OBJECT
	DIM oDoc AS OBJECT
	DIM oDrawpage AS OBJECT
	DIM oForm AS OBJECT
	DIM oFeld AS OBJECT
	DIM stFeld AS STRING
	DIM stDaten AS STRING
	DIM stSql AS STRING
	DIM inNumber AS INTEGER
	DIM inZaehler AS INTEGER
'	Tabelle_leeren("Tabelle1")
	REM Der Kontakt zur Datenbank wird gegebenenfalls hergestellt
	oDatenquelle = ThisComponent.Parent.CurrentController
	If NOT (oDatenquelle.isConnected()) THEN
		oDatenquelle.connect()
	END IF
	REM Die Eingabe einer SQL-Anweisung wird vorbereitet
	oVerbindung = oDatenquelle.ActiveConnection()
	oSQL_Anweisung = oVerbindung.createStatement()
	REM Das Formular wird aufgesucht
	oDoc=thisComponent
	oDrawpage=oDoc.Drawpage
	REM Lage des Feldes in dem entsprechenden Formular aufsuchen
	oForm=oDrawpage.Forms.getByName("Formular")
	oFeld=oForm.getByName("Dateiauswahl")
	REM Den Text aus der Dateiauswahl auslesen
	stFeld=oFeld.Text
    inNumber = FreeFile()	'die nächste freie Dateinummer wird ermittelt und anschließend genutzt
    OPEN stFeld FOR INPUT AS inNumber
    	WHILE NOT EOF(#inNumber)	'solange das Ende der Datei nicht erreicht ist, wird jetzt jede Zeile ausgelesen
    		LINE INPUT #inNumber, stDaten
    		REM Auslesen der daten aus einer zeile der *.csv-Datei
    		inZaehler = 0
    		WHILE Len(stDaten) > 0	
    			ReDim Preserve aDaten(inZaehler)	'Neudimensiponierung des Arrays mit Sicherung des vorherigen Inhaltes
    			REM Wenn es sich um einen Text handelt ist er mit einem " eingegrenzt. Dann darf keine Trennung beim Komma erfolgen
    			IF Left(stDaten,1) = """" THEN	'Eingrenzung durch Anführungszeichen - Beginn mit einem Anführungszeichen
    				aTmp() = Split(stDaten,""",",2)	'Auftrennung in 2 Teile, Trennung an der Kombination aus Anführungszeichen und Komma
    				aDaten(inZaehler) = Mid(aTmp(0),2)	'Erster Teil wird in das Array geschrieben
    			ELSE
    				aTmp() = Split(stDaten,",",2)	'Wenn keine Anführungszeichen existieren: Trenner ist das Komma
    				aDaten(inZaehler) = aTmp(0)
    			END IF
    			IF UBound(aTmp) = 1 THEN	'Solange noch ein zweiter Teil des Arrays existiert wird der Inhalt stDaten neu zugewiesen
    				stDaten = aTmp(1)
    			ELSE
    				stDaten = ""	'... bis stDaten leer ist
    				IF Right(aDaten(inZaehler),1) = """" THEN
    					aDaten(inZaehler) = Mid(aDaten(inZaehler),1,Len(aDaten(inZaehler))-1)
    				END IF
    			END IF
    			inZaehler = inZaehler + 1
    		WEND
			REM Die Daten einer Zeile werden in die Tabelle übertragen
			IF inZaehler >= 4 THEN	'Zahl der Felder abfragen, die in der folgenden Insert-Anweisung benötigt werden 
'			aDaten(2) = Datum_2_SQLDate(aDaten(2))
'			aDaten(3) = Dezimalkomma(aDaten(3))
			stSql = "INSERT INTO ""Tabelle1"" (""Text"", ""Zahl"", ""Datum"", ""Dezimalzahl"") VALUES('" + aDaten(0) + "','" + aDaten(1) + "','" + aDaten(2) + "','" + aDaten(3) + "')"
	   	 	oSQL_Anweisung.executeUpdate(stSql)
			ELSE
    			CLOSE #inNumber
    			msgbox "Die CSV-Datei enthält zu wenige Spalten."
    			EXIT SUB
			END IF
    	WEND
    CLOSE #inNumber
END SUB
Eventuell liefere ich eine Beispieldatei dazu noch nach, mit der auch sicher gestellt wird, dass z.B. Datumsangaben richtig in Tabellen übertragen werden.

Gruß

Robert
Zuletzt geändert von RobertG am Mo, 28.05.2012 11:00, insgesamt 1-mal geändert.
RobertG
********
Beiträge: 2069
Registriert: Fr, 13.04.2012 19:28
Kontaktdaten:

Re: Anfängerfrage: Mehrere SQL-Befehle nacheinander ausführe

Beitrag von RobertG »

Jetzt habe ich auch eine Beispieldatenbank dafür fertig gestellt. Hier kann direkt der Import aus der beigefügten *.csv-Datei überprüft werden. Die erwarteten Feldeigenschaften sind zuerst ein Text, dann eine Zahl, dann ein Datum und schließlich eine Dezimalzahl. Die letzten beiden Eingaben werden durch eine Funktion so umgewandelt, dass in der HSQLDB-Tabelle daraus auch wirklich ein Datum bzw. eine Dezimalzahl wird.

Gruß

Robert
Dateianhänge
CSV_Import.zip
Import von CSV-Tabellen in Base - Löschung des Altdatenbestandes bei neuem Import - Datums- und Dezimalzahlberücksichtigung
(12.57 KiB) 103-mal heruntergeladen
RobertG
********
Beiträge: 2069
Registriert: Fr, 13.04.2012 19:28
Kontaktdaten:

Re: Anfängerfrage: Mehrere SQL-Befehle nacheinander ausführe

Beitrag von RobertG »

Ich habe das jetzt noch etwas erweitert:
Die folgende Version kann CSV-Daten auch aus unbekannten Tabellen importieren und versucht anhand der ersten Zeile zu erkennen, ob es sich um ein Datum, eine Dezimalzahl, eine Zahl oder Text handelt. Die vorherige einfachere Version wurde nur um die Möglichkeit erweitert, auch einzelne Daten als NULL weiter zu geben.
http://robert.familiegrosskopf.de/downl ... _Start.zip
Wie dem Namen zu entnehmen ist noch etwas mit reingepackt worden: Start eines Mailprogramms mit vorgegebener Adresse oder zusätzlich auch Betreff und Inhalt sowie Start des Webbrowsers mit vorgegebener Adresse - alles aus Base-Formularen heraus. Und damit das auch so ausschaut, als ob es sich um einen Link in der Datenbank handelt: Alles beides auch nur mit einem Textfeld, blaue Schrift, blau unterstrichen und beim Überfahren mit der Maus wird der Zeiger zu einer zeigenden Hand. Beim Klick öffnet sich dann der erwartete Pfad.
Verbesserungen und Erweiterungen veröffentliche ich weiter auf http://robert.familiegrosskopf.de, dort besonders im Menüpunkt "Einführung Base".

Gruß

Robert
Antworten