PostgreSQL插入或更新触发函数波动率类别

时间:2015-02-27 10:38:40

标签: postgresql immutability volatile volatility

假设我的数据库中有2个表(postgresql-9.x)

CREATE TABLE FOLDER (
    KEY BIGSERIAL PRIMARY KEY,
    PATH TEXT,
    NAME TEXT
);
CREATE TABLE FOLDERFILE (
    FILEID BIGINT,
    PATH TEXT,
    PATHKEY BIGINT
);

每当我插入或更新FOLDERFILE.PATHKEY时,我都会FOLDER.KEY自动更新FOLDERFILE

CREATE OR REPLACE FUNCTION folderfile_fill_pathkey() RETURNS trigger AS $$
DECLARE
  pathkey bigint;
  changed boolean;
BEGIN
  IF tg_op = 'INSERT' THEN
     changed := TRUE;
    ELSE IF old.FILEID != new.FILEID THEN
       changed := TRUE;
    END IF;
  END IF;
  IF changed THEN
     SELECT INTO pathkey key FROM FOLDER WHERE PATH = new.path;
     IF FOUND THEN
       new.pathkey = pathkey;
     ELSE
       new.pathkey = NULL;
     END IF;
  END IF;
  RETURN new;
END
$$ LANGUAGE plpgsql VOLATILE;

CREATE TRIGGER folderfile_fill_pathkey_trigger AFTER INSERT OR UPDATE 
ON FOLDERFILE FOR EACH ROW EXECUTE PROCEDURE fcliplink_fill_pathkey();

所以问题是关于函数folderfile_fill_pathkey()的波动性。文件说

  

任何带副作用的功能必须标记为VOLATILE

但据我所知 - 此函数不会更改它所依赖的表中的任何数据,因此我可以将此函数标记为IMMUTABLE。这是正确的吗?

如果我在同一事务中将许多行批量插入FOLDERFILE,那么IMMUTABLE触发器功能是否会出现任何问题,例如:

BEGIN;
INSERT INTO FOLDERFILE ( ... );
...
INSERT INTO FOLDERFILE ( ... );
COMMIT;

1 个答案:

答案 0 :(得分:5)

首先,正如@pozs已经指出的那样,您提供的函数定义绝对是STABLE而不是IMMUTABLE,因为它执行数据库查找。这意味着结果不是简单地从输入参数(如IMMUTABLE建议的那样)得出的,而且也来自存储在FOLDER表中的数据(必然会发生变化)。根据文件:

  

STABLE表示该函数无法修改数据库,并且   在单个表扫描中,它将始终返回相同的内容   结果是相同的参数值,但其结果可能会改变   跨SQL语句。 这是适当的功能选择   其结果取决于数据库查找,参数变量(例如   当前时区)等。

其次,将稳定性修饰符(IMMUTABLE / STABLE / VOLATILE)添加到触发器函数中充其量只是为了说明目的,因为AFAIK PostgreSQL实际上并没有执行任何规划这将保证他们的使用。来自pgsql-hackers邮件列表的following post似乎支持我的声明:

  

无论如何,波动率对于触发函数来说都是完全无操作的   其他计划者参数,如成本/行,因为没有   计划涉及触发调用。

总结一下:你现在最好避开触发器(!)程序中的稳定性关键字,因为包含它们似乎几乎没有任何好处,但需要几个意外的警告/陷阱(见最后) @ pozs的第一个评论)。