PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Erro do Postgres:mais de uma linha retornada por uma subconsulta usada como expressão


Tecnicamente , para reparar seu extrato, você pode adicionar LIMIT 1 para a subconsulta para garantir que no máximo 1 linha seja retornada. Isso removeria o erro, seu código ainda seria um absurdo.
... 'SELECT store_key FROM store LIMIT 1' ...

Praticamente , você deseja corresponder as linhas de alguma forma em vez de escolher uma linha arbitrária da tabela remota store para atualizar cada linha de sua tabela local customer .
Sua pergunta rudimentar não fornece detalhes suficientes, então estou supondo uma coluna de texto match_name em ambas as tabelas (e UNIQUE em store ) por causa deste exemplo:
... 'SELECT store_key FROM store
     WHERE match_name = ' || quote_literal(customer.match_name)  ...

Mas essa é uma maneira extremamente cara de fazer as coisas.

Idealmente , você reescreve completamente a instrução.
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;

Isso corrige uma série de problemas em sua declaração original.

Obviamente, o problema básico levando ao seu erro é corrigido.

Normalmente é melhor juntar relações adicionais no FROM cláusula de um UPDATE instrução do que executar subconsultas correlacionadas para cada linha individual.

Ao usar dblink, o acima se torna mil vezes mais importante. Você não quer chamar dblink() para cada linha, isso é extremamente caro . Chame-o uma vez para recuperar todas as linhas que você precisa.

Com subconsultas correlacionadas, se nenhuma linha for encontrada na subconsulta, a coluna é atualizada para NULL, o que quase sempre não é o que você deseja. Na minha consulta atualizada, a linha só é atualizada se uma linha correspondente for encontrada. Caso contrário, a linha não é tocada.

Normalmente, você não gostaria de atualizar as linhas, quando nada realmente muda. Isso é caro não fazer nada (mas ainda produz linhas mortas). A última expressão no WHERE cláusula impede tais atualizações vazias :
     AND   c.customer_id IS DISTINCT FROM sub.store_key

Relacionado:
  • Como posso (ou posso) SELECT DISTINCT em várias colunas?