Hi,
Ich möchte einen Skriptgenerator basteln, der aus einem Memory-Dataset
SQL-Code generiert.
Wenn ein neuer Datensatz im InMemory-Dataset erzeugt wird, bekommt dieser vorläufig einen PK < 0, genauergesagt eine eindeutige ID (<0). Gelöschte Datensätze werden in einer Liste vermerkt und Änderungen an Feldinhalten auch.
Wenn ich die Änderungen in die
SQL-Datenbank einpflegen will, dann gehe ich durch das Dataset und füge die Records ein, deren PK negativ ist und erzeuge UPDATE bzw DELETE Anweisungen für die veränderten bzw. gelöschten Datensätze. Vernachlässigen wir die Änderungen, die sind ohne Probleme machbar.
Beim Einfügen treffe ich auf das bekannte Problem, das die neu generierten AutoInc-Werte wieder zurück in das In-memory Dataset geschrieben werden müssen (ich muss ja nach Speicherung den vorläufigen negativen PK mit dem aktuellen Wert überschreiben).
Bei direktem Ändern ist das kein Problem, denn ich kann ein Skript à la
insert into TABELLE (FELD) values ('FOO') returning PKFeldName;
in einem TIBQuery ausführen und dann via
TheQuery.Field[0]
den neuen Wert auslesen und den vormals negativen PK mit dem aktuellen Wert aus der
DB überschreiben (Natürlich ist da ein ON INSERT - Trigger mit Generator dahinter).
Die Ausführung ist also:
1. Gehe durch das Dataset
2. Wenn Dataset[PK]<0 dann
2.1 führe
insert into TABELLE (FELD) values ('FOO') returning PKFeldName;
aus.
2.2. schreibe das Ergebnis zurück in "Dataset[PK]"
Nun möchte ich die Ausführung jedoch verändern:
1. Skript für alle veränderten/eingefügten/gelöschten Records generieren
2. Skript ausführen
3. Neue PK 'auf einmal' in das In-Memory Dataset einflegen.
Um das zu erreichen muss das Skript eine Tabelle erstellen, die für jedes vorläufige negative PK den dann erzeugten Wert enthält.
Beispiel;
Im InMemory-Dataset sind zwei Zeilen eingefügt, deren vorläufiger PK ist -1 und -2.
Nehmen wir an, die
DB wird für die beiden neuen Records die PK 10 und 11 erzeugen, dann soll mein Skript folgendes Dataset zurück liefern:
Dann kann ich anschließend mein InMemory-Dataset entsprechend überarbeiten, sodaß dann das InMemory-Dataset die neu vergebenen PK-Inhalte enthält und somit eine 1:1 Abbildung der Original-Tabelle ist, OHNE das ich die Daten neu laden muss.
Frage:
Wie müsste so ein Skript aussehen. Ich skizziere mal, wie ich das machen würde
SQL-Code:
-- Statischer Teil: Präambel
create temporary table _PK (Key int, ID int);
declare variable newPK int;
-- Update code für InMemory- record mit vorläufiger ID -1
insert into TABELLE (FELD) values ('FOO') returning PKFeldName into :newPK;
insert into _PK (-1,:newPK);
-- Update code für InMemory- record mit vorläufiger ID -2
insert into TABELLE (FELD) values ('BAR') returning PKFeldName into :newPK;
insert into _PK (-2,:newPK);
-- Statischer Teil: Postambel
select * from _PK;
drop table _PK;
Wie würde o.g. Skript für Firebird richtig aussehen?
Kann man auf das Anlegen einer temporären Tabelle verzichten?