Referenzwert der seriellen Spalte in einer anderen Spalte während des gleichen INSERT

8

Ich habe eine Tabelle mit einem SERIAL-Primärschlüssel und auch eine ltree-Spalte, deren Wert ich die Verkettung dieser Primärschlüssel sein möchte. z.B.

%Vor%

Ich bin gespannt, ob es eine Möglichkeit gibt, eine solche Einfügung in einer Abfrage durchzuführen, z. B.

%Vor%

Ich übertreibe wahrscheinlich hier und versuche, in einer Abfrage zu tun, was ich in zwei (in einer Transaktion gruppiert) tun sollte.

    
Aaron Fi 14.09.2012, 23:06
quelle

2 Antworten

7

Sie können eine Unterabfrage oder ein beschreibbares CTE verwenden, um den Wert aus der Sequenz einmal abzurufen und wiederholt zu verwenden :

%Vor%

Daten modifizierendes CTE erfordert Postgres 9.1 oder höher .

Wenn Sie sich über den Namen der Sequenz, die Sie verwenden können, nicht sicher sind pg_get_serial_sequence() stattdessen:

%Vor%

Wenn der Tabellenname "foo" möglicherweise nicht für alle Schemata in der Datenbank eindeutig ist, können Sie ihn mit einem Schema qualifizieren. Und wenn die Schreibweise eines beliebigen Namens nicht standardisiert ist, müssen Sie eine doppelte Anführungszeichen verwenden:

%Vor%


Schnelltests zeigten Marks Idee mit lastval() könnte auch funktionieren:

%Vor%
  • Sie können id nur aus der Abfrage herauslassen, die Spalte serial wird automatisch zugewiesen. Macht keinen Unterschied.

  • Es sollte keine Wettlaufbedingung zwischen den Reihen geben. Ich zitiere das Handbuch :

  

currval

     

Gibt den Wert zurück, den nextval zuletzt für diese Sequenz in der aktuellen Sitzung erhalten hat. (Ein Fehler wird gemeldet, wenn nextval hat   nie für diese Sequenz in dieser Sitzung aufgerufen worden.) Weil das ist   Wenn Sie einen sitzungslokalen Wert zurückgeben, erhalten Sie eine vorhersehbare Antwort   oder andere Sitzungen haben nextval seit der aktuellen Sitzung ausgeführt   haben.

     

lastval

     

Gibt den Wert zurück, der zuletzt von nextval in der aktuellen Sitzung zurückgegeben wurde. Diese Funktion ist identisch mit currval, außer anstelle von   Nimmt man den Sequenznamen als Argument, wird der Wert von   letzte von nextval in der aktuellen Sitzung verwendete Sequenz. Es ist ein Fehler   lastval aufrufen, wenn nextval noch nicht im aktuellen aufgerufen wurde   Sitzung.

Fett Hervorhebung meins.

Aber , wie , es kann doch scheitern. Auf den zweiten Gedanken hin macht das Sinn: Es gibt keine Garantie dafür, dass der Standardwert gefüllt wird (und nextval() wird im Prozess aufgerufen) , bevor lastval() aufgerufen wird, um die zweite Spalte ltree zu füllen. Also bleiben Sie bei der ersten Lösung und nextval() , um sicher zu sein.

    
Erwin Brandstetter 15.09.2012, 00:08
quelle
3

Das hat in meinem Test funktioniert:

%Vor%

Ich denke, es gibt dort eine Race-Bedingung, wenn zwei INSERTs zur gleichen Zeit stattfinden, da diese den letzten Sequenzwert anstelle der aktuellen Zeile referenzieren. Ich wäre persönlich eher dazu geneigt (Pseudo-Code):

%Vor%     
Mark Stosberg 14.09.2012 23:38
quelle