🙏 Helfen Sie jetzt mit, unser LibreOffice Forum zu erhalten! 🙏
Mit Ihrer Spende sichern Sie den Fortbestand, den Ausbau und die laufenden Kosten dieses Forums. 🌱

🍀 Jeder Beitrag zählt – vielen Dank für Ihre Unterstützung!🍀

❤️ DANKE >> << DANKE ❤️

>> Dank Ihrer Unterstützung -> Keine Werbung für alle registrierten LibreOffice-Forum User! <<
🤗 Als Dankeschön werden Sie im Forum als LO-SUPPORTER gekennzeichnet. 🤗

Datenbank schließen

Alles zur Programmierung im LibreOffice.
Antworten
chico
Beiträge: 17
Registriert: Mo 28. Jul 2014, 15:13

Datenbank schließen

Beitrag von chico » Di 21. Okt 2014, 18:08

Hallo LibreOffice-Helfer,

ich komme auch nach langem Suchen nicht weiter.
Szenario:
In einem Makro werden 2 Datenbanken aufgerufen. Mit der 1. Datenbank "file:///Z:/wmt/verwaltung.odb" wird LO gestartet und mit

Code: Alles auswählen

    oVerbindungZiel = oDatenbank.ActiveConnection() 
zur aktiven Verbindung.
Die 2. Datenbank wird mit

Code: Alles auswählen

 oDatabaseContext = createUnoService("com.sun.star.sdb.DatabaseContext")
    oDatenquelle = oDatabaseContext.getByName("file:///Y:/wmt/empfang.odb")
    oVerbindungQuelle = oDatenquelle.GetConnection("","")
verbunden.
Nachdem eine Tabelle von der 1. - zur 2. Datenbank kopiert wurde, soll die 1.Datenbank die 2.Datenbank überschreiben.

Code: Alles auswählen

FileCopy("file:///Z:/wmt/verwaltung.odb","file:///Y:/wmt/empfang.odb")
Dabei kommt die Fehlermeldung:'Pfad nicht gefunden'.
Das liegt nach meinem Verständnis daran, dass die2. Datenbank nicht überschrieben werden kann, weil sie noch geöffnet ist, erkennbar auch an der Existenz des Lockfiles empfang.odb.lck
Nun versuche ich die 2. Datenbank vor dem Kopiervorgang zu schließen und komme nicht weiter.
Mit welcher Funktion wird die 2. Datenbank geschlossen, sodass das Lockfile verschwindet ? Mit oVerbindungQuelle.close() wird zwar kein Fehler angezeigt, aber die Verbindung nicht geschlossen.
Hier nochmal der gesamte Makro-Code, zum besserem Verständnis.

