postgresql Postgres错误:用作表达式的子查询返回多行

olhwl3o2  于 2022-12-18  发布在  PostgreSQL
关注(0)|答案(6)|浏览(293)

我有两个独立的数据库。我正在尝试将一个数据库中的列更新为另一个数据库中的列的值:

UPDATE customer
SET customer_id=
   (SELECT t1 FROM dblink('port=5432, dbname=SERVER1 user=postgres password=309245',
   'SELECT store_key FROM store') AS (t1 integer));

这是我收到的错误:

ERROR:  more than one row returned by a subquery used as an expression

有什么想法吗?

np8igboo

np8igboo1#

从技术上讲,要删 debugging 误,请将**LIMIT 1**添加到子查询中,以最多返回1行。该语句仍然是无意义的。

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

实际上,您希望 * 以某种方式 * 匹配行,而不是从远程表store中选取任意一行来更新本地表customer的每一行。

在这个例子中,我 * 假设 * 两个表中都有一个文本列match_nameUNIQUEstore中):

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

但这是一种极其昂贵的做事方式。

理想情况下,您可以完全重写语句。

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;


这纠正了你原来陈述中的一些问题。
显然,基本错误已修复。
通常,在FROM clause of an UPDATE statement中加入额外的关系要比为每一行运行相关子查询要好。
当使用dblink时,上面的内容会变得更加重要一千倍。你不想为每一行调用dblink(),这是极其昂贵的。调用一次就可以检索到你需要的所有行。
使用相关子查询时,如果在子查询中没有找到行,则列将更新为NULL,这几乎总是不符合您的要求。在我的更新查询中,只有找到匹配行时,才会更新该行。否则,不会触及该行。
通常情况下,当实际上什么都没有改变时,你不想更新行,这样做代价很高(但仍然会产生死行),WHERE子句中的最后一个表达式防止了这样的空更新

AND   c.customer_id IS DISTINCT FROM sub.store_key

相关:

  • 如何(或可以)对多列执行SELECT DISTINCT操作?
ckocjqey

ckocjqey2#

在具有一对多关系的情况下,通常可以通过将=更改为**IN**来简单地解决基本问题。例如,如果要更新或删除给定客户的一组帐户:

WITH accounts_to_delete AS 
    ( 
        SELECT     account_id
        FROM       accounts a
        INNER JOIN customers c
                ON a.customer_id = c.id
        WHERE      c.customer_name='Some Customer'
    )

-- this fails if "Some Customer" has multiple accounts, but works if there's 1:
DELETE FROM accounts
 WHERE accounts.guid = 
( 
    SELECT account_id 
    FROM   accounts_to_delete 
);

-- this succeeds with any number of accounts:
DELETE FROM accounts
 WHERE accounts.guid IN   
( 
    SELECT account_id 
    FROM   accounts_to_delete 
);
5uzkadbs

5uzkadbs3#

这意味着嵌套SELECT返回多行。
您需要向其中添加适当的WHERE子句。

z31licg0

z31licg04#

此错误意味着SELECT store_key FROM store查询在SERVER1数据库中返回了两行或更多行。如果要更新所有客户,请使用联接而不是标量=运算符。要执行此操作,您需要一个将客户“连接”到存储项目的条件。
如果希望将所有customer_id更新为同一个store_key,则需要为远程执行的SELECT提供WHERE子句,以便查询返回单个行。

2sbarzqh

2sbarzqh5#

USE LIMIT 1 -因此它将只返回1行。示例
客户ID-(从枚举中选择
ID
,其中enumerations.name =“准备开票”限制1)

b09cbbtk

b09cbbtk6#

查询生成的结果是没有需要正确处理的行。如果在查询中提供有效的处理程序,如1.将查询限制为返回单个行2.也可以通过提供将返回单个行的“select max(column)”来解决此问题

相关问题