在古生物学数据库的数据库中,我在PostgreSQL v.12中具有此表定义:
CREATE TABLE taxon (
id integer DEFAULT NEXTVAL('taxon_oid_seq') PRIMARY KEY,
taxon varchar(100) UNIQUE NOT NULL,
reino varchar(50) NOT NULL,
phylum varchar(100) ,
subphylum varchar(100) ,
classe varchar(100) ,
subclasse varchar(100) ,
superordem varchar(100) ,
ordem varchar(100) ,
subordem varchar(100) ,
infraordem varchar(100) ,
familia varchar(100) ,
subfamilia varchar(100) ,
genero varchar(100) ,
especie varchar(100) ,
subespecie varchar(100) );
分类单元字段将自动填充有可能确定给定物种分类的最低级别。为了实现这一点,我有这个触发器:
CREATE OR REPLACE FUNCTION get_taxon() RETURNS TRIGGER LANGUAGE
plpgsql AS $BODY$
BEGIN
NEW.taxon := coalesce(NEW.subespecie, NEW.especie, NEW.genero, NEW.subfamilia,
NEW.familia, NEW.infraordem, NEW.subordem, NEW.ordem, NEW.superordem,
NEW.subclasse, NEW.classe, NEW.subphylum, NEW.phylum, NEW.reino);
RETURN NEW;
END;
$BODY$
VOLATILE;
CREATE TRIGGER update_taxon
BEFORE INSERT OR UPDATE ON taxon
FOR EACH ROW EXECUTE PROCEDURE get_taxon();
但是此触发器仅在INSERT
上触发,如果制作了UPDATE
,则什么也不会发生。在UPDATE
的情况下如何触发此触发器?
编辑
我刚刚意识到我还有另一个触发器会在更新时触发。此其他触发器定义为:
CREATE OR REPLACE FUNCTION taxon_history_update() RETURNS trigger AS
$BODY$
BEGIN
INSERT INTO history.taxon(operacao, data, tecnico, original_oid,
taxon, reino, phylum, subphylum, classe,
subclasse, superordem, ordem, subordem,
infraordem, familia, subfamilia, genero,
especie, subespecie)
VALUES
('UPDATE', current_timestamp, current_user,
old.oid, old.taxon, old.reino, old.phylum,
old.subphylum, old.classe, old.subclasse,
old.superordem, old.ordem, old.subordem,
old.infraordem, old.familia,
old.subfamilia, old.genero, old.especie,
old.subespecie);
RETURN old;
END;
$BODY$
LANGUAGE plpgsql;
CREATE TRIGGER taxon_history_update
BEFORE UPDATE ON taxon
FOR EACH ROW EXECUTE PROCEDURE taxon_history_update();
这两个触发因素之间是否存在某种冲突/干扰?如果我放下update_taxon
触发器,我的taxon_history_update
触发器也适用于更新!
我正在写答案,因为我的评论不适合:
如果创建表和触发器,然后执行INSERT
和UPDATE
,则会得到:
foo=# select * from taxon;
id | taxon | reino | phylum | subphylum | classe | subclasse | superordem | ordem | subordem | infraordem | familia | subfamilia | genero | especie | subespecie
----+-------+-------+--------+-----------+--------+-----------+------------+-------+----------+------------+---------+------------+--------+---------+------------
(0 rows)
foo=# explain analyze insert into taxon (reino) values ('sapienz');
QUERY PLAN
-----------------------------------------------------------------------------------------------
Insert on taxon (cost=0.00..0.01 rows=1 width=495) (actual time=0.111..0.111 rows=0 loops=1)
-> Result (cost=0.00..0.01 rows=1 width=495) (actual time=0.062..0.063 rows=1 loops=1)
Planning Time: 0.034 ms
Trigger update_taxon: time=0.026 calls=1
Execution Time: 0.137 ms
(5 rows)
foo=# select * from taxon;
id | taxon | reino | phylum | subphylum | classe | subclasse | superordem | ordem | subordem | infraordem | familia | subfamilia | genero | especie | subespecie
----+---------+---------+--------+-----------+--------+-----------+------------+-------+----------+------------+---------+------------+--------+---------+------------
1 | sapienz | sapienz | | | | | | | | | | | | |
(1 row)
foo=# explain analyze update taxon set reino = 'sapien' where id = 1;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
Update on taxon (cost=0.14..8.16 rows=1 width=1005) (actual time=0.134..0.135 rows=0 loops=1)
-> Index Scan using taxon_pkey on taxon (cost=0.14..8.16 rows=1 width=1005) (actual time=0.017..0.019 rows=1 loops=1)
Index Cond: (id = 1)
Planning Time: 0.100 ms
Trigger update_taxon: time=0.039 calls=1
Execution Time: 0.162 ms
(6 rows)
foo=# select * from taxon;
id | taxon | reino | phylum | subphylum | classe | subclasse | superordem | ordem | subordem | infraordem | familia | subfamilia | genero | especie | subespecie
----+--------+--------+--------+-----------+--------+-----------+------------+-------+----------+------------+---------+------------+--------+---------+------------
1 | sapien | sapien | | | | | | | | | | | | |
(1 row)
[您可以看到,在两个EXPLAIN ANALYZE
调用中都触发了触发器—您可以使用有关如何重现所看到的行为的更多详细信息来更新您的问题吗?顺便说一句,我正在使用PostgreSQL v。12.0
UPDATE根据您的更新:嗯,我想您的问题是您正在为第二个触发器执行RETURN old;
-您需要RETURN new
否则它会放弃所做的更改。按照the documentation:
不打算引起上述任何一种行为的行级BEFORE触发器必须小心返回返回的结果(即INSERT和UPDATE触发器的NEW行,删除触发器)。
我认为,您的历史记录触发功能中有一个错字。表分类中没有“ oid”列,但有“ id”列(因此记录了变量“ old”)。这会中断触发器功能的执行,并可能回滚事务。
BTW:自PostgreSQL v12起,所有表都缺少内部的“ oid”列,如您在docs中所见(创建表:“ ...不再支持使用OIDS创建表。”),即使用“ oid”可以一直工作到第11页。
希望这会有所帮助。
您的问题是第二个触发因素。这是一个BEFORE UPDATE
触发器,它返回old
而不是应该返回的new
。
这意味着原始行(old
)将被写入表,而不是更新后的行(new
)。因此,您的更新将无效。
由于BEFORE UPDATE
触发器是按字母顺序执行的,所以update_taxon
触发器将获得旧行,而不是将新行作为new
。
将taxon_history_update
功能修复为RETURN new;
,您的所有麻烦都将消失。