SQL更新另一个字段的一个表的字段
我有两个表格:
A [ID, column1, column2, column3] B [ID, column1, column2, column3, column4]
A
将永远是B
子集(意味着A
所有列也都在B
)。
我想用A
中所有列的A
的数据更新B
具有特定ID
的logging。 此ID
存在于A
和B
。
有没有UPDATE
语法或任何其他方式来做到这一点,而不指定列名称,只是说“设置A的所有列” ?
我正在使用PostgreSQL,所以一个特定的非标准命令也被接受(但不是首选)。
您可以使用非标准的FROM子句。
UPDATE b SET column1 = a.column1, column2 = a.column2, column3 = a.column3 FROM a WHERE a.id = b.id AND b.id = 1
这个问题很老,但我觉得还没有给出最好的答案。
有没有UPDATE语法… 没有指定列名称 ?
一般解决scheme与dynamicSQL
你不需要知道任何列名,除了一些独特的列join(在例子中的id
)。 可以为任何可能的angular落案例可靠地工作,我能想到的。
这是PostgreSQL特有的。 我正在构build基于information_schema的dynamic代码,特别是在ANSI SQL中定义的表information_schema.columns
以及大多数现代的RDBMS(Oracle除外)都支持它。 但是执行dynamicSQL的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
中的每一列都有一个匹配的列,但是不是相反的。 b
可以有额外的列。
WHERE b.id = 123
是可选的,只更新选定的行。
SQL小提琴。
更多解释的相关答案:
- dynamic更新因plpgsql中的string周围不需要的括号而失败
- 更新多个以特定string开头的列
部分解决scheme与普通的SQL
与共享列的列表
您仍然需要知道这两个表共享的列名称的列表。 使用更新多列的语法快捷方式 – 比任何情况下build议的其他答案都要短。
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小提琴。
这个语法是在2006年12月在Postgres 8.2中引入的,早在问题被提出之前。
本手册中的更多细节以及与dba.SE相关的解答:
- 批量更新所有列
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
)。
我们仍然需要find一个匹配的行,所以外部查询中的b.id = ab.id
SQL小提琴。
除了FROM
子句,这是标准的SQL。
它可以工作,不pipe哪一列实际存在于A
,但查询不能区分实际的NULL值和A
缺失列,所以只有在A
中的所有列都定义为NOT NULL
情况下才是可靠的。
有多种可能的变化,这取决于你知道两个表。
我已经使用IBM DB2数据库十多年了,现在正在努力学习PostgreSQL。
它适用于PostgreSQL 9.3.4,但不适用于DB2 10.5:
UPDATE B SET COLUMN1 = A.COLUMN1, COLUMN2 = A.COLUMN2, COLUMN3 = A.COLUMN3 FROM A WHERE A.ID = B.ID
注意:主要问题是DB2中不支持的FROM原因,也不是ANSI SQL中的原因。
它适用于DB2 10.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和DB2 10.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)
不一定你问什么,但也许使用postgresinheritance可能有帮助?
CREATE TABLE A ( ID int, column1 text, column2 text, column3 text ); CREATE TABLE B ( column4 text ) INHERITS (A);
这避免了需要更新B.
但一定要阅读所有的细节 。
否则,你所要求的是不被认为是一个好的做法 – dynamic的东西,如与SELECT * ...
意见是不鼓励的(因为轻微的便利可能会打破更多的东西,而不是帮助的东西),你要求的是相当于UPDATE ... SET
命令。
这是一个很大的帮助。 代码
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
使其工作。
你可以build立和执行dynamicsql来做到这一点,但它真的不理想
尝试以下
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