Entwickler-Ecke

Datenbanken - Tabelle via SQL-Befehl von Datenbank 1 zu Datenbank 2?


Shorti - Mi 10.08.11 11:30
Titel: Tabelle via SQL-Befehl von Datenbank 1 zu Datenbank 2?
Hallo zusammen,

auch nach intensiver Suche habe ich noch keine Lösung gefunden.
Ich habe 2 Firebird-Datenbanken, auf denen ich mit Zeos-Komponenten zugreife. Die Struktur ist identisch. Nun möchte ich eine ganze Tabelle von Datenbank 1 zu Datenbank 2 kopieren. Am liebsten mit einem SQL-Befehl (z.B. INSERT INTO TAB(DB1) SELECT * FROM TAB(DB2)), aber wie kann das funktionieren? Der Befehl bezieht sich doch nur auf 1 TZConnection, oder?

Bitte um Unterstützung.

MfG Shorti


Xion - Mi 10.08.11 12:50

http://sql.1keydata.com/de/sql-insert-into.php hat folgendes geschrieben:


SQL-Anweisung
1:
2:
3:
4:
INSERT INTO Store_Information (store_name, Sales, Date)
SELECT store_name, Sales, Date
FROM Sales_Information
WHERE Year(Date) = 1998


//Edit: Hab irgendwie das wesentliche verpasst. Ob das so zwischen 2 Datenbanken geht musst du mal ausprobieren.

http://www.traum-projekt.com/forum/19-traum-dynamik/28017-datenbank-tabelle-kopieren-und-einfuegen.html hat folgendes geschrieben:


SQL-Anweisung
1:
INSERT INTO datenbankC.tabelleA SELECT * FROM datenbankB.tabelleA                    


Shorti - Mi 10.08.11 14:05

Hallo Xion,

danke für die schnelle Antwort, aber was genau steckt hinter datenbankC, der Pfad zur Datenbank?
Und mit welchem Query löst du den SQL Befehl (ExecSQL) aus?


Also, es gibt 2 ZConnections DatabaseIntern und DatabaseTmp.
Datenbank wird erst erstellt (DatabaseTmp nur anderer Pfad):


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
   //Datenbank erstellen
    DatabaseIntern.LoginPrompt   := false;
    DatabaseIntern.Database      := DirSystem + 'InternDB.fdb';
    DatabaseIntern.User          := 'sysdba';
    DatabaseIntern.Password      := 'masterkey';
    DatabaseIntern.Protocol      := 'firebird-2.1';

    DatabaseIntern.Properties.Add ('CreateNewDatabase=CREATE DATABASE ' +
      QuotedStr (DatabaseIntern.Database) + ' USER ' +
      QuotedStr (DatabaseIntern.User) + ' PASSWORD ' + QuotedStr (DatabaseIntern.Password) +
      ' PAGE_SIZE 4096 DEFAULT CHARACTER SET NONE');


Dann DatabaseIntern.Connect.
Dann eine Tabelle erstellen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
   //Teiledaten
     query := ('CREATE TABLE TEILEDATEN (TEILENR VARCHAR(8),ARTIKELNR VARCHAR(8),'+
        'FARBE VARCHAR(15), AUSRICHTUNG VARCHAR(2), PROFILTYP VARCHAR(15), LAENGE VARCHAR(8), '+
        'ANWI VARCHAR(8), ABWI VARCHAR(8),RAHMENNR INT, STABNR INT,' +
        'UP VARCHAR(3), FERTIG VARCHAR(6), BEDARF VARCHAR(8))');
     ExecuteQuery(query,DatabaseIntern);


Wie soll ich jetzt deiner Meinung nach die komplette Tabelle TEILEDATEN von DatabaseIntern
nach DatabaseTmp kopieren?


Delphi-Quelltext
1:
INSERT INTO datenbankC.tabelleA SELECT * FROM datenbankB.tabelleA                    

Kann ich schlecht umsetzen, da fehlt mir zuviel.
Also nach deinem Beispiel funktioniert es nicht, oder was mache ich falsch?:

Delphi-Quelltext
1:
2:
query := ('INSERT INTO '+QuotedStr(DatabaseTmP.Teiledaten)+' SELECT * FROM Teiledaten');
ExecuteQuery(query,DatabaseIntern);


In ExecuteQuery() wird zur Laufzeit ein Query erstellt und der SQL Befehl über die angegebene
ZConnection(DatabaseIntern) abgesetzt.

Was muss ich ändern???


MfG Shorti


Xion - Mi 10.08.11 14:43

Wie heißen denn deine beiden Datenbanken?

DatabaseIntern.Database und 'InternDB'?

query := ('INSERT INTO '+DatabaseIntern.Database+'.Teiledaten SELECT * FROM InternDB.Teiledaten');

Hier verwenden sie aber einen anderen Befehl:
http://forums.devshed.com/ms-sql-development-95/copy-table-contents-to-different-database-88123.html hat folgendes geschrieben:

