postgresql - postgres 触发器创建索引 : BEFORE INSERT ON hides one row

标签 postgresql triggers postgresql-9.4

我有一个调用函数的触发器 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
  • 在执行选择时插入的行没有出现 :(
  • 尝试插入同一行会导致 错误:重复键值违反唯一约束“mytable_pkey” 因为 DETAIL: Key (id, id2)=(1391, 868) already存在。
  • 为相同的 id2 插入其他行按预期工作:)
  • 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();

对比

CREATE TRIGGER mytrigger
BEFORE INSERT ON mytable
FOR EACH ROW EXECUTE PROCEDURE myfunction();

最佳答案

我认为这是 PostgreSQL 中的错误。我可以用 9.6 重现它。

很明显该行不包含在索引中,因为它是在 BEFORE 触发器中创建的,但是当插入行时索引没有更新这一事实是我的一个错误意见。

我有written to pgsql-hackers征求意见。

但除此之外,我看不出整个练习的意义所在。 比创建大量索引更好的方法是创建一个索引:

CREATE INDEX ON mytable(id2, id);

关于postgresql - postgres 触发器创建索引 : BEFORE INSERT ON hides one row,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44109737/

相关文章:

php - Doctrine 注册自定义 DQL 函数

django - DRF - 如何让 WritableField 不将整个数据库加载到内存中?

jquery - 如果通过 JQuery 创建 html,则鼠标触发无法正确发生

mysql - 如何在mysql中的触发器上编写业务规则

PostgreSQl pg_dump权限错误?

json - Oracle JSON_TABLE 到 PostgreSQL - 如何从 JSON 列中的第二个分层键进行搜索

python - psycopg2 操作错误 : cursor does not exist

node.js - 使用 Node.js Sequelize 和 Hooks 实现触发器

sql - 检查数据是否具有默认长度并且它在sql中是数字

docker - 如何将镜像创建的卷与 docker-compose 指定的命名卷链接起来?