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