这个问题很老,但我觉得还没有给出最好的答案。
是否有UPDATE
语法...而不指定列名?
使用动态 SQL 的通用解决方案
id
除了要加入的一些唯一列(在示例中)之外,您不需要知道任何列名。对于我能想到的任何可能的极端情况都能可靠地工作。
这是 PostgreSQL 特有的。我正在基于information_schema构建动态代码,特别是 table information_schema.columns
,它在 SQL 标准中定义,大多数主要的 RDBMS(Oracle 除外)都有它。但是带有执行动态 SQL 的PL/pgSQLDO
代码的语句是完全非标准的 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
假设 中的每一列都有一个匹配的列a
,但反之则不然。b
可以有额外的列。
WHERE b.id = 123
是可选的,用于更新选定的行。
db<>fiddle here
旧sqlfiddle
更多解释的相关答案:
使用纯 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;
db<>fiddle here
旧sqlfiddle
这种语法是在 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
旧sqlfiddle
这是除FROM
子句外的标准 SQL 。
无论实际存在哪些列,它都有效A
,但查询无法区分实际的 NULL 值和缺失的列,因此只有在定义A
了所有列时才可靠。A
NOT NULL
有多种可能的变化,这取决于您对这两个表的了解。