Hallo,
bin ein SQL-Neuling und bei meinem Versuch, eine erste Datenbank zu erstellen auf folgendes Problem gestoßen:
Gegeben sind zwei Tabellen mit jeweils SERIAL als primary key.
CREATE TABLE a
(
id SERIAL PRIMARY KEY,
...
) ;
CREATE TABLE b
(
id SERIAL PRIMARY KEY,
...
);
Zwischen denen soll es eine n:m-Relation geben, die natürlich durch eine Zwischentabelle ab gelöst wird.
CREATE TABLE ab
(
aid INTEGER REFERENCES a (id),
aid INTEGER REFERENCES a (id)
);
Als umsichtiger Neuling achte ich selbstverständlich auf Datenintegrität und verwende Fremdschlüssel, um zu verhindern,
dass jemand Verknüpfungszeilen in ab einträgt, deren Werte in a oder b gar nicht existieren.
So weit so gut.
Möchte ich nun die Tabellen mit Daten füllen, muss ich das ja auf drei INSERTS verteilen, die ich ebenfalls bombensicher innerhalb einer Transaktion unterbringen will.
BEGIN;
INSERT INTO a (id,...) VALUES ...;
INSERT INTO a (id,...) VALUES ...;
INSERT INTO ab (aid,bid) VALUES (currval('a_id_seq'), currval('b_id_seq'));
COMMIT;
Sonst wäre es ja denkbar, das ein User Tabellen a und b füllt, und vor Ausführung des dritten INSERTS jemand anderes die Sequenz hochzählt, und damit das dritte INSERT die falschen Werte bekommt.
Das Problem ist aber, das durch die Transaktion tatsächlich noch gar nichts in Tabelle a und b steht (es ist nur vorgemerkt), und deshalb auch die Eintragung der currvals in “ab” fehlschlägt.
Wie löst man das richtig? Ich hatte schon die Idee, in einer temporären Tabelle vor der Transaktion einen Sequenzwert zu sichern, und diesen dann innerhalb der Transaktion auszulesen.
Gibt es einen saubereren Weg? (ohne zusätzliche Tabellen)
Vielen Dank,
Rainer