![]() |
Datenbank: Firebird • Version: 2.0 • Zugriff über: Firebird .NET Provider
[SQL] Datensatz kopieren
Hallo,
ich stehe im Moment etwas auf dem Schlauch. Ich möchte einen Datensatz mit leichten Änderungen kopieren. Dabei möchte gern alle Felder, bis auf 2 bestimmte Felder eins zu eins kopieren. Und das auch, wenn in Zukunft evtl. mal Felder dazukommen. In SQL könnte ich ja schreiben:
SQL-Code:
Das produziert eine Kopie von Datensatz 3 und weist die ID 4 zu.
INSERT INTO TABELLE (ID, NAME, VORNAME) SELECT 4 AS ID, NAME, VORNAME FROM TABELLE WHERE ID = 3;
Wenn nun aber in Zukunft noch das Feld BERUF hinzu kommt, möchte ich mein SQL-Statement nicht ändern müssen. Wie geht man sowas an? Leider kann ich im SELECT den * nur benutzen, wenn ich sonst nichts mit reinschreibe. Sonst hätte ich so eine Idee gehabt:
SQL-Code:
Geht aber nicht.
INSERT INTO TABELLE SELECT 4 AS ID, * FROM TABELLE WHERE ID = 3;
Tipps? Danke! Jens |
Re: [SQL] Datensatz kopieren
Ich glaube das ist nicht möglich. Ich wunder mich aber gerade, dass das "4 as ID" funktioniert. Ich kannte es bisher nur dass man direkt den Wert also hier nur "4" hinschreiben würde.
Gruß Reli |
Re: [SQL] Datensatz kopieren
Zitat:
Wenn ich schreibe
SQL-Code:
dann nennt Firebird die Spalter "F_1".
SELECT 4 FROM RDB$DATABASE
Wenn ich schreibe
SQL-Code:
dann heißt die Spalte halt "ID".
SELECT 4 AS ID FROM RDB$DATABASE
Gruß, Jens |
Re: [SQL] Datensatz kopieren
Hallo,
kenne Firebird nicht. Bei Oracle oder SQL-Server täte ich ins Dictionary schauen und mir dort aus den Einträgen zur Laufzeit das passende Statement bauen, mit Ausnahme der Spalten, bei denen ich selbst was ändern möchte. Unter SQL-Server könnte das ungefähr so aussehen:
SQL-Code:
Wenn Du Dir nun das Ergebnis dieses SQL nimmst, solltest Du das Insert-Statement erhalten, das Du wünschst.
select 'insert into tabelle (ID '
union all select ' ,' + column_name from information_schema.columns where table_name like 'tabelle' and column_name <> 'ID' union all select ') select 4 as ID' union all select ',' + column_name from information_schema.columns where table_name like 'tabelle' and column_name <> 'ID' union all select 'from tabelle where id = 3'
SQL-Code:
Und wenn Du neue Spalten in die Tabelle einfügst, so ändert sich das Ergebnis der ersten Abfrage um die entsprechenden Spalten und passt sich somit an Dein geändertes Datenmodell an.
insert into tabelle (ID
,name ,vorname ,beruf ) select 4 as ID ,name ,vorname ,beruf from tabelle where id = 3 Unter Oracle haben wir mal ein System gebaut, dass permanenten Änderungen des Datenmodells unterworfen war und ist. Diese Routinen sind nun seit etwa 5 Jahren im Einsatz und mussten bisher nicht einmal angepasst werden. |
Re: [SQL] Datensatz kopieren
Ja bei Abfragen ist das ja auch i.O. aber bei "Insert Selects" überflüssig, da es da auf die Reihenfolge ankommt wie du die Spalten angibst.
Gruß reli |
Re: [SQL] Datensatz kopieren
Wie wärs denn mit sowas :
Delphi-Quellcode:
Dataset2 := Dataset1; // alle Felder zunächst mal kopieren
// einzelne Felder bearbeiten Dataset2.Post; |
Re: [SQL] Datensatz kopieren
Zitat:
Bis vor einiger Zeit habe ich 4GL programmiert, dort konnte man sowas einfach mit dem Befehl BUFFER-COPY lösen. Naja, alles hat sein Vor- und Nachteile. Gruß, Jens |
Re: [SQL] Datensatz kopieren
Zitat:
Gruß, Jens |
Re: [SQL] Datensatz kopieren
Soll das heißen, bei .NET gibts in Delphi kein TDataset oder ähnliches mehr ? :shock:
|
Re: [SQL] Datensatz kopieren
Zitat:
Gruß, Jens |
Re: [SQL] Datensatz kopieren
Hallo Jens,
Zitat:
Nochmal zu dem oben genannten Beispiel von mir: Der Kunde, für den wir da tätig waren, hatte mehrere Systeme, die sich mindestens vierteljährlich änderten. Es war ein Datenaustausch notwendig zwischen einem halben Dutzend Systemen mit ähnlicher Änderungsrate. Das war zuerst in C++ geschrieben und jede Änderung musse in die Bibliothek übernommen werden, damit die Programme eine einheitliche Schnittstelle hatten. Bibliotheken mussten also in Quartalsversioenn gepflegt werden, die Programme jeweils mit den Bibliotheken kompiliert und den entsprechenden Versionen vorliegen. Wir sind Wahnsinnig geworden, weil man da einfach nicht mehr mithalten kann. Also haben wir gesagt: Die Datenbank ist Oracle (das einzig Konstante in dem System), wir bauen ein Package, dass den Job übernimmt und von den Programmen nur aufgerufen wird mit einer Angabe, zu welchem Jahr, Quartal und Version Daten zu übernehmen sind. Es gibt eine Konfigurationstabelle, in der die Versionen verwaltet werden und das läuft, auch wenn die SQL's dahinter zum Teil extrem komplext geworden sind, da ja bei der Übernahme auch noch die Constrains zu beachten sind... Aber der Aufwand hat sich gelohnt und die Geschwindigkeitsvorteile sind beachtlich. |
Re: [SQL] Datensatz kopieren
So, nun geht es.
Ich habe folgendes gemacht: 1. Eine Funktion, die mir eine Liste der Tabellenfelder zurückliefert. Dabei kann die Funktion auch Feldnamen durch etwas anderes ersetzen:
Delphi-Quellcode:
Meine Routine zum kopieren sieht jetzt so aus (Auszug):
function xxx.GetFieldList(strTable: String; trans : FBTransaction; ReplaceFields, Replace : Array Of String): string;
var c : FBCommand; dr : FBDataReader; i : Integer; bReplaced : Boolean; strField : String; begin {Gibt eine Liste der Felder der Tabelle zurück und ersetzt dabei ggf. die angegebenen String.} if length(ReplaceFields) <> length(Replace) then raise(Exception.Create('Die Anzahl der Elemente in ReplaceFields und Replace muss gleich sein!')); result := ''; c := FBCommand.Create('SELECT TRIM(RDB$FIELD_NAME) FROM RDB$RELATION_FIELDS WHERE UPPER(RDB$RELATION_NAME) = UPPER(@TABELLE) ORDER BY RDB$FIELD_POSITION', fbCon); try c.Transaction := trans; c.Prepare; c.Parameters.add('@TABELLE', fbdbtype.VarChar).Value := strTable; dr := c.ExecuteReader; while dr.Read do begin strField := dr.GetString(0); bReplaced := False; i := Low(ReplaceFields); while (not bReplaced) and (i <= high(ReplaceFields)) do begin if ReplaceFields[i] = strField then begin strField := Replace[i]; bReplaced := True; end; inc(i); end; if result <> '' then result := result + ','; result := result + strField; end; {while dr.read} dr.Close; finally c.Free; dr.Free; end; end;
Delphi-Quellcode:
Kritik ist willkommen. :mrgreen: strFields := GetFieldList('Buchungen', trans, [], []); strFields2 := GetFieldList('Buchungen', trans, ['ID', 'DATUM'], ['CAST(@IDZIEL AS INTEGER) AS ID', 'CAST(@DATUM AS DATE) AS DATUM']); c.CommandText := 'INSERT INTO BUCHUNGEN ' + '(' + strFields + ') ' + ' SELECT ' + strFields2 + ' FROM BUCHUNGEN WHERE ID = @IDQUELL'; c.Prepare; c.Parameters.Add('@IDZIEL', fbdbtype.Integer).Value := TObject(iID); c.Parameters.add('@IDQUELL', fbdbtype.Integer).Value := TObject(iBuchungID); c.Parameters.add('@DATUM', fbdbtype.Date).Value := TObject(dDatum); c.ExecuteNonQuery; trans.Commit; Gruß, Jens |
Re: [SQL] Datensatz kopieren
Hallo Jens,
Zitat:
Wenn Du aber auch eine Lösung innerhalb des DataSet (des NET-DataSet, nicht von Delphi-TDataset) in Betracht ziehst, kannst Du so vorgehen:
Gruß Jürgen PS. Deine Lösung, die Du inzwischen geschrieben hast, kann auch sinnvoll sein. Ich werde sie mir gleich genauer durchlesen. So, nachdem der Forum-Server wieder bereit ist, hier mein Kommentar: Grundsätzlich ein mögliches Verfahren, zumal Du es für Deine Bedürfnisse etwas erweitert und verallgemeinert hast. Nur ein paar Anmerkungen:
|
Re: [SQL] Datensatz kopieren
Hallo,
das sollte Deiner Aufgabenstellung gerecht werden ;-) |
Re: [SQL] Datensatz kopieren
Man könnte Testen ob man mit einem Execute-Block noch etwas rausholen kann
|
Re: [SQL] Datensatz kopieren
Hallo Thomas,
vielen Dank für die ausführliche Antwort. Zitat:
Zitat:
Zitat:
Gruß, Jens |
Re: [SQL] Datensatz kopieren
Hallo Jens,
Zitat:
Zitat:
Zitat:
Zitat:
Weiterhin viel Erfolg! Jürgen |
Re: [SQL] Datensatz kopieren
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:53 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz