【问题标题】:Postgres Insert Into View Rule with Returning ClausePostgres 使用返回子句插入视图规则
【发布时间】:2014-03-24 23:28:40
【问题描述】:

我试图在 Postgres v9.4 中允许将带有返回子句的语句插入到视图中,但在语法上遇到了困难。这就是我想调用插入语句的方式:

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 的值?谢谢!

【问题讨论】:

  • 我强烈建议您为此使用ON UPDATE DO INSTEAD 触发器,而不是规则。

标签: postgresql sql-insert sql-returning


【解决方案1】:

在这里使用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();

检查序列的当前值以查看在另一个表中插入了什么是bad bad bad的做法。即使您在这里进行一次交易,也不要这样做。

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

【讨论】:

  • 抱歉,我花了这么长时间才接受这个答案,但直到今天我才有时间测试你的建议。经过一番研究,似乎大多数人建议使用触发器而不是规则,因为它具有可读性、可维护性和易用性。谢谢。
  • currval() 不只是 checking the current value of a sequence to see what was inserted in another table 就像名字所暗示的那样。 The manual:Return the value most recently obtained by nextval for this sequence in the current session. (An error is reported if nextval has never been called for this sequence in this session.) Because this is returning a session-local value, it gives a predictable answer whether or not other sessions have executed nextval since the current session did.
猜你喜欢
  • 1970-01-01
  • 2021-10-16
  • 2019-07-20
  • 2018-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多