Import von leeren Zellen nicht möglich

Hallo Users,

ich habe eine Datenbank für die Imkerei als eingebettete HSQLDB in Base
erstellt.

Um den kommenden Nutzern bei Updates die Datenübernahme von einer
Vorversion in die Neuversion zu erleichtern, habe ich ein Makro auf der
Grundlage des Handbuchs (SUB Datenkopie) erstellt.

Mein Makro kopiert nun die Daten von mehreren Tabellen der
Vorgängerdatenbank in die gleich strukturierten Tabellen der Neuen
Datenbank, die z.B. aktualisierte Abfragen, Berichte, oder Formulare
enthält.

Das funktioniert soweit ohne Probleme.

Zwei Fehler treten allerdings auf, die ich trotz zahlreichen Versuchen
und Recherchen nicht lösen könnte.

1. In Zahlen-Felder, die in der Ursprungstabelle keine Einträge
enthalten, wird in die Zieltabelle immer die Zahl 0 (Null) importiert.

2. Datensätze mit Beziehungsfeldern, die auf ID-Felder von
Vorgabe-Tabellen verweisen, werden nur dann importiert, wenn in der
Vorgabe-Tabelle ein Vorgabedatensatz mit der ID 0 (Zahl Null) erstellt
wird, und als Vorgabewert kein Eintrag enthalten ist. Auch hier werden
dann aber in die Zieltabelle als Wert die Zahl 0 (Null) eingetragen.

Dies ist so der Fall, obwohl weder in den Zahlenfeldern, noch in den
Beziehungsfeldern zu ID-Werten in der Tabellenstruktur Einträge
erzwungen werden.

Gibt es für diese Importvariante irgend einen Typ, der auch leere
Datenfelder überträgt?

Hier als weitere Erläuterung mein auf den Import einer Tabelle gekürztes
Makro mit meinen Kommentaren:

SUB Datenkopie

dim dbname as string
dbname = InputBox("Datenbankname der Quelldatenbank eingeben")
if dbname = "" then
exit sub
end if

DIM oDatabaseContext AS OBJECT
DIM oDatenquelle AS OBJECT
DIM oDatenquelleQuell AS OBJECT
DIM oVerbindung AS OBJECT
DIM oVerbindungQuell AS OBJECT
DIM oDB AS OBJECT
DIM oSQL_Anweisung AS OBJECT
DIM oSQL_AnweisungQuell AS OBJECT
DIM oAbfrageergebnis AS OBJECT
DIM oAbfrageergebnisQuell AS OBJECT
DIM stSql AS String
DIM stSqlZiel AS STRING
DIM inID AS INTEGER
DIM inIDZiel AS INTEGER

oDB = thisDatabaseDocument
oDatenquelle = thisDatabaseDocument.CurrentController
If NOT (oDatenquelle.isConnected()) THEN
oDatenquelle.connect()
END IF
oVerbindung = oDatenquelle.ActiveConnection()
oDatabaseContext = createUnoService("com.sun.star.sdb.DatabaseContext")

stDir = Left(oDB.Location,Len(oDB.Location)-Len(oDB.Title))
stDir = ConvertToUrl(stDir & ""+dbname+"")           
'Quell-Datenbankpfad erstellen
oDatenquelleQuell = oDatabaseContext.getByName(stDir)       
'Quell-Datenbankpfad einlesen
oVerbindungQuell = oDatenquelleQuell.GetConnection("","")       
'Quell-Datenbankverbindung einlesen
oSQL_AnweisungQuell = oVerbindungQuell.createStatement()       
'SQL-Statement für Quelldatenbank erstellen

stSql = "SELECT * FROM ""tbl_Auswinterung"""
oAbfrageergebnisQuell = oSQL_AnweisungQuell.executeQuery(stSql)
WHILE oAbfrageergebnisQuell.next
inID = oAbfrageergebnisQuell.getint(1)     'ID (Integer)
sp2 = oAbfrageergebnisQuell.getLong(2)     'Integer
sp3 = oAbfrageergebnisQuell.getLong(3)     'Zahl' Long Double und int =
0 bei leer, String bricht ab bei leer, Currency Numeric Single Other Var
Varchar bricht sofort ab
sp4 = oAbfrageergebnisQuell.getString(4)     'Text
sp5 = oAbfrageergebnisQuell.getLong(5)    'Dezimalzahl
sp6 = oAbfrageergebnisQuell.getLong(6)    'Dezimalzahl
sp7 = oAbfrageergebnisQuell.getString(7)    'Datum
sp8 = oAbfrageergebnisQuell.getLong(8)    'Zahl
sp9 = oAbfrageergebnisQuell.getLong(9)    'Zahl