Code: Alles auswählen

   '/** openDatenabgleichBesuche
    '*************************************************************************.
    '* Wird von der Schaltfläche 'Datenabgleich' gestartet
    '* In empfang.odb wurde nur die Tabelle 'Besuche' geändert
    '* In verwaltung.odb wurden alle übrigen Tabellen geändert
    '* Prüft, ob beide Sticks im Rechner stecken
    '* Leert die Tabelle 'Besucher' des Z:Aufnahme-Sticks
    '* Kopiert die Tabelle 'Besucher' des Y:Empfang-Sticks in die leere Tabelle
    '* 'Besucher' des Z:Aufnahme-Sticks
    '* Kopiert die Datenbank 'verwaltung.odb' des Z:Aufnahme-Sticks nach
    '* 'empfang.odb' des Y:Empfang-Sticks
    '* Als Ergebnis sind die Datenbanken auf beiden Sticks gleich.
    '*************************************************************************
    '*/
    Sub openDatenabgleichBesuche 
       DIM oDatabaseContext AS OBJECT
       DIM oDatenbank AS OBJECT
       DIM oDatenquelle AS OBJECT
       DIM oDatenziel AS OBJECT
       DIM oVerbindungQuelle AS OBJECT
       DIM oVerbindungZiel AS OBJECT
       DIM sTitel As STRING
       if NOT checkPfadKomplett("file:///Y:/wmt/empfang.odb") then
             MsgBox("Kann empfang.odb nicht finden ! Bitte Empfangs-Stick 'Y' einstecken !",48,"Hinweis")
             exit sub
          end if   
          if NOT checkPfadKomplett("file:///Z:/wmt/verwaltung.odb") then
             MsgBox("Kann verwaltung.odb nicht finden ! Bitte Verwaltungs-Stick 'Z' einstecken !",48,"Hinweis")
             exit sub 
         end if    
       CacheToDB               
       oDatenbank = ThisComponent.Parent.CurrentController  'Ziel-Datenbank verwaltung.odb   
       If NOT (oDatenbank.isConnected()) THEN
          oDatenbank.connect()
       END IF
       oDoc = ThisComponent.Parent
       sTitel = oDoc.Title
       IF sTitel <> "verwaltung.odb" THEN
          MsgBox("Das Programm muss mit der Datei 'verwaltung.odb' gestartet werden !",16,"Falsche Datenbank gestartet")
          exit sub
       END IF
       oVerbindungZiel = oDatenbank.ActiveConnection()           'Verbindung zur Zieldatenbank verwaltung.odb aktivieren
       oDatabaseContext = createUnoService("com.sun.star.sdb.DatabaseContext")  'Sun Service aufrufen
       oDatenquelle = oDatabaseContext.getByName("file:///Y:/wmt/empfang.odb") 'Quelldatenbank empfang.odb aufrufen
       oVerbindungQuelle = oDatenquelle.GetConnection("","")   'Quelldatenbank  verbinden
       oSQL_Anweisung = oVerbindungQuelle.createStatement()     'SQL-Anweisung für Quell-Datenbank empfang.odb
       stSql = "SELECT * FROM ""Besuche"""                     'Alles aus Tabelle Besuche der Quelldatenbank auswählen
       oAbfrageergebnis = oSQL_Anweisung.executeQuery(stSql)   'Ergebnis auswerten
       oSQL_AnweisungZiel = oVerbindungZiel.createStatement()   'SQL-Anweisung für Ziel-Datenbank
       stSqlDelete = "DELETE FROM ""Besuche"""                'Tabelle Besuche der Zieldatenbank leeren
       oSql_AnweisungZiel.executeUpdate(stSqlDelete)          'SQL-Anweisung Durchführen
       WHILE oAbfrageergebnis.next                       'Alle Datensätze(Zeilen) der Quell-Tabelle empfang.odb nacheinander aufrufen
          inID = oAbfrageergebnis.getInt(1)               'Jedes Datenfeld einer Zwischenvariablen zuweisen
          dBesuche = oAbfrageergebnis.getString(2)
          inKunden_ID = oAbfrageergebnis.getInt(3)
          bEuro = oAbfrageergebnis.getBoolean(4)
          oSQL_AnweisungZiel = oVerbindungZiel.createStatement() 'SQL-Anweisung für Ziel-Datenbank vorbereiten
          stSqlZiel = "INSERT INTO ""Besuche"" (""ID"",""Besuche"",""Kunden_ID"",""Euro"") VALUES ('"+inID+"','"+dBesuche+"','"+inKunden_ID+"','"+bEuro+"')"
          oSql_AnweisungZiel.executeUpdate(stSqlZiel)           'Alle Datenfelder der Quelltabelle in die leere Zieltabelle Kopieren
       WEND    'nächster Datensatz
       oVerbindungQuelle.close()
       FileCopy("file:///Z:/wmt/verwaltung.odb","file:///Y:/wmt/empfang.odb")
       msgbox("Die Datenbank verwaltung.odb und empfang.odb haben sich gegenseitig aktualisiert."+chr$(13)+"Beide Datenbanken sind nun gleich.",64,"Datenabgleich erfolgreich")
    End Sub  
Vielen Dank im Voraus !

Jens

gogo
* LO-Experte *
Beiträge: 1081
Registriert: Sa 5. Feb 2011, 19:07

Re: Datenbank schließen

Beitrag von gogo » Di 21. Okt 2014, 20:27

chico hat geschrieben:Nachdem eine Tabelle von der 1. - zur 2. Datenbank kopiert wurde, soll die 1.Datenbank die 2.Datenbank überschreiben.
sry, aber daraus werd' ich nicht schlau ;) - wozu kopierst Du etwas von A nach B, wenn B Sekunden später zerstört wird?
chico hat geschrieben:... Dabei kommt die Fehlermeldung:'Pfad nicht gefunden' ...
Pfad nicht gefunden ist Pfad nicht gefunden. Ein fehlerhafter Zugriff würde einen E/A-Fehler verursachen. Versuch's mal mit den URLs:

Code: Alles auswählen

FileCopy(ConvertToUrl("file:///Z:/wmt/verwaltung.odb"),ConvertToUrl("file:///Y:/wmt/empfang.odb") )
.. oder so ähnlich.

ad Öffnen und Schließen von Datenbanken bzw. von Dateien ("Starbasic-Component"):
mit

Code: Alles auswählen

oDatenbank = ThisComponent
öffnest Du nicht nur die Verbindung zur DB, sondern auch die Datei selbst. Wenn Du mit den Dateien jonglieren willst, dann wäre es gut die ganze Aktion durch ein extra Makro zu machen, das NICHT in einer der beiden DB steckt. Du müsstest ja dabei die Datei manipulieren in der Du gerade arbeitest. Das Schließen von DBs funktioniert nach meiner Erfahrung nur dann zuverlässig, wenn es von außen passiert. (Und der Erfolg hängt noch von weiteren Faktoren ab wie Schnellstarter, Betriebssystem ...)

