質問は古いですが、最良の答えはまだ得られていないと感じました。
列名を指定せずにUPDATE構文... はありますか?
動的SQLを使用した一般的なソリューション
結合する一意の列(id例)を除いて、列名を知る必要はありません。考えられるあらゆるコーナーケースで確実に機能します。
これはPostgreSQLに固有です。information_schemaに基づいて動的コードを構築しています。特にinformation_schema.columns、SQL標準で定義されているtable であり、ほとんどの主要なRDBMS(Oracleを除く)がそれを持っています。しかし、動的SQLを実行するPL / pgSQLコードDOを含むステートメントは、完全に非標準のPostgreSQL構文です。
DO
$do$
BEGIN
EXECUTE (
SELECT
'UPDATE b
SET (' || string_agg( quote_ident(column_name), ',') || ')
= (' || string_agg('a.' || quote_ident(column_name), ',') || ')
FROM a
WHERE b.id = 123
AND a.id = b.id'
FROM information_schema.columns
WHERE table_name = 'a' -- table name, case sensitive
AND table_schema = 'public' -- schema name, case sensitive
AND column_name <> 'id' -- all columns except id
);
END
$do$;
のすべての列bについて一致する列があると想定しますが、逆の場合は想定しません。追加の列を含めることができます。ab
WHERE b.id = 123 選択した行を更新するためのオプションです。
SQL Fiddle。
関連する回答と詳細な説明:
プレーンSQLによる部分的なソリューション
共有列のリスト
両方のテーブルが共有する列名のリストを知る必要があります。複数の列を更新するための構文ショートカットを使用-これまでのところ、他の回答がこれまでに提案していたものよりも短くなっています。
UPDATE b
SET ( column1, column2, column3)
= (a.column1, a.column2, a.column3)
FROM a
WHERE b.id = 123 -- optional, to update only selected row
AND a.id = b.id;
SQL Fiddle。
この構文は、質問されるずっと前に、2006年にPostgres 8.2で導入されました。 マニュアルの詳細。
関連:
の列のリスト B
のすべての列Aが定義されている場合NOT NULL(ただし、必ずしも必要Bでは
ありません)の列名がわかっている場合B(ただし、必ずしもそうである必要はありませんA)。
UPDATE b
SET (column1, column2, column3, column4)
= (COALESCE(ab.column1, b.column1)
, COALESCE(ab.column2, b.column2)
, COALESCE(ab.column3, b.column3)
, COALESCE(ab.column4, b.column4)
)
FROM (
SELECT *
FROM a
NATURAL LEFT JOIN b -- append missing columns
WHERE b.id IS NULL -- only if anything actually changes
AND a.id = 123 -- optional, to update only selected row
) ab
WHERE b.id = ab.id;
NATURAL LEFT JOIN行を結合b同じ名前のすべての列が同じ値を保持する場合。この場合、更新は必要なく(何も変更されません)、プロセスの早い段階でそれらの行を削除できます(WHERE b.id IS NULL)。
一致する行を見つける必要があるためb.id = ab.id、外側のクエリを使用します。
db <> fiddle here
Old sqlfiddle。
これは、FROM句を除いて標準SQL です。
どの列が実際に存在してAいても機能しますが、クエリは実際のNULL値と欠落している列を区別できないためA、すべての列Aが定義されている場合にのみ信頼できますNOT NULL。
両方のテーブルについての知識に応じて、複数の可能なバリエーションがあります。