Postgresql
無論如何更新具有復合類型記錄/行的行上的一系列列?
拿一張桌子
foo
,CREATE TABLE foo(a,b,c,d) AS VALUES (1,2,3,4);
foo
我可以使用行類型插入..INSERT INTO foo SELECT (foo).* FROM foo; INSERT INTO foo SELECT (v).* FROM ( VALUES (42,42,42,42) ) AS v;
但我不能用行類型更新 foo 。
-- fails UPDATE foo SET (a,b,c,d) = ( SELECT ROW(1,2,3,4) ).*; -- also fails. UPDATE foo SET (a,b,c,d) = (SELECT (1,2,3,4)); ERROR: number of columns does not match number of values LINE 1: UPDATE foo SET (a,b,c,d) = (SELECT (1,2,3,4));
是否有任何語法可以使用複合類型更新整行。真正奇怪的是,這可以在帶有 的觸發器中使用
NEW
,而我正在嘗試編寫沒有觸發器的相同程式碼。CREATE OR REPLACE FUNCTION foo() RETURNS trigger AS $$ BEGIN NEW=(42,42,42,42); RETURN NEW; END; $$ LANGUAGE plpgsql IMMUTABLE; CREATE TRIGGER ok BEFORE UPDATE ON foo FOR EACH ROW EXECUTE PROCEDURE foo(); -- The NEW row in trigger gets updated with (42,42,42,42) -- the UPDATE succeeds; all rows (42,42,42,42) UPDATE foo SET (a,b,c,d) = (1,2,3,4);
你可以在這裡看到我們可以更新過程中的行對象,並更改更新。但是,我們不能在
UPDATE
ddl 中這樣做嗎?我希望由同名表生成的 RECORD 以相同的方式工作。-- Such as this, UPDATE foo SET foo = (1,2,3,4);
其實有很多關於這個的文章。。
但是,根據/u/pstef,其中一個已送出,並且此語法現在適用於 HEAD,儘管 @ypercubeᵀᴹ 報告它不適用於 9.6.5
UPDATE foo SET (a,b,c,d) = ROW(10,9,8,7);
文件對此並沒有多說
根據標準,帶括號的目標列名稱子列表的源值可以是產生正確列數的任何行值表達式。**PostgreSQL 只允許源值是行建構子或子 SELECT。**單個列的更新值可以在行建構子的情況下指定為 DEFAULT,但不能在子 SELECT 中指定。
但您也可以在UPDATE 的語法中看到
( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) |
怎麼樣(伺服器 9.5.7)…
create table foo(a,b,c,d) as values (1,2,3,4) , (4,5,6,7) , (8,9,0,null); postgres=# select * from foo; a | b | c | d ---+---+---+--- 1 | 2 | 3 | 4 4 | 5 | 6 | 7 8 | 9 | 0 | (3 rows) update foo set (a,b,c,d) = ( select (v).* from ( values (42,42,42,42) ) as v ) ; postgres=# select * from foo; a | b | c | d ----+----+----+---- 42 | 42 | 42 | 42 42 | 42 | 42 | 42 42 | 42 | 42 | 42 (3 rows)
Dbfiddle在這裡。
或者,確實(沒有觸發器):
postgres=# update foo postgres-# set (a,b,c,d) = (11,22,33,44) ; UPDATE 3 postgres=# select * from foo; a | b | c | d ----+----+----+---- 11 | 22 | 33 | 44 11 | 22 | 33 | 44 11 | 22 | 33 | 44 (3 rows)