Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgreSQL don';不使用上次返回的新_Postgresql_Triggers - Fatal编程技术网

PostgreSQL don';不使用上次返回的新

PostgreSQL don';不使用上次返回的新,postgresql,triggers,Postgresql,Triggers,我有一个带有before update触发器的表,它可以通过更新同一行来触发自身,但update语句的结果不是该触发器返回的最后一个值。我不明白它为什么和如何工作。举例来说,这个问题更容易理解: BEGIN; SET client_min_messages = 'notice'; CREATE TABLE public.test ( id INTEGER, status INTEGER, value numeric ); CREATE SEQUENCE test_seq;

我有一个带有before update触发器的表,它可以通过更新同一行来触发自身,但update语句的结果不是该触发器返回的最后一个值。我不明白它为什么和如何工作。举例来说,这个问题更容易理解:

BEGIN;

SET client_min_messages = 'notice';

CREATE TABLE public.test (
  id INTEGER, 
  status INTEGER, 
  value numeric
);

CREATE SEQUENCE test_seq;

CREATE OR REPLACE FUNCTION public.test_tr() RETURNS trigger AS $body$
DECLARE
    seq integer;
BEGIN
    seq := nextval('test_seq');
    RAISE NOTICE 'Started: %', seq;
    IF new.status != old.status THEN
        UPDATE test SET value = new.value WHERE id = new.id;
    END IF;
    RAISE NOTICE 'Finished: %, RETURNED NEW: %', seq, new;
    RETURN new;
END
$body$ LANGUAGE 'plpgsql';

CREATE TRIGGER test_tr BEFORE UPDATE ON test FOR EACH ROW EXECUTE PROCEDURE test_tr();

INSERT INTO test (id, status, value) VALUES (1, 1, 1);

UPDATE test SET status = 2, value = 2 WHERE id = 1;

SELECT * FROM test;

ROLLBACK;
其结果如下:

NOTICE:  Started: 1
NOTICE:  Started: 2
NOTICE:  Finished: 2, RETURNED NEW: (1,1,2)
NOTICE:  Finished: 1, RETURNED NEW: (1,2,2)
UPDATE 0

 id | status | value 
----+--------+-------
  1 |      1 |     2

如您所见,最后一次返回的new是(1,2,2)(status=2,value=2),但最后一次选择返回的行“status”=1,“value”=2。为什么status=“1”?为什么不“2”

当更新前的
触发器调用同一行上的
UPDATE
时,手册似乎没有定义任何特定行为

直觉上,我们可能期望
NEW
的最后一个值进入行中,但结果表明,情况并非如此

我的建议是:

  • 触发器发出更新#2。此时,行仍有其初始
    (1,1,1)
    价值观

  • 对于UPDATE#2,触发器再次启动,但它只返回
    NEW
    ,因此不会更改任何内容

  • 更新#2完成后,该行的新版本将变为最新版本,内容为
    (1,1,2)

  • 当更新#1完成时,引擎应该写入
    NEW=(1,2,2)
    ,但随后它会注意到它正在处理的行的版本已经被取代。因此,它丢弃了它的
    新的
    记录,并将其保留在那里

  • 这与psql报告
    更新0
    一致:更新1实际上没有更新任何行。

    您应该使用语句级触发器,而不是行级触发器。