使用使用临时表的函数的物化视图

时间:2018-08-16 11:17:48

标签: postgresql postgresql-9.6

我有一个存储过程,该过程在其主体中使用一个临时表。尝试使用此过程创建实例化视图,例如

CREATE MATERIALIZED VIEW my_view AS SELECT * FROM my_function;

给我一​​个错误:

ERROR:  cannot create temporary table within security-restricted operation

在源代码中的注释中对此进行了解释:

/*
 * Security check: disallow creating temp tables from security-restricted
 * code.  This is needed because calling code might not expect untrusted
 * tables to appear in pg_temp at the front of its search path.
 */

除了重新整理存储过程本身不使用临时表之外,是否还有其他解决方法?

1 个答案:

答案 0 :(得分:2)

此限制背后的思想是防止在刷新实例化视图后更改会话状态。实际上,您在源代码中添加的注释中对此进行了解释(尽管可能会造成混淆)。

换句话说,这意味着即使已经存在具有相同名称的常规表,查询也可能会选择一个新的临时表(可以在函数中创建)。查找表时,pg_temp模式被隐式添加到SEARCH PATH中。


我可以想到两种解决方法:

  1. 使用普通表而不是临时表。您可以指定UNLOGGED以获得更好的性能。

示例代码:

CREATE FUNCTION my_function()
RETURNS BOOLEAN
LANGUAGE 'plpgsql'
AS '
BEGIN
    DROP TABLE IF EXISTS my_tmp_table;
    CREATE UNLOGGED TABLE my_tmp_table(a int); -- regular unlogged table
    RETURN TRUE;
END';

CREATE MATERIALIZED VIEW my_view AS SELECT * FROM my_function(); -- materialized view
  1. 创建一个常规表,而不是物化视图,然后在需要刷新时放下并重新创建它

示例代码:

CREATE FUNCTION my_function()
RETURNS BOOLEAN
LANGUAGE 'plpgsql'
AS '
BEGIN
    DROP TABLE IF EXISTS my_tmp_table;
    CREATE TEMP TABLE my_tmp_table(a int); -- temp table
    RETURN TRUE;
END';

CREATE TABLE my_view AS SELECT * FROM my_function(); -- table, not a view