2つの個別のデータベースがあります。 1つのデータベースの列を他のデータベースの列の値に更新しようとしています。
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
何か案は?
Technically、ステートメントを修復するには、サブクエリに_LIMIT 1
_を追加できます最大で1行が返されるようにします。それはエラーを取り除くでしょう、あなたのコードはまだナンセンスです。
_... 'SELECT store_key FROM store LIMIT 1' ...
_
Practically、行を一致させたいsomehow任意のピッキングの代わりにリモートテーブルstore
の行を使用して、ローカルテーブルcustomer
のすべての行を更新します。
初歩的な質問では十分な詳細情報が得られないため、assumingテキスト列_match_name
_この例のために、両方のテーブル(およびUNIQUE
のstore
)で:
_... 'SELECT store_key FROM store
WHERE match_name = ' || quote_literal(customer.match_name) ...
_
しかし、それは物事を行う非常に高価な方法です。
Ideally、ステートメントを完全に書き換える必要があります。
_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;
_
これにより、元のステートメントの多くの問題が改善されます。
明らかに、エラーにつながるbasic problemは修正されています。
ほとんどの場合、FROM
ステートメントの UPDATE
句 で追加の関係に参加する方が、個々の行ごとにcorrelated subqueriesを実行するよりも優れています。
Dblinkを使用する場合、上記は1000倍重要になります。 1行ごとにdblink()
を呼び出したくありません。つまり、非常に高価ですです。一度呼び出して、必要なすべての行を取得します。
相関サブクエリでは、サブクエリで行が見つからないの場合、列はNULLに更新されますが、これはほとんどの場合、希望どおりではありません。
更新されたフォームでは、一致する行が見つかった場合にのみ行が更新されます。それ以外の場合、行は触れられません。
通常、実際に何も変更されていない場合、行を更新することは望ましくありません。それは何もしませんが、それでも無駄な行を生成します。 WHERE
句の最後の式は、そのようなempty updatesを防ぎます。
_ AND c.customer_id IS DISTINCT FROM sub.store_key
_
これは、ネストされたSELECTが複数の行を返すことを意味します。
適切なWHERE句を追加する必要があります。
基本的な問題は、多くの場合、=
からIN
、1対多の関係がある場合。たとえば、特定の顧客の一連のアカウントを更新または削除する場合:
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
);
このエラーは、SELECT store_key FROM store
クエリがSERVER1
データベースに2つ以上の行を返したことを意味します。すべての顧客を更新する場合は、スカラー=
演算子の代わりに結合を使用します。そのためには、顧客を「接続」してアイテムを保存する条件が必要です。
すべてのcustomer_id
sを同じstore_key
に更新する場合は、クエリが単一の行を返すように、リモートで実行されるWHERE
にSELECT
句を指定する必要があります。
クエリによって生成された結果には、適切な処理を必要とする行がありません。1のようなクエリで有効なハンドラを指定すると、この問題を解決できます。単一の行を返す「max(column)」を選択します