Nir*_*Nir 115 sql postgresql dynamic-sql sql-update
我有两张桌子:
A [ID, column1, column2, column3]
B [ID, column1, column2, column3, column4]
Run Code Online (Sandbox Code Playgroud)
A将永远是其子集B(意味着所有列A也在其中B).
我想更新具有特定ID输入的记录,其中B包含来自A所有列的数据A.这ID存在于A和B.
是否有UPDATE语法或任何其他方法来指定列名称,只是说"设置A的所有列"?
我正在使用PostgreSQL,因此也接受了一个特定的非标准命令(但不是首选).
Sco*_*ley 216
您可以使用非标准FROM子句.
UPDATE b
SET column1 = a.column1,
column2 = a.column2,
column3 = a.column3
FROM a
WHERE a.id = b.id
AND b.id = 1
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 44
这个问题已经过时了,但我觉得还没有给出最好的答案.
是否有UPDATE语法... 没有指定列名?
除了要加入的一些唯一列(UPDATE在示例中)之外,您不需要知道任何列名.对于我能想到的任何可能的角落情况都可靠地工作.
这是PostgreSQL特有的.我正在构建基于information_schema的动态代码,特别id是在ANSI SQL中定义的表,而大多数现代RDBMS(Oracle除外)都支持它.但是PL/pgSQL代码执行动态SQL 的information_schema.columns声明完全是非标准的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$;
Run Code Online (Sandbox Code Playgroud)
假设在一个匹配列DO的每一列b,而不是倒过来.a可以有其他列.
b 是可选的,仅更新选定的行.
相关答案以及更多解释:
您仍然需要知道两个表共享的列名列表.使用语法快捷方式更新多个列 - 比任何情况下到目前为止建议的其他答案都短.
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;
Run Code Online (Sandbox Code Playgroud)
这个语法是在2006年12月的Postgres 8.2中引入的,早在提出问题之前.
有关dba.SE 手册和相关答案的更多详细信息:
WHERE b.id = 123如果B定义了所有列A(但不一定NOT NULL),
并且您知道列名B(但不一定B).
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;
Run Code Online (Sandbox Code Playgroud)
该A联接从行NATURAL LEFT JOIN,其中同名的所有列持有相同的价值观.在这种情况下我们不需要更新(没有任何更改),并且可以在流程早期消除这些行(b).
我们仍然需要找到匹配的行,所以WHERE b.id IS NULL在外部查询中.
这是标准SQL,除了该b.id = ab.id子句.
无论哪个列实际存在FROM,它都可以工作,但查询无法区分实际的NULL值和缺少的列A,因此只有在A定义了所有列时才可靠A.
根据您对两个表的了解,有多种可能的变化.
joc*_*han 23
我已经使用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
Run Code Online (Sandbox Code Playgroud)
注意:主要问题是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)
Run Code Online (Sandbox Code Playgroud)
最后!它适用于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)
Run Code Online (Sandbox Code Playgroud)
小智 7
这是一个很好的帮助.代码
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;
Run Code Online (Sandbox Code Playgroud)
工作得很好.
注意到你需要一个括号""
From "tbl_a" a
Run Code Online (Sandbox Code Playgroud)
使它工作.
不一定是你问的,但也许使用postgres继承可能会有所帮助?
CREATE TABLE A (
ID int,
column1 text,
column2 text,
column3 text
);
CREATE TABLE B (
column4 text
) INHERITS (A);
Run Code Online (Sandbox Code Playgroud)
这避免了更新B的需要.
但一定要阅读所有细节.
否则,你要求的东西不被认为是一种好的做法 - SELECT * ...不鼓励观看动态的东西(因为这种轻微的便利可能会破坏更多的东西而不是帮助的东西),而你要求的东西将等同于UPDATE ... SET命令.
| 归档时间: |
|
| 查看次数: |
136749 次 |
| 最近记录: |