[linux-l] SQL / PostgreSQL

Olaf Radicke olaf_rad at gmx.de
Do Sep 21 22:41:28 CEST 2006


Am Donnerstag, 21. September 2006 15:22 schrieb Pascal Volk:
> * Am Mi, 20 Sep 2006 schrub Olaf Radicke:
> > Lösung gefunden:
> > [...]
> > Wenn ich also meine ID haben will, muss ich den weg "zu Fuss" machen.
> > Erster Schritt:
> > SELECT nextval('einschraenkung_merkmal_id_seq');
> > Dazu muss ich natürlich den Sequenz Namen kennen. Der setzt sich zusammen
> > aus Tabellenname, Tiefstrich, Spaltenname, Tiefstrich, "seq".
>
> Nein und nein.
> Was macht denn nextval? Etwa den nächsten (erst setzen) und dann
> zurückgeben? Ja - genau.
> Rufe dazu mehr SELECT nextval('einschraenkung_merkmal_id_seq'); auf, und du
> wirst sehen, dass jedesmal ein anderen Wert rauskommt. Aber Du wirst
> niemals einen Datensatz haben, der die ID hat, die Dir mit nextval
> angezeigt wurde.
>
> Wo steht bitte geschrieben, dass die Sequenz 'relation_filed_seq' heißen
> muss? Sie kann so heißen, ja.
>
> > Jetzt habe ich meine eindeutige ID, die mir niemand mehr wegnehmen kann.
> > Egal welche Operationen auf der Tabelle in der zwischenzeit ausgeführt
> > werden, wann immer ein Anderer direkt nextval() oder indirekt SERIAL
> > aufruft, er wird immer eine andere ID bekommen, als ich. Auch wenn ich
> > mir 10 Jahre Zeit lasse zwischen dem nextval()-Aufruf und dem
> > INSERT-Befehl. Meine ID wird für mich frei sein.
>
> Ha, das hast Du Dir schön gedacht.
> Du nimmst Dir, mit der oben beschrieben Variante, die ID selbst weg, aka
> Trick 17 m. S. Kein Datensatz wird diese ID jemals bekommen.

[...]


Vielleicht kann ich mich ja auch nicht richtig ausdrücke. Deshalb noch mal die 
PostgreSQL-FAQ:


4.11.2) Wie bekomme ich den Wert einer SERIAL-Sequenz?
------------------------------------------------------

Eine Möglichkeit wäre, mit der nextval()-Funktion den nächsten SERIAL-Wert von 
dem Sequenzobjekt vor der Auszuführung einer INSERT-Anweisung anzufordern und 
ihn dann explizit in die INSERT-Anweisung einzubinden. Anhand der 
Beispieltabelle in 4.11.1 könnte dieser Vorgang in einer Pseudosprache so 
aussehen:
    new_id = output of execute("SELECT nextval('person_id_seq')");
    execute("INSERT INTO person (id, name) VALUES (new_id, 'Blaise Pascal')");

Danach stünde der neue Wert in der Variablen new_id für die Verwendung in 
weiteren Abfragen zur Verfügung, zum Beispiel als Fremdschlüssel zur 
Tabelle 'person'). Bitte beachten Sie, dass der Name des automatisch 
erstellten SEQUENCE-Objektes folgenden Name hat: <table>_<serialcolumn>_seq 
wobei 'table' und 'serialcolumn' die Namen der jeweils betreffenden Tabelle / 
Spalte darstellen.
Als weitere Möglichkeit können Sie nach einer INSERT-Anweisung den automatisch 
eingefügten SERIAL-Wert mit der currval()-Funktion zurückgeben lassen:
    execute("INSERT INTO person (id, name) VALUES (new_id, 'Blaise Pascal')");
    new_id = output of execute("SELECT currval('person_id_seq')");


4.11.3) Führt currval() zu einer Race-Condition mit anderen Nutzern?
--------------------------------------------------------------------

Nein. currval() liefert einen Wert zurück, der von Ihrer Datenbank-Session 
bestimmt wird, und der anderen Sessionen nicht zur Verfügung steht.

[...]

4.12) Was ist ein OID? Was ist ein CTID?
----------------------------------------

Jede Zeile, die in PostgreSQL erzeugt wird, bekommt eine eindeutige OID, 
sofern die Tabelle nicht mit der Option WITHOUT OIDS angelegt wurde. OIDs 
sind automatisch zugewiesene 4-Byte-Integer, die innerhalb der gesamten 
Datenbank einmalig sind. Allerdings laufen sie bei einem Wert von ungefähr 4 
Milliarden über. PostgreSQL verwendet OIDs, um seine interne Systemtabellen 
zu verbinden.
Um einmalige Idenfikatoren in Datentabellen zu erstellen, wird allerdings 
empfohlen, statt OIDs Werte zu verwenden, die vonSERIAL- Sequenzen erzeugt 
werden. SERIAL-Sequenzen sind innerhalb einer Tabelle einmalig und daher 
weniger anfällig für Überläufe. Außerdem können 8-Byte-Sequenzwerte mit 
SERIAL8 erzeugt werden.
CTIDs werden benutzt, um bestimmte physikalische Zeilen durch Block und Offset 
Werte zu identifizieren. CTIDs verändern sich, sobald Zeilen verändert oder 
zurückgeladen werden. Sie werden in Indexeinträgen benutzt um auf die 
physikalischen Zeilen zu zeigen.

(http://sql-info.de/de/postgresql/FAQ_german.html#4.11.2)

Gruß
Olaf




Mehr Informationen über die Mailingliste linux-l