2016-12-13 39 views
0

我试图在PostgreSQL视图上调用insertupdate调用表。下面是我做的一个简单的例子:如何通过触发和插入过程将数据插入视图时避免“空白”插入?

[Person] table: 
id | lastname | firstname | city | age 

[Person_View] table: 
id | lastname | firstname | city 

这里是触发和相关程序:

CREATE TRIGGER tg_update_person_view 
    INSTEAD OF INSERT OR UPDATE OR DELETE ON 
     Person_View FOR EACH ROW EXECUTE PROCEDURE update_person_view_table(); 

CREATE OR REPLACE FUNCTION update_person_view_table() 
RETURNS TRIGGER 
LANGUAGE plpgsql 
AS $function$ 
    BEGIN 
     IF TG_OP = 'INSERT' THEN 
     INSERT INTO Person (id, lastname, firstname) 
     VALUES(NEW.id, NEW.lastname, NEW.firstname); 
     RETURN NEW; 
     ELSIF TG_OP = 'UPDATE' THEN 
     UPDATE Person 
     SET id=NEW.id, lastname=NEW.lastname, firstname=NEW.firstname 
     WHERE id=OLD.id; 
     RETURN NEW; 
     END IF; 
     RETURN NEW; 
    END; 
$function$; 

如果我做的:

INSERT INTO Person_View (id, city) VALUES ('3', 'Berlin') 

一只有ID的行被添加到视图和父表中。

如何检查过程中插入值的列是否具有在过程中定义的“映射”,并且如果没有任何映射列,则不会继续?

+0

在Postgres里9.3+你不需要规则,也不会触动,基于单个表的视图自动更新。 – klin

+0

我知道,我应该说这个简化的例子是可以自动更新的。我的真实情况是,我有基于多个表的视图,我不希望这些空记录发生。 – kaycee

回答

1

您可以定义表上的检查约束,例如:

create table person(
    id int primary key, 
    lastname text, 
    firstname text, 
    city text, 
    age int, 
    check(coalesce(lastname, firstname, city, age::text) is not null) 
); 

insert into person (id) 
values (1); 

ERROR: new row for relation "person" violates check constraint "person_check" 
DETAIL: Failing row contains (1, null, null, null, null). 

解决方案的工作无论是创建或不基于表的任何意见。

1

单独触发&触发功能为ON DELETE来简化。 (你没有做任何事情ON DELETE呢?)

一个CHECK约束像klin suggested似乎是一个不错的主意。不过,你不需要COALESCE。检查一个值为NULL。

CHECK (NOT ROW(lastname, firstname) IS NULL) -- ROW keyword is noise 

这加强了该行中的至少一个NOTNULL值。适用于任意数量的列和任何数据类型。

特别注意,ROW(lastname, firstname) IS NOT NULL是不一样的,不会工作。详细说明:

如果CHECK约束不是一个选项,您可以使用触发器一样的表情 - 这应该是比它添加到触发功能更快。 The manual on CREATE TRIGGER:

Also, a trigger definition can specify a Boolean WHEN condition, which will be tested to see whether the trigger should be fired. In row-level triggers the WHEN condition can examine the old and/or new values of columns of the row.

CREATE TRIGGER tg_update_person_view 
INSTEAD OF INSERT OR UPDATE ON Person_View 
FOR EACH ROW 
WHEN (NOT (NEW.lastname, NEW.firstname) IS NULL) -- more columns? 
EXECUTE PROCEDURE update_person_view_table(); 

如果WHEN表达式的值不以TRUE,触发功能甚至不叫 - 因此它does not proceed像要求。


但是,我错过了你的触发器是INSTEAD OFThe manual:

INSTEAD OF triggers do not support WHEN conditions.

在这种情况下,你必须检查进入的函数体:

IF NOT (NEW.lastname, NEW.firstname) IS NULL THEN 
    -- do stuff 
END IF; 
+0

我得到这个错误:'错误:INSTEAD OF触发器不能在条件********** **********错误'。 – kaycee

+0

@ kaycee:哦,对不起。不适用于INSTEAD触发器。在这种情况下,您必须将支票移入功能。 (你认为'CHECK'约束?) –