我有一个调用函数的触发器AFTER INSERT ON mytable
CREATE OR REPLACE FUNCTION myfunction() RETURNS trigger AS
$BODY$
DECLARE
index TEXT;
BEGIN
index := 'myIndex_' || NEW.id2::text;
IF to_regclass(index::cstring) IS NULL THEN
EXECUTE 'CREATE INDEX ' || index || ' ON mytable(id) WITH (FILLFACTOR=100) WHERE id2=' || NEW.id2|| ';';
RAISE NOTICE 'Created new index %',index;
END IF;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
SECURITY DEFINER
COST 100;
ALTER FUNCTION myfunction()
OWNER TO theadmin;
这非常有用。对于每个不同的id2
,我创建一个索引。通过大量加快相关查询。
如上所述,我触发此AFTER INSERT ON
。在此之前,我将触发器设置为BEFORE INSERT ON
。功能做了一些奇怪的事情。 (是的,我已将RETURN NULL
更改为RETURN NEW
)
insert into mytable VALUES(1391, 868, 0.5, 0.5);
myIndex_868
ERROR: duplicate key value violates unique constraint "mytable_pkey"
,因为当然DETAIL: Key (id, id2)=(1391, 868) already exists.
DELETE FROM mytable WHERE id = 1391 and id2 = 868
什么都不做DROP INDEX myIndex_868;
删除索引。突然间,表中从未出现的最初一行突然出现了!为什么BEFORE INSERT ON
表现得如此不同?这是postgres 9.4中的错误还是忽略了什么?
只是为了完整'缘故:
CREATE TRIGGER mytrigger
AFTER INSERT ON mytable
FOR EACH ROW EXECUTE PROCEDURE myfunction();
VS
CREATE TRIGGER mytrigger
BEFORE INSERT ON mytable
FOR EACH ROW EXECUTE PROCEDURE myfunction();
答案 0 :(得分:2)
我认为这是PostgreSQL中的一个错误。我可以用9.6重现它。
很明显,该行未包含在索引中,因为它是在BEFORE
触发器中创建的,但是在插入行时索引未更新的事实是我认为的错误。 / p>
我有written to pgsql-hackers要求提出意见。
但除此之外,我没有看到整个演习的重点。 创建一个巨大的索引比创建一个单一的索引更好:
CREATE INDEX ON mytable(id2, id);