PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

RETURNING verursacht Fehler:fehlender FROM-Klauseleintrag für Tabelle

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.

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: