PostgreSQL 插入或更新触发函数波动类别
PostgreSQL insert or update trigger function volatility category
假设,我的数据库中有 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
:
时,我都会自动从 FOLDER.KEY
更新 FOLDERFILE.PATHKEY
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()
波动性的。文档说
Any function with side-effects must be labeled VOLATILE
但据我所知——这个函数不会改变它所依赖的表中的任何数据,所以我可以将这个函数标记为 IMMUTABLE
。对吗?
如果我在同一事务中将许多行批量插入 FOLDERFILE
,IMMUTABLE 触发器函数会有任何问题吗,例如:
BEGIN;
INSERT INTO FOLDERFILE ( ... );
...
INSERT INTO FOLDERFILE ( ... );
COMMIT;
首先,正如@pozs 已经指出的那样,您提供的函数定义绝对是 STABLE
而不是 IMMUTABLE
,因为它执行数据库查找。这意味着结果不仅来自输入参数(如 IMMUTABLE
所建议的那样),还来自存储在 FOLDER
table 中的数据(这肯定会发生变化)。根据文档:
STABLE
indicates that the function cannot modify the database, and
that within a single table scan it will consistently return the same
result for the same argument values, but that its result could change
across SQL statements. This is the appropriate selection for functions
whose results depend on database lookups, parameter variables (such as
the current time zone), etc.
其次,向触发器函数添加稳定性修饰符 (IMMUTABLE
/STABLE
/VOLATILE
) 充其量只是为了说明目的,因为 AFAIK PostgreSQL 实际上并未执行任何计划这将保证他们的使用。 pgsql-hackers
邮件列表中的 following post 似乎支持我的说法:
Volatility is a complete no-op for a trigger function anyway, as are
other planner parameters such as cost/rows, because there is no
planning involved in trigger calls.
总而言之:您现在最好避免在触发器 (!) 过程中使用稳定性关键字,因为包含它们似乎几乎没有什么好处,但会带来一些意想不到的 caveats/pitfalls(请参阅@pozs 的第一条评论结束)。
假设,我的数据库中有 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
:
FOLDER.KEY
更新 FOLDERFILE.PATHKEY
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()
波动性的。文档说
Any function with side-effects must be labeled VOLATILE
但据我所知——这个函数不会改变它所依赖的表中的任何数据,所以我可以将这个函数标记为 IMMUTABLE
。对吗?
如果我在同一事务中将许多行批量插入 FOLDERFILE
,IMMUTABLE 触发器函数会有任何问题吗,例如:
BEGIN;
INSERT INTO FOLDERFILE ( ... );
...
INSERT INTO FOLDERFILE ( ... );
COMMIT;
首先,正如@pozs 已经指出的那样,您提供的函数定义绝对是 STABLE
而不是 IMMUTABLE
,因为它执行数据库查找。这意味着结果不仅来自输入参数(如 IMMUTABLE
所建议的那样),还来自存储在 FOLDER
table 中的数据(这肯定会发生变化)。根据文档:
STABLE
indicates that the function cannot modify the database, and that within a single table scan it will consistently return the same result for the same argument values, but that its result could change across SQL statements. This is the appropriate selection for functions whose results depend on database lookups, parameter variables (such as the current time zone), etc.
其次,向触发器函数添加稳定性修饰符 (IMMUTABLE
/STABLE
/VOLATILE
) 充其量只是为了说明目的,因为 AFAIK PostgreSQL 实际上并未执行任何计划这将保证他们的使用。 pgsql-hackers
邮件列表中的 following post 似乎支持我的说法:
Volatility is a complete no-op for a trigger function anyway, as are other planner parameters such as cost/rows, because there is no planning involved in trigger calls.
总而言之:您现在最好避免在触发器 (!) 过程中使用稳定性关键字,因为包含它们似乎几乎没有什么好处,但会带来一些意想不到的 caveats/pitfalls(请参阅@pozs 的第一条评论结束)。