Hallo Forum,
Folgende Problematik:
Ich habe zwei Tabellen in einer Postgre-Datenbank:
tabelle1
+------+--------+
| id1 | desc |
+------+--------+
id1: bint, not null, primary, default: nextval('tabelle1_id_seq')
tabelle2
+------+--------+---------+
| id2 | id1 | name |
+------+--------+---------+
(Das ist nur eine Beispielstruktur! Bitte nicht über deren Sinn diskutieren *g*)
"Id1" hat eine Sequenz namens ("tabelle1_id_seq" --> default values!)
******* dump.sql ******
-- tabelle 1 erstellen
CREATE TABLE "public"."tabelle1" (
"id1" BIGINT NOT NULL,
"desc" CHAR(50),
PRIMARY KEY("id1")
) WITH OIDS;
-- sequenz erstellen
CREATE SEQUENCE "tabelle1_id_seq";
-- default wert für primary setzten
ALTER TABLE "public"."tabelle1" ALTER COLUMN "id1" SET DEFAULT nextval('tabelle1_id_seq');
*******
Ziel ist: Ich möchte eine neue Zeile in die Tabelle1 schreiben und brauche die neue Id für die Eingabe in Tabelle2 (foreign key).
(Tabelle2 ist nur zur Veranschaulichung und wird für die Testumgebung nicht benötigt)
Ouso, ich habe folgenden Test-Code in php:
****** test.php ******
<?
$conn = pg_connect("host=xxx.xxx.xxx.xxx port=5432 dbname=db1 user=user1 password=*****");
// zuerst die nächste id in der sequenz auslesen
$sql = "select nextval('tabelle1_id_seq') as nextId from tabelle1;";
$rs = pg_exec($conn, $sql);
$rn = pg_numrows($rs);
echo $rn; // geben wir das mal aus
if ($rn > 0) $nextIdArr = pg_fetch_array($rs,0);
print_r($nextIdArr); // auch dieses brauchen wir zu debug-zwecken
pg_freeresult($rs);
$nextId = 0;
$nextId = $nextIdArr[nextid];
if ($nextId == 0) {
$nextId = 1; // ganz lustig und unsauber. [1]
}
$sql = "insert into tabelle1 (id1, desc)";
$sql .= " values ($nextId,";
$sql .= " 'test')";
echo $sql; // auch wieder zu debug-zwecken
pg_exec($conn, $sql)
?>
******
Also, das ganze mal ausgeben und es passiert folgendes:
----------------------
output --> "0insert into tabelle1 (id1, "desc") values (1, 'test')"
Hit-Reload
output --> "duplicated key" --> siehe [1]
Hit-Reload
output --> "1Array ( [0] => 2 [nextid] => 2 ) insert into tabelle1 (id1, "desc") values (2, 'test')"
Hit-Reload
output --> "2Array ( [0] => 3 [nextid] => 3 ) insert into tabelle1 (id1, "desc") values (3, 'test')"
Hit-Reload
output --> "3Array ( [0] => 5 [nextid] => 5 ) insert into tabelle1 (id1, "desc") values (5, 'test')"
Hit-Reload
output --> "4Array ( [0] => 8 [nextid] => 8 ) insert into tabelle1 (id1, "desc") values (8, 'test')"
Hit-Reload
output --> "5Array ( [0] => 12 [nextid] => 12 ) insert into tabelle1 (id1, "desc") values (12, 'test')"
------------------------
Erklärung:
Bei der ersten Ausgabe muss ich den Primary Key faken [1], weil mir "select nextval('tabelle1_id_seq') as nextId from tabelle1;" nichts zurück gibt. Hier würde ich eigentlich "1" erwarten.
Beim Reload gibt es natürlich einen Fehler weil mir das "nextval"-Statement wieder "1" zurückgibt (es wurde anscheinend erst jetzt initialisiert).
Danach klappt es mit den "inserts" und jetzt taucht das nächste Problem auf:
Das "nextval"-Statment liefert mir je öfters aufgerufen, desto mehr "Recordsets" zurück. ("Primary-Key"-Pakete *g*)
Dementsprechend wird die verwendete ID folgendermassen hochgezählt:
k(n) = k(n-1) + (k(n-1) - k(n-2) + 1)
n >= 5
1, 2, 3, 5, 8, 12, 17 ...
Irgendwie unerklärlich und irgendwie doof :-(
Kann mir jemand bei diesem Problem auf die Sprünge helfen?
Auch [1] ist recht komisch, meiner Meinung nach müsste beim ersten "select nextval"-Statement schon eine "1" zurückgeliefert werden und nicht "nichts".
Vielen Dank schon mal!
Grüsse
Siramon,
ja der Penner aus Nr. 14