使用PostgreSQL更新多行
我需要使用PostgreSQL更新同一sql事务中的多行。从下面的帖子: 我看到以下代码:使用PostgreSQL更新多行,sql,postgresql,Sql,Postgresql,我需要使用PostgreSQL更新同一sql事务中的多行。从下面的帖子: 我看到以下代码: UPDATE test AS t SET column_a = c.column_a, column_c = c.column_c FROM (values (123, 1, '---'), (345, 2, '+++') ) AS c(column_b, column_a, column_c) WHERE c.column_b = t.column_b; 但是,只有当您更新每组值的所有列
UPDATE test AS t SET
column_a = c.column_a,
column_c = c.column_c
FROM (values
(123, 1, '---'),
(345, 2, '+++')
) AS c(column_b, column_a, column_c)
WHERE c.column_b = t.column_b;
但是,只有当您更新每组值的所有列时,才需要这样做,而我不在其中。是否有人能解决此问题以允许多个更新仅使用SQL(而不是plpgsql)?假设您不更新到
NULL
值,您可以使用:
UPDATE test t
SET column_a = COALESCE(c.column_a, t.column_a),
column_c = COALESCE(c.column_c, t.column_c
FROM (values ('123', 1, NULL),
('345', NULL, '+++')
) c(column_b, column_a, column_c)
WHERE c.column_b = t.column_b;
编辑:
如果值可以是NULL
,则需要其他列来指定是否应使用该值:
UPDATE test t
SET column_a = (CASE WHEN c.use_a THEN c.column_a::numeric ELSE t.column_a END),
column_c = (CASE WHEN c.use_b THEN c.column_c::varchar ELSE t.column_c END)
FROM (values (123, 1, NULL, true, false),
(345, NULL, '+++', false true)
) c(column_b, column_a, column_c, use_a, use_c)
WHERE c.column_b::int4 = t.column_b;
您的论点“仅当您正在更新每组值的所有列时”是不正确的。更新将只影响SET子句中提到的那些列。由于接受NULL作为新值,因此只需为特定列设置一个直接值:
update test t
set column_a = c.column_a
, column_c = c.column_c
from (values ('123', 1, NULL, 'Ignored Column')
, ('345', NULL, '+++','Ignored Column')
) c(column_b, column_a, column_c,column_d)
where c.column_b = t.column_b ;
请参阅,特别是附加的列_d.当我说“值集”时,我指的是set子句中提到的那些值。此外,“忽略”一栏可能给出,也可能不给出。那么“我不”是什么意思呢。在什么情况下,您不会更新值集中的列。这需要明确定义。您的编辑几乎可以工作,但在CASE语句中,您必须将值转换为与原始列值相同的类型,以获得一致的返回值。我使用postgreSQL 11.1对其进行了测试,并抛出了一个错误,说明了上述内容。我会看看是否可以编辑你的答案,然后我会把它标记为这个问题的实际答案。@TimMoses。没有理由怀疑这些列会有不同的类型;你的问题甚至没有提供样本数据。我的问题提供了样本数据“('123',1',--',('345',2',++')”。无论如何,对于上述解决方案的“工作”,它必须铸造到某些类型。是的,我没有在问题中提供类型或进一步的信息,但我只是说没有它们它将无法工作。