Mik*_*ite 3 postgresql triggers plpgsql
我打算用instead of insert
触发器查看视图。不过,插入默认值似乎有问题。
将触发器设置如下,以下查询失败
INSERT INTO v1.clients (foo) VALUES ('bar')
Run Code Online (Sandbox Code Playgroud)
这将返回一个
“is_admin”列中的空值违反了非空约束
即使基础data.users
( not null
) 表设置了默认值。
我要说的是视图将所有缺失值转换为null
并instead of
应用,尝试插入null
到not null default false
列中。
我可以以某种方式设置触发器而不是尝试插入 null 来插入默认值吗?在coalesce(NEW.is_admin, default)
触发器中进行相关插入是语法错误。我宁愿不在触发器中手动复制默认值。
这在 postgres 中支持吗?将两个表的视图拆分为这些表同时允许默认值的最佳方法是什么?
定义:
CREATE OR REPLACE VIEW v1.clients AS
SELECT
c.id, c.foo,
u.id user_id, u.is_admin
FROM data.clients c
INNER JOIN data.users u ON u.client_id = c.id;
CREATE FUNCTION data.separate_client_user_data()
RETURNS TRIGGER AS $$
DECLARE
client_id clients.id%TYPE;
BEGIN
INSERT INTO data.clients (foo) VALUES (NEW.foo) RETURNING id INTO client_id;
INSERT INTO data.users (client_id, is_admin)
VALUES (client_id, NEW.is_admin);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER user_data_trigger
INSTEAD OF INSERT ON v1.clients
FOR EACH ROW EXECUTE PROCEDURE data.separate_client_user_data();
Run Code Online (Sandbox Code Playgroud)
我知道比赛迟到了,但我想分享一些额外的见解。
请注意,正如 Patrick 所说,TRIGGER PROCEDURE 使用的 NEW 变量包含所有字段 - 为最初不属于 INSERT 语句的任何字段添加 NULL。
正如您所指出的,基础表具有该is_admin
字段的默认值,不幸的是,该默认值没有机会被看到,因为 NEW 变量已经具有 NEW.is_admin = NULL。
但是,我想指出与 Patrick 不同的解决方案。确实,您可以在 plpgsql 函数中手动编写 IF 检查(基本上是重新实现默认值逻辑!)。但从 DRY 的角度来看,这可能感觉不是最佳的。当我遇到你的问题时,这是我的关键:
TL/DR
构建 NEW 变量时,会遵循视图本身的默认值。因此,如果你这样做,ALTER TABLE <view_name> ALTER is_admin SET DEFAULT false
它应该导致false
被传递到NEW.is_admin
,而不是NULL
.
希望有帮助!
归档时间: |
|
查看次数: |
2009 次 |
最近记录: |