oSQL_AnweisungZiel = oVerbindung.createStatement()
stSql = "SELECT ""ID"" FROM ""tbl_Auswinterung"" WHERE ""ID"" = '"+inID+"'"
oAbfrageergebnis = oSQL_AnweisungZiel.executeQuery(stSql)
inIDZiel = - 1
WHILE oAbfrageergebnis.next
inIDZiel = oAbfrageergebnis.getInt(1)
WEND
IF inIDZiel = - 1 THEN
stSqlZiel = "INSERT INTO ""tbl_Auswinterung""
(""ID"",""StockNr"",""Brutwaben"",""Bemerkung"",""Futterwaben"",""Totenfall"",""Datum"",""Jahr_ID"",""Stärke_ID"")
VALUES
('"+inID+"','"+sp2+"','"+sp3+"','"+sp4+"','"+sp5+"','"+sp6+"','"+sp7+"','"+sp8+"','"+sp9+"')"
oSQL_Anweisung.executeUpdate(stSqlZiel)
END IF
WEND

MsgBox("Daten wurden übernommen")
end sub

MfG L-H

Hallo Leo,

hmm, nur ein paar kurze Bemerkungen (ich glaube, die Gesamtproblematik ist komplexer und ohne den kompletten Code zu kennen kaum lösbar...)

Zu den Fehlern:

1. In Zahlen-Felder, die in der Ursprungstabelle keine Einträge
enthalten, wird in die Zieltabelle immer die Zahl 0 (Null) importiert.

Tia, das hängt doch von deinen Variablen ab. Wenn in der DB ein Zahlenfeld definiert wird, steht dort immer eine Zahl drin oder eben (Null) nichts. wenn Du das ausliest mit getLong() wird immer ein Longwert zurückgeliefert - also bei leeren Feldern eine 0. Eine Longvariabel in Basic kann den Wert "nichts" nicht annehmen.

hier müsstest Du nicht den LongWert abfragen, sondern den Stringwert (getString) - der liefert Dir entweder den Wert als String(Text) oder eben einen leeren String.

Das kannst Du auch problemlos der DB wieder zuweisen - ist das DB Feld als Zahlwert definiert (long oder integer) so wird ein String passen umgewandelt - und ein leerer String wird zu "nichts":wink: (Vorausgesetzt, dass ist in der DB Definition zulässig).  Aber das machst Du ja sowieso - du weist allen Feldern Strings zu (erkennbar an den einfachen Hochzeichen).

Also: Viele Variablen und viele Möglichkeiten - aber so, wie das derzeit im Code gelöst ist, wird es korrekterweise 0 ergeben:)

Beim Code fällt mir noch auf: Wahrscheinlich wäre die IGNORE Anweisung sinnvoller, als zunächst abzufragen, ob die ID schon existiert. Bin mir aber nicht sicher, ob die HSQLDB diese überhaupt unterstützt.

So weit erst einmal , viele Grüße

Thomas

Hallo Leo-Hubert,

Thomas meint diese Zeile:

sp3 = oAbfrageergebnisQuell.getLong(3)

Mach' daraus

sp3 = oAbfrageergebnisQuell.getString(3)
IF sp3="" THEN
  sp3="NULL"
END IF

Vielleicht reicht das schon.

Gruß

Robert

... und dann noch die einfachen Anführungszeichen beim Insert weg -
sonst wird NULL nicht angenommen.

Gruß

Robert

Hey Robert, *

Hallo Leo-Hubert,

Thomas meint diese Zeile:

sp3 = oAbfrageergebnisQuell.getLong(3)

korrekt, eine Zeile unter mehreren...;))

Mach' daraus

sp3 = oAbfrageergebnisQuell.getString(3)

na, vorher:

dim sp3 as string

dann

sp3 = oAbfrageergebnisQuell.getString(3)

IF sp3="" THEN
  sp3="NULL"
END IF

Den Teil brauchste eigentlich nicht (es sei denn, die HSQLDB engine braucht das??).

Wenn Du später zuweist:

"INSERT INTO ""tbl_Auswinterung""
(""ID"",""StockNr"",""Brutwaben"",""Bemerkung"",""Futterwaben"",""Totenfall"",""Datum"",""Jahr_ID"",""Stärke_ID"")
VALUES
('"+inID+"',...., '" & sp3 & "'...)

und sp3 ist ne leerer String, so bleibt der Spaltenwert auf "NULL" .

Dass Du NULL dort explizit reinschreiben musst, ist an sich nicht nötig... es sei denn, es ist ne Besonderheit von HSQLDB..;))

VG

Thomas

Vielen Dank Robert und Thomas,

ich hab jetzt mal mehrere Varianten getestet.