SQL-Anweisung
1:
SELECT * INTO TargetDB.dbo.NewTable FROM existingdb.dbo.existingtable                    


//Edit: Wie man vielleicht merkt hab ich von Firebird speziell keine Ahnung ;)


zuma - Mi 10.08.11 16:22

Ich arbeite zwar mit Interbase, aber das Problem sehe ich nicht so sehr in der verwendeten Datenbank sondern eher darin, das man 2 Datenbanken gleichzeitg im Zugriff haben will.
Wenn ein übertragen von Tabellendaten mit EINEM Sql-befehl zwischen ZWEI Datenbanken funktioniert, würde ich gerne wissen, wie, denn nach so einer Möglichkeit such ich schon seit Jahren und glaubte bisher, das das nicht geht.
Hab daher eine andere Lösung, da ich oft Daten zwischen verschiedenen Datenbanken austauschen muss.
Das ganze sind nur einige wenige Codezeilen bei mir und funktioniert auch bei größeren Datenmengen recht schnell, daher war ich bislang mit der Lösung zufrieden.
Wie siehts denn mit den Problemen "Daten schon vorhanden in ZielTabelle, ändern oder überschreiben? bei dir aus? Oder willst du 'nur' in Ziel-DB spiegeln ?


Shorti - Mi 10.08.11 16:24

Danke für die Bemühungen Xion,
aber das hilft mir Leider nicht weiter.

Die beiden ZConnections heißen DatabaseIntern und DatabaseTmp. Die Datenbank selber heißt beide male InternDB.fdb, liegt aber in verschiedenen Ordnern. Diese Bezeichnungen kann ich aber glaube ich nicht im SQL-Statement nutzen.

Vielleicht weiß da ja noch wer anders Rat.

MfG Shorti

---Moderiert von user profile iconNarses: Beiträge zusammengefasst---

Hallo Zuma,

meine Ziel-DB ist auf alle Fälle immer leer. Der ganze Hintergrund für diese Geschichte ist, das ich ein Backup/Restore der eigentlichen Datenbank durchführen will, und nicht ShellExecute mit dem "gbak"- Programm nutzen will.
Wie kopierst du denn die Daten zur Zeit, auch über Querys mittels Schleifen(Feld für Feld) oder hast du da noch einen anderen Weg für mich?

MfG Shorti


zuma - Mi 10.08.11 16:47

Also, ganz simpel gesagt:
ich habe 2 Query's (Quelle, Ziel) mit den jeweiligen Connections zur richtigen DB.
Quelle und Ziel lese ich mit dem selben sql (Select * from Tabelle), in deinem Fall ist ziel ja leer, daher entfällt meine logik für änderungen an der stelle.
dann mach ich ein

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
while not quelle.eof do
begin
 ziel.Append;
 for i := 0 to quelle.fieldcount -1 do
  ziel.Fields[i].asvariant = quelle.Fields[i].asvariant;
 ziel.post;
 quelle.next;
end;


Backup/Restore der ganzen DB mach ich mit den IB-Komponenten für Backup/restore (hab da ne eigene kleine Unit für gebastelt), aber ich sicher ja auch ne ganze DB, nicht nur eine Tabelle aus der DB ;)

mach nu Feierabend, falls du noch fragen hast: morgen ab 07:30 bin ich wieder hier ;)


Shorti - Do 11.08.11 08:00

Danke Zuma,

in ähnlicher Form mache ich es bis jetzt auch. Ich wundere mich nur, das es wirklich keine andere Lösung dafür geben soll. Bei andern Datenbanken habe ich im Netz so etwas wie "INSERT INTO Tabelle1 IN Datenbank1 SELECT * FROM Tabelle2" gesehen.

Aber soweit ich weiß gibt es diese Syntax bei Firebird nicht INSERT INTO ... IN ..

Naja, trotzdem Danke für die Unterstützung.


MfG Shorti


Nersgatt - Do 11.08.11 08:32

Mit Firebird 2.5 ist es in PSQL evtl. möglich. Selbst probiert hab ich es aber noch nicht.
Damit wäre dann so ein Konstrukt möglich:


SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
execute block returns (emp_no smallintas
begin
FOR EXECUTE STATEMENT 'select emp_no from employee'
ON EXTERNAL DATA SOURCE 'localhost:employee' AS USER 'sysdba' PASSWORD 'masterkey'
INTO :emp_no
DO SUSPEND;
end


http://www.firebirdfaq.org/faq16/


Shorti - Do 11.08.11 08:59

Danke Nersgatt,

das Thema hat sich mit der bitteren Wahrheit somit erledigt.

MfG Shorti


Singlepin - So 14.08.11 20:41

Hallo Shorti,

wenn ich die Sache richtig verstanden habe sollte es so gehen:

ZConnection1.ExecuteDirect('CREATE TABLE DBZiel.t_TabelleNeu AS SELECT * FROM DBQuelle.t_TabelleAlt;');

Getestet Mit Delphi 6 Zeos und MySQl