我有两个简单的表人和地址,插入通过可更新的视图person_details.
关系和触发器
CREATE TABLE address ( id serial PRIMARY KEY,street varchar,town varchar NOT NULL ); CREATE TABLE person ( id serial PRIMARY KEY,first_name varchar,family_name varchar NOT NULL,address integer REFERENCES address );
所有者显然拥有完全权限,但普通用户只能通过包含两个表中详细信息的视图访问数据:
CREATE VIEW person_details AS SELECT p.id,p.first_name,p.family_name,a.street,a.town FROM person p LEFT JOIN address a ON a.id = p.address;
视图是可更新的,以便常规用户可以插入到视图下面的表中:
GRANT SELECT,INSERT ON person_details TO public;
我已经定义了将INSERT传播到表的触发器,所有工作都正常:
CREATE FUNCTION t0ii_person_details() RETURNS trigger AS $$ DECLARE addr integer; BEGIN -- Want at least a town to insert anything into table address. IF (NEW.town IS NOT NULL) THEN INSERT INTO address(street,town) VALUES (NEW.street,NEW.town) RETURNING id INTO addr; ELSE addr := NULL; END IF; INSERT INTO person(first_name,family_name,address) VALUES (NEW.first_name,NEW.family_name,addr); RETURN NEW; END; $$LANGUAGE plpgsql Security DEFINER; CREATE TRIGGER t0ii_person_details INSTEAD OF INSERT ON person_details FOR EACH ROW EXECUTE PROCEDURE t0ii_person_details();
插入 – 好的
一个简单的插入:
pfams=# INSERT INTO person_details (first_name,town) VALUES ('John','Doe','Eders'); INSERT 0 1 pfams=# SELECT * FROM person_details; id | first_name | family_name | street | town ----+------------+-------------+--------+-------- 1 | John | Doe | | Eders (1 row)
INSERT RETURNING id – 不行
但是,如果我想直接从INSERT语句返回新分配的id(来自于从序列,串行数据类型生成它的person表),那么我什么也得不到:
pfams=# INSERT INTO person_details (first_name,town) VALUES ('Jim','Eders') RETURNING id; id ---- (1 row) INSERT 0 1
但数据是:
pfams=# SELECT * FROM person_details; id | first_name | family_name | street | town ----+------------+-------------+--------+-------- 1 | John | Doe | | Eders 2 | Jim | Doe | | Eders (2 rows)
我在这里错过了什么?
pfams=# SELECT version(); version ----------------------------------------------------------------------------------------------------- Postgresql 9.3.6 on i686-pc-linux-gnu,compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3,32-bit
解决方法
你太近了;)你只需要在触发器中更新NEW.id.
CREATE FUNCTION t0ii_person_details() RETURNS trigger AS $$ DECLARE addr integer; BEGIN -- Want at least a town to insert anything into table address. IF (NEW.town IS NOT NULL) THEN INSERT INTO address(street,addr) -- here is the only change I made RETURNING id INTO NEW.id; RETURN NEW; END; $$LANGUAGE plpgsql Security DEFINER;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。