Mit Postgres 9.6, ich habe die Strategie in https://stackoverflow.com/a/40325406/435563 empfohlen folgte ein INSERT
oder SELECT
und die daraus gewonnenen Ergebnisse id zu tun: nichtsINSERT oder SELECT-Strategie, um immer eine Zeile zurückzugeben?
with ins as (
insert into prop (prop_type, norm, hash, symbols)
values (
$1, $2, $3, $4
) on conflict (hash) do
update set prop_type = 'jargon' where false
returning id)
select id from ins
union all
select id from prop where hash = $3
jedoch manchmal zurück. Ich hätte erwartet, dass es eine Zeile egal was zurückgeben würde. Wie kann ich es reparieren, um sicherzustellen, dass es immer eine ID zurückgibt?
NB, obwohl keine Zeile zurückgegeben wird, scheint die Zeile bei der Inspektion zu existieren. Ich glaube, dass das Problem damit verbunden sein kann, den gleichen Datensatz über zwei Sitzungen gleichzeitig hinzuzufügen.
Die betreffende Tabelle ist wie folgt definiert:
create table prop (
id serial primary key,
prop_type text not null references prop_type(name),
norm text not null,
hash text not null unique,
symbols jsonb
);
Daten:
EDT DETAIL: parameters: $1 = 'jargon', $2 = 'j2', $3 = 'lXWkZSmoSE0mZ+n4xpWB', $4 = '[]'
Wenn ich prop_type = 'jargon'
ändern prop_type = 'foo'
es funktioniert! Es scheint, dass die Sperre nicht genommen wird, wenn der Ausdruck selbst unter der where false
Klausel nichts ändern würde. Muss das wirklich davon abhängen, dass ich einen Wert erraten habe, der nicht in der Reihe wäre? Oder gibt es einen besseren Weg, um sicherzustellen, dass Sie das Schloss bekommen?
--- UPDATE ---
Die Gesamtsituation ist, dass die Anwendung versucht, einen gerichteten azyklischen Graphen mit einem Verbindungspool (... mit autocommit) zu speichern, und wurde mit dieser Abfrage zu erhalten ID beim Duplizieren von Duplikaten. [Es stellt sich heraus, dass es viel klüger ist, eine Transaktion zu verwenden und nur zu einer Verbindung zu serialisieren. Aber das Verhalten, wenn Streit gibt es hier ungerade]
Der Fremdschlüssel scheint nicht um den Einsatz zu beeinflussen - zB.
create table foo(i int unique, prop_id int references prop(id));
insert into foo values (1, 208);
insert into foo values (1, 208)
on conflict (i) do update set prop_id = 208 where false;
--> INSERT 0 0
insert into foo values (1, 208)
on conflict (i) do update set prop_id = -208 where false;
--> INSERT 0 0
Hinweis eines mit gültigen fk 208, das andere mit ungültigen -208. Wenn ich ein select auf eines dieser beiden Elemente mit dem vollständigen Muster verbinde, geben beide in Situationen ohne Konkurrenz i = 1 zurück, wie erwartet.
bitte Datenabtastwert Post als auch, wenn im nicht irre es immer eine Zeile zurückgeben, so könnte man sogar von xmin sagen, xmax, wenn es wurde aktualisiert oder eingefügt –
Daten hinzugefügt. Ich denke, es ist mit der Anwendung verwandt, die versucht, eine komplexe Datenstruktur zu speichern, in der dieses Blatt zweimal unter Verwendung eines Verbindungspools angezeigt wird. Der Datensatz wird also in zwei verschiedenen Verbindungen hinzugefügt. – shaunc
mit Ihrem Update habe ich festgestellt, wo falsch, was Update nicht passieren - mit dieser Antwort wird anders sein :) –