这个问题很老,但是我觉得还没有给出最好的答案。
是否有UPDATE语法... 未指定列名?
动态SQL的一般解决方案
您不需要知道任何列名,只需加入一些唯一的列即可(id在示例中)。我可以想到的任何可能的情况都可以可靠地工作。
这是特定于PostgreSQL的。我正在基于information_schema构建动态代码,特别information_schema.columns是基于SQL标准中定义的table的表,并且大多数主要的RDBMS(Oracle除外)都有它。但是DO带有执行动态SQL的PL / pgSQL代码的语句完全是非标准的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 是可选的,以更新选定的行。
SQL提琴。
相关答案以及更多说明:
使用纯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提琴。
在问这个问题很久之前,Postgres 8.2就在2006年引入了此语法。手册中的详细信息。
有关:
带有列列表 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。
根据您对两个表的了解,可能有多种变体。