postgres函数中的make语句以原子方式运行

时间:2012-10-08 10:06:39

标签: postgresql transactions

我有以下postgres功能

CREATE OR REPLACE FUNCTION refresh_materialized_view(name)
  RETURNS integer AS
$BODY$
DECLARE
  _table_name ALIAS FOR $1;
  _entry materialized_views%ROWTYPE;
  _result INT;
BEGIN

  SELECT * INTO _entry FROM materialized_views WHERE table_name = _table_name;

  BEGIN;
    EXECUTE 'CREATE TEMP TABLE new_materialized_view_rows ON COMMIT DROP AS SELECT * FROM ' || _entry.view_name;
    EXECUTE 'TRUNCATE TABLE ' || _table_name;
    EXECUTE 'INSERT INTO ' || _table_name || ' SELECT * FROM new_materialized_view_rows';

    UPDATE materialized_views
    SET    last_refresh = CURRENT_TIMESTAMP
    WHERE  table_name = _table_name;
  COMMIT;

  EXECUTE 'ANALYZE ' || table_name; 
  RETURN 1;
END
$BODY$
LANGUAGE plpgsql VOLATILE SECURITY DEFINER;

ALTER FUNCTION refresh_materialized_view(name) OWNER TO portal;

该函数是从非事务性上下文调用的,所以我附上了使用

更新数据的语句
BEGIN; 

COMMIT;

以便这些语句以原子方式执行。但是,当我执行上面的脚本时,我收到以下错误:

ERROR:  syntax error at or near ";"
LINE 16:   BEGIN;

2 个答案:

答案 0 :(得分:1)

函数始终是调用事务的一部分。您无法在函数中提交事务。因此,您需要在调用代码中执行以下操作:

begin;
select efresh_materialized_view('foobar');
commit;


从非交易环境调用该函数
这是不可能的。如果没有PostgreSQL中的事务,您将无法工作。您可能是指“自动提交”模式,它隐含地提交每个语句 - 但这仍然是事务性的。

答案 1 :(得分:0)

您不能在函数中使用COMMIT。无论如何,这个函数都是事务性的,这就是为什么你不需要第二个BEGIN;同样。这也是你的错误,这是它失败的地方。