テーブルを取る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内では指定できません。
しかし、 PDATEの構文 でも確認できます。
( 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)
これは動作するようです(バージョン9.5および9.6)。問題が解決するかどうかはわかりません。
行をfoo
型に変換します。
row(1,2,3,4)::foo
列に展開します。
select ( ).*
コード全体:
update foo set (a,b,c,d) = (select (row(1,2,3,4)::foo).*) ;