SQL 从一个表的字段更新另一个表的字段

我有两张桌子:

A [ID, column1, column2, column3]
B [ID, column1, column2, column3, column4]

A将始终是 B的子集(意味着 A的所有列也在 B中)。

我想用 B中特定的 ID更新一条记录,用 A中所有列的数据更新它们。这个 ID同时存在于 AB中。

有没有一种 UPDATE语法或者其他方法可以不指定列名,只说 “设置所有 A 栏”就可以做到这一点?

我使用的是 PostgreSQL,因此也接受一个特定的非标准命令(但不是首选命令)。

225019 次浏览

您可以构建和执行动态 sql 来完成这项工作,但是它实际上并不理想

试试跟踪

Update A a, B b, SET a.column1=b.column1 where b.id=1

编辑:-更新多个栏目

Update A a, B b, SET a.column1=b.column1, a.column2=b.column2 where b.id=1

不一定是你问的,但也许使用 postgres 继承可能会有帮助?

CREATE TABLE A (
ID            int,
column1       text,
column2       text,
column3       text
);


CREATE TABLE B (
column4       text
) INHERITS (A);

这就避免了更新 B 的需要。

但是一定要读完所有的 详情

否则,您所要求的就不被认为是一个好的实践——不鼓励使用 SELECT * ...的视图这样的动态内容(因为这种轻微的便利可能会破坏比帮助更多的内容) ,而且您所要求的内容对于 UPDATE ... SET命令来说是等价的。

您可以使用非标准的 来自子句。

UPDATE b
SET column1 = a.column1,
column2 = a.column2,
column3 = a.column3
FROM a
WHERE a.id = b.id
AND b.id = 1

这个问题很老了,但我觉得最好的答案还没有给出。

有没有 UPDATE语法... 而不指定列名

动态 SQL 通用解决方案

只知道两个表的主键列

您不需要知道任何列名,只需要知道一些要加入的唯一列(示例中为 id)。对任何我能想到的可能的角落案件都可靠。

这是 PostgreSQL 特有的。我正在构建基于 Information _ schema的动态代码,特别是表 information_schema.columns,它是在 SQL 标准中定义的,大多数主要的 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是可选的,用于更新选定的行。

分贝 < > 小提琴 给你
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;

分贝 < > 小提琴 给你
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在外部查询中。

分贝 < > 小提琴 给你
Sqlfiddle

这是标准的 SQL 除了 FROM条款
无论 A中实际存在哪些列,它都可以工作,但是查询无法区分实际的 NULL 值和 A中缺少的列,因此只有在 A中的所有列都定义为 NOT NULL时,它才是可靠的。

有多种可能的变化,这取决于您对这两个表的 知道

这真是帮了大忙,密码

UPDATE tbl_b b
SET   (  column1,   column2,   column3)
= (a.column1, a.column2, a.column3)
FROM   tbl_a a
WHERE  b.id = 1
AND    a.id = b.id;

效果很好。

注意到您需要在

From "tbl_a" a

才能成功。

我使用 IBM DB2数据库工作了十多年,现在尝试学习 PostgreSQL。

它适用于 PostgreSQL 9.3.4,但不适用于 DB210.5:

UPDATE B SET
COLUMN1 = A.COLUMN1,
COLUMN2 = A.COLUMN2,
COLUMN3 = A.COLUMN3
FROM A
WHERE A.ID = B.ID

注意: 主要问题是 FROM 原因,DB2和 ANSI SQL 都不支持这个问题。

它适用于 DB210.5,但不适用于 PostgreSQL 9.3.4:

UPDATE B SET
(COLUMN1, COLUMN2, COLUMN3) =
(SELECT COLUMN1, COLUMN2, COLUMN3 FROM A WHERE ID = B.ID)

终于! 它可以在 PostgreSQL 9.3.4和 DB210.5上运行了:

UPDATE B SET
COLUMN1 = (SELECT COLUMN1 FROM A WHERE ID = B.ID),
COLUMN2 = (SELECT COLUMN2 FROM A WHERE ID = B.ID),
COLUMN3 = (SELECT COLUMN3 FROM A WHERE ID = B.ID)