Es stimmt, wie bereits erwähnt, dass der RETURNING
-Klausel eines INSERT
sieht nur die eingefügte Zeile. Genauer gesagt, das Handbuch hier zitieren :
Fett Hervorhebung von mir.
Also hält Sie nichts davon ab, eine korrelierte Unterabfrage hinzuzufügen zum RETURNING
Liste:
INSERT INTO employees.password_resets AS ep
(empl_pwd_reset_uuid , empl_user_pvt_uuid , t_valid , for_empl_user_pvt_uuid, token)
SELECT 'f70a0346-a077-11eb-bd1a-aaaaaaaaaaaa', '6efc2b7a-f27e-11ea-b66c-de1c405de048', '2021-04-18 19:57:47.111365', eu.empl_user_pvt_uuid , '19d65aea-7c4a-41bc-b580-9d047f1503e6'
FROM employees.users eu
WHERE empl_user_pub_uuid = 'e2bb39f1f28011eab66c63cb4d9c7a34'
RETURNING for_empl_user_pvt_uuid AS empl_user_pvt_uuid -- alias to meet your org. query
, (SELECT email
FROM employees.emails
WHERE empl_user_pvt_uuid = ep.empl_user_pvt_uuid
ORDER BY t DESC -- NULLS LAST ?
LIMIT 1
) AS email
, (SELECT name_first
FROM employees.profiles
WHERE empl_user_pvt_uuid = ep.empl_user_pvt_uuid
-- ORDER BY ???
LIMIT 1
) AS name_first;
Dies ist auch viel effizienter als Ihre Anfrage (oder was vorgeschlagen wurde) aus mehreren Gründen.
-
Wir führen die Unterabfragen
ee
nicht aus undep
über alle Zeilen der Tabellenemployees.emails
undemployees.profiles
. Das wäre effizient, wenn wir große Teile dieser Tabellen benötigen, aber wir holen nur eine einzige interessante Zeile aus jeder. Mit entsprechenden Indizes ist dafür eine korrelierte Unterabfrage wesentlich effizienter. Siehe: -
Wir fügen den Overhead eines oder mehrerer CTEs nicht hinzu.
-
Zusätzliche Daten werden erst nach abgerufen ein erfolgreiches
INSERT
, sodass keine Zeit verschwendet wird, wenn die Beilage aus irgendeinem Grund nicht durchgegangen ist. (Siehe Zitat oben!)
Außerdem, möglicherweise am wichtigsten, ist dies richtig . Wir verwenden Daten aus der Zeile, die tatsächlich eingefügt wurde - after Einfügen. (Siehe Zitat oben!) Nachdem mögliche Standardwerte, Auslöser oder Regeln angewendet wurden. Wir können sicher sein, dass das, was wir sehen, tatsächlich (derzeit) in der Datenbank ist.
Sie haben kein ORDER BY
für profiles.name_first
. Das ist nicht richtig. Entweder gibt es nur eine qualifizierende Zeile, dann brauchen wir kein DISTINCT
noch LIMIT 1
. Oder es können mehrere sein, dann brauchen wir auch ein deterministisches ORDER BY
um ein deterministisches Ergebnis zu erhalten.
Und wenn emails.t
NULL sein kann, sollten Sie NULLS LAST
hinzufügen im Feld ORDER BY
Klausel. Siehe:
Indizes
Idealerweise haben Sie diese mehrspaltigen Indizes (mit Spalten in dieser Reihenfolge):
users (empl_user_pub_uuid, empl_user_pvt_uuid)
emails (empl_user_pvt_uuid, email)
profiles (empl_user_pvt_uuid, name_first)
Dann, wenn die Tabellen ausreichend evakuiert sind, erhalten Sie drei Nur-Index-Scans und die ganze Operation geht blitzschnell.
Pre-INSERT
abrufen Werte?
Wenn Sie das wirklich wollen (was Sie meiner Meinung nach nicht tun), überlegen Sie: