Postgres插入视图规则与返回条款

时间:2014-03-24 23:28:40

标签: postgresql sql-insert sql-returning

我试图在Postgres v9.4中允许带有返回子句的insert语句进入视图,但我正在努力学习语法。这就是我想要调用insert语句的方法:

CREATE VIEW MyView AS SELECT a.*, b.someCol1
    FROM tableA a JOIN tableB b USING(aPrimaryKey);
INSERT INTO MyView (time, someCol) VALUES (someTime, someValue) RETURNING *;
INSERT INTO MyView (someCol) VALUES (someValue) RETURNING *;

请注意,时间的默认值为NOW()。这就是我到目前为止所做的:

CREATE RULE MyRuleName AS ON INSERT TO MyView DO INSTEAD (
    INSERT INTO tableA (time) VALUES COALESCE(NEW.time, NOW());
    INSERT INTO tableB (aPrimaryKey, someCol)
        VALUES (CURRVAL('tableA_aPrimaryKey_seq'), NEW.someValue);
);

上面的工作是插入值,但我正在努力尝试找出如何添加返回的语句。我没有成功尝试以下内容:

CREATE RULE MyRuleName AS ON INSERT TO MyView DO INSTEAD (
    INSERT INTO tableA (time) VALUES COALESCE(NEW.time, NOW())
        RETURNING *, NEW.someValue;
    INSERT INTO tableB (aPrimaryKey, someCol)
        VALUES (CURRVAL('tableA_aPrimaryKey_seq'), NEW.someValue);
);
-- ERROR:  invalid reference to FROM-clause entry for table "new"

CREATE RULE MyRuleName AS ON INSERT TO MyView DO INSTEAD (
    WITH a AS (INSERT INTO tableA (time)
        VALUES COALESCE(NEW.time, NOW()) RETURNING *)
    INSERT INTO tableB (aPrimaryKey, someCol)
        SELECT aPrimaryKey, NEW.someValue FROM a RETURNING *;
);
-- ERROR:  cannot refer to NEW within WITH query

哎呀!有没有人知道添加返回语句的方法,该语句将第一个插入中的主键(SERIAL)和时间(TIMESTAMP WITH TIME ZONE)添加到数据库中,以及第二个插入中的someCol值?谢谢!

1 个答案:

答案 0 :(得分:6)

在这里使用INSTEAD OF INSERT触发器会好得多:

CREATE FUNCTION MyFuncName() RETURNS trigger AS $$
DECLARE
  id integer;
BEGIN
  INSERT INTO tableA (time) VALUES COALESCE(NEW.time, NOW()) RETURNING aPrimaryKey INTO id;
  INSERT INTO tableB (aPrimaryKey, someCol1) VALUES (id, NEW.someValue);
  RETURN NEW;
END; $$ LANGUAGE PLPGSQL;

CREATE TRIGGER MyView_on_insert INSTEAD OF INSERT ON MyView
  FOR EACH ROW EXECUTE PROCEDURE MyFuncName();

检查序列的当前值以查看在另一个表中插入的内容是坏坏坏练习。即使您在一次交易中,也不要这样做。

您对RETURNING信息的问题感到困惑,因为当我阅读您的问题时,我也很困惑。在函数内部使用INTO子句填充本地声明的变量来保存记录值,然后可以在后续语句中使用这些记录值。在函数外部,使用RETURNING子句,就像在最顶部的代码段中一样。