Die hier unten funktioniert und löst beide beschriebene Probleme.

Wenn sich nach eurer Meinung da aber noch etwas vereinfachen lässt, bin
ich für jeden Rat dankbar.

Das "IF...THEN..NULL" wird wohl von der HSQLDB benötigt....

Jetzt werde ich bei Gelegenheit noch die anderen vom gleichen Problem
betroffenen Importbefehle anpassen.

Dann sollte der Veröffentlichung des Updates eigentlich nichts mehr im
Wege stehen.

Gruß L-H

SUB Datenkopie

dim dbname as string
dbname = InputBox("Datenbankname der Quelldatenbank eingeben")
if dbname = "" then
exit sub
end if

DIM oDatabaseContext AS OBJECT
DIM oDatenquelle AS OBJECT
DIM oDatenquelleQuell AS OBJECT
DIM oVerbindung AS OBJECT
DIM oVerbindungQuell AS OBJECT
DIM oDB AS OBJECT
DIM oSQL_Anweisung AS OBJECT
DIM oSQL_AnweisungQuell AS OBJECT
DIM oAbfrageergebnis AS OBJECT
DIM oAbfrageergebnisQuell AS OBJECT
DIM stSql AS String
DIM stSqlZiel AS STRING
DIM inID AS INTEGER
DIM inIDZiel AS INTEGER

oDB = thisDatabaseDocument
oDatenquelle = thisDatabaseDocument.CurrentController
If NOT (oDatenquelle.isConnected()) THEN
oDatenquelle.connect()
END IF
oVerbindung = oDatenquelle.ActiveConnection()
oDatabaseContext = createUnoService("com.sun.star.sdb.DatabaseContext")

stDir = Left(oDB.Location,Len(oDB.Location)-Len(oDB.Title))
stDir = ConvertToUrl(stDir & ""+dbname+"")                   
'Quell-Datenbankpfad erstellen
oDatenquelleQuell = oDatabaseContext.getByName(stDir)       
'Quell-Datenbankpfad einlesen
oVerbindungQuell = oDatenquelleQuell.GetConnection("","")   
'Quell-Datenbankverbindung einlesen
oSQL_AnweisungQuell = oVerbindungQuell.createStatement()   
'SQL-Statement für Quelldatenbank erstellen

REM Hier stehen noch mehrere andere Tabellen zum Import

stSql = "SELECT * FROM ""tbl_Auswinterung"""
oAbfrageergebnisQuell = oSQL_AnweisungQuell.executeQuery(stSql)
WHILE oAbfrageergebnisQuell.next
inID = oAbfrageergebnisQuell.getint(1)     'ID (Integer)
sp2 = oAbfrageergebnisQuell.getLong(2)     'Integer
sp3 = oAbfrageergebnisQuell.getString(3)     'Zahl'
IF sp3="" THEN
    sp3="NULL"
END IF
sp4 = oAbfrageergebnisQuell.getString(4)     'Text
sp5 = oAbfrageergebnisQuell.getString(5)    'Dezimalzahl
IF sp5="" THEN
    sp5="NULL"
END IF
sp6 = oAbfrageergebnisQuell.getString(6)    'Dezimalzahl
IF sp6="" THEN
    sp6="NULL"
END IF
sp7 = oAbfrageergebnisQuell.getString(7)    'Datum
sp8 = oAbfrageergebnisQuell.getLong(8)    'Zahl
sp9 = oAbfrageergebnisQuell.getString(9)    'Zahl
IF sp9="" THEN
    sp9="NULL"
END IF

oSQL_AnweisungZiel = oVerbindung.createStatement()
stSql = "SELECT ""ID"" FROM ""tbl_Auswinterung"" WHERE ""ID"" = '"+inID+"'"
oAbfrageergebnis = oSQL_AnweisungZiel.executeQuery(stSql)
inIDZiel = - 1
WHILE oAbfrageergebnis.next
inIDZiel = oAbfrageergebnis.getInt(1)
WEND
IF inIDZiel = - 1 THEN
stSqlZiel = "INSERT INTO ""tbl_Auswinterung""
(""ID"",""StockNr"",""Brutwaben"",""Bemerkung"",""Futterwaben"",""Totenfall"",""Datum"",""Jahr_ID"",""Stärke_ID"")
VALUES ('"+inID+"','"+sp2+"'," & sp3 & ",'"+sp4+"'," & sp5 &"," & sp6 &
",'"+sp7+"','"+sp8+"'," & sp9 & ")"
oSQL_Anweisung.executeUpdate(stSqlZiel)
END IF
WEND

REM Hier stehen noch mehrere andere Tabellen zum Import

MsgBox("Daten wurden übernommen")
end sub