Wenn Du wirklich mit der "Verwaltungs-DB" auf Y weiterarbeiten willst, mach am besten vorher eine SiKop von der Empfangs-DB, dann holst Du die Daten aus der SiKop in die Verwaltungs-DB, beendest die Transaktion auf alle Fälle mit einem zuverlässigen Flush-Kommando (welches genau kann ich Dir nicht sagen weil ich nie mit der HSQLDB arbeite), und dann kopierst Du die Verwaltungs-DB nach Y. Also etwa so:

Code: Alles auswählen

Makro (z.B. in einem Writer-Dok, oder nur so als Extension...)

filecopy (empf.odb, empf_sicher.odb)
oVerw=oVerwContext.getByName(verw.odb)
oEmpf=oEmpfContext.getByName(empf_sicher.odb)

oVerw.Stat.ExeUpdate(Delete   from Besuche)
oEmpf.Stat.ExeSelect(Select * from Besuche)

Do while oEmpf.Stat.next
  oVerw.Stat.ExeUpdate(insert into Besuche)
Loop

oVerw.flush
oVerw.close

kill empf.odb
filecopy (verw.odb, empf.odb)
Alternativ, falls der letzte filecopy-Befehl fehlschlägt, kannst Du den auch per shell-Kommando nach Beendigung von LO erledigen - nach meiner Erfahrung funktioniert ein Überschreiben von gerade mal eben geöffneten Dateien am besten wenn LO komplett geschlossen ist, dh. auch der LO-Prozess beendet ist!
g
2008 LucidL./MaverickM./WinXP LibreOffice 3.3.2 > 02/13 LinuxMint13/Xubuntu > 09/13 Debian Wheezy+LO3.5.4.2 > 01/15 Debian Jessie KDE+LO4.3.3.2/Mint17 openbox auf USB+LO4.2.8.2 > 03/16 ArchLin & LO5.1+ff > 02/18 Kubuntu

chico
Beiträge: 17
Registriert: Mo 28. Jul 2014, 15:13

Re: Datenbank schließen

Beitrag von chico » Mi 22. Okt 2014, 10:23

@ gogo
Vielen Dank für die schnelle Antwort.
1.
Nachdem eine Tabelle von der 1. - zur 2. Datenbank kopiert wurde, soll die 1.Datenbank die 2.Datenbank überschreiben.
sry, aber daraus werd' ich nicht schlau ;) - wozu kopierst Du etwas von A nach B, wenn B Sekunden später zerstört wird?
Da hast Du natürlich Recht. Es muss heißen:
Nachdem eine Tabelle von der 1. - zur 2. Datenbank kopiert wurde, soll die 2.Datenbank die 1.Datenbank überschreiben.
Hintergrund:
Am Anfang sind beide Datenbanken gleich. In der 1. Datenbank werden Änderungen nur in einer Tabelle gemacht, in der 2. Datenbank nur in allen anderen Tabellen. Diese Änderungen müssen gleichzeitig auf zwei Rechnern in verschiedenen Räumen gemacht werden. Ein Betrieb im Netzwerk mit einem Datenbankserver ist nicht möglich. Durch das Kopieren und Überschreiben sollen beide Datenbanken auf den gleichen Stand gebracht werden.
2.
Dabei kommt die Fehlermeldung:'Pfad nicht gefunden' ...
Pfad nicht gefunden ist Pfad nicht gefunden. Ein fehlerhafter Zugriff würde einen E/A-Fehler verursachen. Versuch's mal mit den URLs:

Code: Alles auswählen
FileCopy(ConvertToUrl("file:///Z:/wmt/verwaltung.odb"),ConvertToUrl("file:///Y:/wmt/empfang.odb") )
Wenn ich z.B. schreibe

Code: Alles auswählen

FileCopy("file:///Z:/wmt/verwaltung.odb","file:///Y:/wmt/empfang2.odb") 
wird der Kopie-Befehl ohne Fehler ausgeführt. An der Pfadangabe stört sich LO daher nicht. Die Fehlermeldung müsste etwa lauten ' Die Datei empfang.odb ist noch in Gebrauch und kann nicht überschrieben werden'.

Deine anderen Vorschläge werde ich jetzt mal ausprobieren.

Gruß
Jens

chico
Beiträge: 17
Registriert: Mo 28. Jul 2014, 15:13

Re: Datenbank schließen

Beitrag von chico » Sa 1. Nov 2014, 18:42

Nachdem ich alle notwendigen Datenbankkopien beim Schließen der Datenbank mit dem Ausführen von batch-Dateien mit dem shell() Befehl erledige gibt es keine Probleme mehr.


An alle, die das LibreOffice-Forum gern nutzen und unterstützen wollen:


Bitte helfen Sie uns mit 7 Euro pro Monat.
Durch Ihren Beitrag tragen Sie dazu bei, unsere laufenden Kosten für die kommenden Monate zu decken.
Unkompliziert per Kreditkarte oder PayPal.
Als ein kleines Dankeschön werden Sie im LO-Forum als SUPPORTER gekennzeichnet.



Antworten