我正在尝试为PostgreSQL中某些分区表的主表的插入和更新事件设置触发器。每次在主表中进行插入时,插入触发事件都会将其重定向到正确的分区表中。因此,由于我也不想填充主表,因此需要从此函数调用返回NULL。如果主表收到更新事件,它将在对表进行更改之前更新时间戳。问题在于,永远不会触发更新触发器。我正在使用PostgreSQL 9.6版。
我尝试将触发器函数合并为一个,并将调用的触发器过程也合并为一个,但是结果是相同的。仅当我从插入触发函数(填充主表)返回NEW时,或者完全注释掉插入触发函数时,才会触发更新触发。
DROP SCHEMA IF EXISTS test CASCADE;
CREATE SCHEMA test;
SET SCHEMA 'test';
CREATE TYPE test_type AS ENUM ('unit', 'performance');
CREATE TABLE test (
type test_type NOT NULL,
score INTEGER NOT NULL CHECK (score > 0),
id SERIAL PRIMARY KEY,
updated_at TIMESTAMP DEFAULT current_timestamp
);
CREATE TABLE performance_test (
CHECK (type = 'performance')
) INHERITS (test);
CREATE FUNCTION insert_test()
RETURNS trigger AS
$$
BEGIN
INSERT INTO performance_test VALUES (NEW.*);
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE FUNCTION update_timestamp()
RETURNS trigger AS
$$
BEGIN
RAISE NOTICE 'This is never reached.';
UPDATE performance_test
SET updated_at = current_timestamp
WHERE id = NEW.id;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER test_insertion BEFORE INSERT ON test
FOR EACH ROW EXECUTE PROCEDURE insert_test();
CREATE TRIGGER test_update BEFORE UPDATE ON test
FOR EACH ROW EXECUTE PROCEDURE update_timestamp();
---------------------------------------------------------------------------
INSERT INTO test VALUES ('performance', 10);
SELECT * FROM performance_test;
UPDATE test SET score = 20 WHERE id = 1;
SELECT * FROM performance_test;
我不确定用这种方法是否可以实现我想要的,所以我在这里寻求任何建议。预先感谢!
/汉普斯
答案 0 :(得分:0)
行触发器必须在单个分区上定义,而不是在分区表上定义。参见https://www.postgresql.org/docs/10/ddl-partitioning.html#DDL-PARTITIONING-DECLARATIVE-LIMITATIONS
我不知道为什么9.6的文档中没有提及
工作更新触发器:
CREATE FUNCTION update_timestamp()
RETURNS trigger AS
$$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER test_update BEFORE UPDATE ON performance_test
FOR EACH ROW EXECUTE PROCEDURE update_timestamp();
如果您执行UPDATE test SET score = 30, updated_at=DEFAULT;
或UPDATE test SET score = 30, updated_at=current_timestamp;
,则可能不需要更新触发器。
分区不是免费的午餐,因为它对行为和性能都没有明显的影响,正如您所注意到的那样,触发器的行为并不符合您的预期。如果您输入有误,很容易导致查询失败,甚至是不良数据。
如果您确实确定需要它,则应确保您详细了解它,否则,我建议您避免使用它,可以通过确保表统计信息是最新的来解决慢查询的大多数问题,使用正确的索引,优化查询,更改Postgres配置或添加更多硬件。