sql >> Databasteknik >  >> RDS >> PostgreSQL

Postgres-fel:Mer än en rad returneras av en underfråga som används som uttryck

Tekniskt , för att reparera ditt kontoutdrag kan du lägga till LIMIT 1 till underfrågan för att säkerställa att högst 1 rad returneras. Det skulle ta bort felet, din kod skulle fortfarande vara nonsens.

... 'SELECT store_key FROM store LIMIT 1' ...

Praktiskt taget , vill du matcha rader på något sätt istället för att välja en godtycklig rad från fjärrtabellen store för att uppdatera varje rad i din lokala tabell customer .
Din rudimentära fråga ger inte tillräckligt med detaljer, så jag utgår ifrån en textkolumn match_name i båda tabellerna (och UNIQUE i store ) för detta exempel:

... 'SELECT store_key FROM store
     WHERE match_name = ' || quote_literal(customer.match_name)  ...

Men det är ett extremt dyrt sätt att göra saker på.

Helst , skriver du om uttalandet helt.

UPDATE customer c
SET    customer_id = s.store_key
FROM   dblink('port=5432, dbname=SERVER1 user=postgres password=309245'
            , 'SELECT match_name, store_key FROM store')
       AS s(match_name text, store_key integer)
WHERE c.match_name = s.match_name
AND   c.customer_id IS DISTINCT FROM s.store_key;

Detta åtgärdar ett antal problem i ditt ursprungliga uttalande.

Uppenbarligen är det grundläggande problemet som leder till ditt fel är åtgärdat.

Det är vanligtvis bättre att gå med i ytterligare relationer i FROM sats i en UPDATE än att köra korrelerade underfrågor för varje enskild rad.

När du använder dblink blir ovanstående tusen gånger viktigare. Du vill inte anropa dblink() för varje enskild rad är det extremt dyrt . Ring det en gång för att hämta alla rader du behöver.

Med korrelerade underfrågor, om ingen rad hittas i underfrågan uppdateras kolumnen till NULL, vilket nästan alltid inte är vad du vill ha. I min uppdaterade fråga uppdateras raden bara om en matchande rad hittas. Annars berörs inte raden.

Normalt skulle du inte vilja uppdatera rader när ingenting faktiskt förändras. Det är dyrt att göra ingenting (men ger fortfarande döda rader). Det sista uttrycket i WHERE klausul förhindrar sådana tomma uppdateringar :

     AND   c.customer_id IS DISTINCT FROM sub.store_key

Relaterat:

  • Hur väljer jag (eller kan jag) DISTINCT på flera kolumner?


  1. Hur man får rekord med maxvärde i MySQL

  2. Hur MATCH MOT fungerar i MariaDB

  3. SQLite uttrycksbaserat index

  4. Rätt sätt att hantera dubbelriktad 1:m i Green-DAO