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

Postgres-Fehler:Mehr als eine Zeile, die von einer als Ausdruck verwendeten Unterabfrage zurückgegeben wird

Technisch , um Ihre Aussage zu reparieren, können Sie LIMIT 1 hinzufügen an die Unterabfrage, um sicherzustellen, dass höchstens 1 Zeile zurückgegeben wird. Das würde den Fehler beseitigen, dein Code wäre immer noch Unsinn.

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

Praktisch , möchten Sie Zeilen irgendwie abgleichen anstatt eine beliebige Zeile aus der entfernten Tabelle store auszuwählen um jede Zeile Ihrer lokalen Tabelle customer zu aktualisieren .
Ihre rudimentäre Frage liefert nicht genügend Details, also gehe ich annehmen eine Textspalte match_name in beiden Tabellen (und UNIQUE im store ) für dieses Beispiel:

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

Aber das ist eine extrem teure Methode.

Im Idealfall , schreiben Sie die Anweisung komplett neu.

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;

Dies behebt eine Reihe von Problemen in Ihrer ursprünglichen Anweisung.

Offensichtlich das grundlegende Problem was zu Ihrem Fehler führt, wird behoben.

Normalerweise ist es besser, zusätzliche Relationen in FROM einzufügen -Klausel eines UPDATE Anweisung statt korrelierte Unterabfragen auszuführen für jede einzelne Zeile.

Bei der Verwendung von dblink wird das Obige tausendmal wichtiger. Sie möchten dblink() nicht aufrufen für jede einzelne Zeile ist das extrem teuer . Rufen Sie es einmal auf, um alle benötigten Zeilen abzurufen.

Bei korrelierten Unterabfragen, wenn keine Zeile gefunden wird in der Unterabfrage wird die Spalte auf NULL aktualisiert, was fast immer nicht das ist, was Sie wollen. In meiner aktualisierten Abfrage wird die Zeile nur aktualisiert, wenn eine übereinstimmende Zeile gefunden wird. Andernfalls wird die Zeile nicht berührt.

Normalerweise möchten Sie Zeilen nicht aktualisieren, wenn sich eigentlich nichts ändert. Das ist teuer, nichts zu tun (aber immer noch tote Zeilen zu produzieren). Der letzte Ausdruck im WHERE -Klausel verhindert solche leeren Updates :

     AND   c.customer_id IS DISTINCT FROM sub.store_key

Verwandte:

  • Wie kann ich (oder kann ich) DISTINCT für mehrere Spalten auswählen?