加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

postgresql – 来自可更新视图的RETURNING数据不起作用?

发布时间:2020-12-13 15:52:50 所属栏目:百科 来源:网络整理
导读:我有两个简单的表人和地址,插入通过可更新的视图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
我有两个简单的表人和地址,插入通过可更新的视图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;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读