use*_*502 30 sql database postgresql dblink subquery
我有两个独立的数据库.我试图将一个数据库中的列更新为另一个数据库中的列的值:
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));
Run Code Online (Sandbox Code Playgroud)
这是我收到的错误:
Run Code Online (Sandbox Code Playgroud)ERROR: more than one row returned by a subquery used as an expression
有任何想法吗?
Erw*_*ter 49
从技术上讲,要修复语句,可以添加LIMIT 1到子查询以确保最多返回1行.这将删除错误,您的代码仍然是无稽之谈.
... 'SELECT store_key FROM store LIMIT 1' ...Run Code Online (Sandbox Code Playgroud)
实际上,您希望以某种方式匹配行,而不是从远程表中选择任意行store来更新本地表的每一行customer.
你的基本问题没有提供足够的细节,所以为了这个例子,我在两个表(和in)中假设一个文本列:match_nameUNIQUEstore
... 'SELECT store_key FROM store
WHERE match_name = ' || quote_literal(customer.match_name) ...Run Code Online (Sandbox Code Playgroud)
但这是一种非常昂贵的做事方式.
理想情况下,您应该完全重写该语句.
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;
Run Code Online (Sandbox Code Playgroud)
这可以解决您原始声明中的许多问题.
显然,导致错误的基本问题是固定的.
在语句的FROM子句中UPDATE加入其他关系而不是为每个单独的行运行相关子查询几乎总是更好.
使用dblink时,上面的重要性要高出千倍.你不想dblink()为每一行打电话,这是非常昂贵的.调用一次以检索所需的所有行.
使用相关子查询,如果在子查询中找不到行,则列会更新为NULL,这几乎总是不是您想要的.
在我更新的表单中,只有找到匹配的行才会更新行.否则,行不会被触及.
通常,当没有任何实际更改时,您不希望更新行.那是昂贵的无所事事(但仍会产生死行).WHERE子句中的最后一个表达式可防止此类空更新:
AND c.customer_id IS DISTINCT FROM sub.store_key
Run Code Online (Sandbox Code Playgroud)rot*_*ial 13
在一对多关系的情况下,基本问题通常可以通过更改=to来简单解决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
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
90236 次 |
| 最近记录: |