PostgreSQLs ON CONFLICT DO NOTHING
und Datenabruf
Bei Verwendung der ON CONFLICT DO NOTHING
-Klausel von PostgreSQL mit RETURNING
werden leere Ergebnisse zurückgegeben, wenn Konflikte auftreten. Dies liegt daran, dass DO NOTHING
keine Zeilen aktualisiert oder zurückgibt. In diesem Artikel werden Lösungen zum Abrufen von Daten untersucht, selbst wenn Konflikte auftreten.
Herausforderungen und Einschränkungen bestehender Ansätze
Bestehende Methoden beheben dieses Problem häufig für einzelne Konfliktziele und einfache Bedingungen. Diese Ansätze können jedoch Einschränkungen und mögliche Nebenwirkungen haben.
Robuste Lösungen für den Datenabruf
Wir stellen zwei verbesserte Ansätze vor, um Konflikte effektiv zu behandeln und den Datenabruf sicherzustellen, indem wir gleichzeitige Schreibszenarien berücksichtigen:
1. Umgang mit Konflikten ohne gleichzeitige Schreibvorgänge
Diese Methode verwendet einen Common Table Expression (CTE), um INSERT
- und SELECT
-Operationen zu trennen. Die Ergebnisse werden mit UNION ALL
.
<code class="language-sql">WITH input_rows(usr, contact, name) AS ( VALUES ('foo1', 'bar1', 'bob1') , ('foo2', 'bar2', 'bob2') -- more? ) , ins AS ( INSERT INTO chats (usr, contact, name) SELECT * FROM input_rows ON CONFLICT (usr, contact) DO NOTHING RETURNING id ) SELECT 'i' AS source, id FROM ins UNION ALL SELECT 's' AS source, c.id FROM input_rows JOIN chats c USING (usr, contact);</code>
Diese Abfrage versucht zunächst, einzufügen. Anschließend werden vorhandene Zeilen ausgewählt, die den Eingabedaten entsprechen. Die Spalte source
gibt an, ob eine Zeile eingefügt ('i') oder ausgewählt ('s') wurde.
2. Umgang mit Konflikten mit gleichzeitigen Schreibvorgängen
Diese robustere Lösung berücksichtigt gleichzeitige Schreibvorgänge. Es sucht nach fehlenden Zeilen innerhalb der Abfrage und verwendet ein zusätzliches UPSERT
, um diese zu verarbeiten.
<code class="language-sql">WITH input_rows(usr, contact, name) AS ( ... ) -- as above , ins AS ( INSERT INTO chats (usr, contact, name) SELECT * FROM input_rows ON CONFLICT (usr, contact) DO NOTHING RETURNING id, usr, contact ) , sel AS ( SELECT 'i' AS source, id, usr, contact FROM ins UNION ALL SELECT 's' AS source, c.id, usr, contact FROM input_rows JOIN chats c USING (usr, contact) ) , ups AS ( INSERT INTO chats (usr, contact, name) SELECT i.* FROM input_rows i LEFT JOIN sel s USING (usr, contact) WHERE s.usr IS NULL ON CONFLICT (usr, contact) DO UPDATE SET name = c.name -- or EXCLUDED.name RETURNING 'u' AS source, id ) SELECT source, id FROM sel UNION ALL SELECT * FROM ups;</code>
Dieser Ansatz stellt sicher, dass alle eingefügten oder aktualisierten Zeilen zurückgegeben werden, unabhängig von Konflikten oder gleichzeitigen Aktualisierungen. Der ups
CTE verarbeitet alle Zeilen, die im ersten INSERT
fehlen. Die Spalte source
unterscheidet zwischen eingefügten ('i'), ausgewählten ('s') und aktualisierten ('u') Zeilen. Dies bietet eine umfassende Lösung zum Abrufen von Daten unter verschiedenen Bedingungen.
Das obige ist der detaillierte Inhalt vonWie rufe ich Daten ab, wenn ich PostgreSQLs ON CONFLICT DO NOTHING mit RETURNING verwende?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!