相关疑难解决方法(0)

约束定义DEFERRABLE INTITIALLY IMMEDIATE仍然是DEFERRED?

关于这个答案,我偶然发现了一个我无法解释的现象.

版本:
x86_64-unknown-linux-gnu上的PostgreSQL 9.1.2,由gcc-4.4.real编译(Debian 4.4.5-8)4.4.5,64位

请考虑以下演示.测试平台:

CREATE TEMP TABLE t (
  id  integer
 ,txt text
 ,CONSTRAINT t_pkey PRIMARY KEY (id) DEFERRABLE INITIALLY IMMEDIATE
);

INSERT INTO t VALUES
 (1, 'one')
,(2, 'two');
Run Code Online (Sandbox Code Playgroud)

1)修改多行的UPDATE语句:

UPDATE t
SET    id = t_old.id
FROM   t t_old
WHERE (t.id, t_old.id) IN ((1,2), (2,1));
Run Code Online (Sandbox Code Playgroud)

目前的实施似乎有一个错误?上面的UPDATE虽然不应该有效.约束已定义INITIALLY IMMEDIATE,我没有使用SET CONSTRAINTS.

我错过了什么,或者这是一个(相当无害)的错误?


2)数据修改CTE

因此,修改CTE的数据也可以工作,尽管它有一个NOT DEFERREDpk 失败:

WITH x AS (
    UPDATE t SET id = 1 WHERE id = 2 …
Run Code Online (Sandbox Code Playgroud)

postgresql constraints postgresql-9.1

14
推荐指数
2
解决办法
1万
查看次数

检测postgres更新触发器中的列更改

我有一个postgres数据库,有几个表我想看更新,如果有任何更新,我想发一个"嘿,改变了一些"的更新.这适用于基本情况,但现在是时候改进了.

CREATE FUNCTION notify_update() RETURNS trigger AS $notifyfunction$
BEGIN
  PERFORM pg_notify('update_watchers',
    $${"event":"update", "type": "$$ || TG_TABLE_NAME || $$", "payload": {"id": $$ || new.id || $$}}$$);
  RETURN new;
END;
$notifyfunction$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

工作得很好.我把它附在桌子上,如下:

CREATE TRIGGER document_update_body
AFTER UPDATE ON documents
FOR EACH ROW EXECUTE PROCEDURE notify_update();
Run Code Online (Sandbox Code Playgroud)

(作为一个侧面问题:如果json.stringify我的触发结果比触发器功能中的mess'o' $$更好/更容易,请告诉我.平衡引号并不好玩).

我想要做的是在pg_notify调用中附加已更改的列的列表.除了迭代表中的列并检查NEW.col是否与OLD.col不同之外,似乎没有任何简单的方法可以做到这一点.执行此操作的不好方法是在我的通知过程中对列名进行硬编码(脆弱,如果我更改模式则更新另一件事等).

我也非常喜欢编写plpgsql,所以我不确定在哪里寻求帮助.理想情况下(如果没有我在文档中没有看到的updated_columns块变量),有一种方法可以在通知块中获取表的模式而不会导致过于严重的性能开销(因为这些表将更新为公平的).

sql postgresql plpgsql

8
推荐指数
1
解决办法
3230
查看次数

MySQL更新触发器 - 查找更改的列?

我有一个120列的表.我需要设置审计跟踪,如果已更改,则会记录任何列.就像现在一样,我想我必须为每一列设置一个具有类似条件的触发器:

IF(NEW.columnName != OLD.columnName)
THEN //log the old value
Run Code Online (Sandbox Code Playgroud)

这需要做120次......虽然我会在20年前接受这种方法,但今天我拒绝相信自动执行如此简单的程序自动查找更改的列是不可能的.

这是我到目前为止发现的:

  • NEW和OLD都不是一个表,它是一种语言结构,因此你不能做"现在选择.*"或类似的东西.
  • 触发器中不允许使用动态SQL(这可以解决问题).
  • 触发器中不允许使用动态SQL的过程(严重的是,Oracle,看起来你无论如何都很难禁用此功能).

我正在考虑将BEFORE和AFTER触发器与可能解决问题的临时表和变量结合使用,但是再次需要动态SQL.我觉得我走到了尽头.

有这个解决方案吗?

一个附带问题:这在PostgreSQL中是否可行?

更新:我找到了2个可能的解决方案,但它们对我来说都不够清晰:

  • 使用EVENTS作为解决方法,将触发器与动态SQL 解决方法结合使用.我不得不承认,我不太明白,这是否意味着无论如何,EVENT每秒都会开火?
  • 本文说,只要临时表与它一起使用,就可以在触发器内部使用动态SQL.那仍然是使用动态SQL,所以我不太明白.

mysql triggers

7
推荐指数
1
解决办法
3781
查看次数