1

我有两个表,通过 is-relation 在 E/R 中连接。一个代表“母桌”

CREATE TABLE PERSONS(
      id                SERIAL NOT NULL,
      name              character varying NOT NULL,
      address           character varying NOT NULL,
      day_of_creation   timestamp NOT NULL DEFAULT current_timestamp,
      PRIMARY KEY (id)
)

另一个代表“子表”

CREATE TABLE EMPLOYEES (
      id               integer NOT NULL,
      store            character varying NOT NULL,
      paychecksize     integer NOT NULL,
      FOREIGN KEY (id)
              REFERENCES PERSONS(id),
      PRIMARY KEY (id)
)

现在这两个表连接在一个视图中

CREATE VIEW EMPLOYEES_VIEW AS
    SELECT 
       P.id,name,address,store,paychecksize,day_of_creation
    FROM 
       PERSONS AS P
    JOIN
       EMPLOYEES AS E ON P.id = E.id

我想编写规则或触发器以使 db 用户能够在该视图上进行插入,从而避免将拆分列的令人讨厌的细节放入不同的表中。

但我也想让它方便,因为 id 是一个 SERIAL 并且day_of_creation有一个默认值,用户不需要提供这些,因此像这样的语句

INSERT INTO EMPLOYEES_VIEW (name, address, store, paychecksize)
VALUES ("bob", "top secret", "drugstore", 42)

应该足以导致

人员

id|name|address   |day_of_creation
-------------------------------
1 |bob |top secret| 2013-08-13 15:32:42

雇员

id|   store |paychecksize
---------------------
1 |drugstore|42

一个基本规则很简单

CREATE RULE EMPLOYEE_VIEW_INSERT AS ON INSERT TO EMPLOYEE_VIEW
DO INSTED (
    INSERT INTO PERSONS
    VALUES (NEW.id,NEW.name,NEW.address,NEW.day_of_creation),
    INSERT INTO EMPLOYEES
    VALUES (NEW.id,NEW.store,NEW.paychecksize)
)

应该足够了。但这并不方便,因为用户必须提供 id 和时间戳,即使实际上没有必要。

如何重写/扩展该代码库以符合我的便利标准?

4

1 回答 1

1

就像是:

CREATE RULE EMPLOYEE_VIEW_INSERT AS ON INSERT TO EMPLOYEES_VIEW
DO INSTEAD 
(
    INSERT INTO PERSONS (id, name, address, day_of_creation)
    VALUES (default,NEW.name,NEW.address,default);
    INSERT INTO EMPLOYEES (id, store, paychecksize)
    VALUES (currval('persons_id_seq'),NEW.store,NEW.paychecksize)
);

这样,默认值persons.idpersons.day_of_creation将是默认值。另一种选择是简单地从插入中删除这些列:

INSERT INTO PERSONS (name, address)
VALUES (NEW.name,NEW.address);

定义规则后,以下插入应该可以工作:

insert into employees_view (name, address, store, paychecksize)
values ('Arthur Dent', 'Some Street', 'Some Store', 42);

顺便说一句:对于当前的 Postgres 版本,instead of触发器是使视图可更新的首选方式。

于 2013-08-13T14:08:39.733 回答