Jac*_*las 6 postgresql functions postgresql-9.3 temporary-tables
查询语言 (SQL) 和 PL/pgSQL 函数对临时表的处理方式不同:
begin;
create table foo(id) as values (1);
select * from foo;
/*
id
----
1
*/
savepoint s;
create function f() returns setof integer language sql as $$
create temporary table foo(id) on commit drop as values (2);
select id from foo;
$$;
select * from f();
/*
f
---
1
*/
rollback to s;
create function f() returns setof integer language plpgsql as $$
begin
create temporary table foo(id) on commit drop as values (2);
return query select id from foo;
end;
$$;
select * from f();
/*
f
---
2
*/
rollback;
Run Code Online (Sandbox Code Playgroud)
文档说:
...当临时表存在时,具有相同名称的现有永久表对当前会话不可见,除非它们被模式限定名称引用...
这并没有提到上面演示的异常。这在其他地方有记录吗?
这是因为在执行 SQL 函数时,会解析并执行整个函数体。但是用PLPGSQL函数逐条语句进行解析和执行。由于这个原因,SQL 函数无法看到函数执行期间创建的临时表。
换句话说,这适用于其他对象,而不仅仅是临时表。这也很容易证明:
begin;
--
create function pg_temp.f() returns integer language sql as $$select 1;$$;
create function g() returns integer language sql as $g$
create or replace function pg_temp.f() returns integer language sql as $$select 2;$$;
select pg_temp.f();
$g$;
--
select g();
/*
g
---
1
*/
select g();
/*
g
---
2
*/
--
rollback;
Run Code Online (Sandbox Code Playgroud)
甚至:
begin;
create schema stack;
set search_path to stack;
create temp table foo(id) on commit drop as values (1);
select * from foo;
/*
id
----
1
*/
savepoint s;
create function f() returns setof integer language sql set search_path = stack, pg_temp as $$
create table foo(id) as values (2);
select id from foo;
$$;
select * from f();
/*
f
---
1
*/
rollback to s;
create function f() returns setof integer language plpgsql set search_path = stack, pg_temp as $$
begin
create table foo(id) as values (2);
return query select id from foo;
end;
$$;
select * from f();
/*
f
---
2
*/
rollback;
Run Code Online (Sandbox Code Playgroud)
关于 pgsql-bugs 的建议是修改文档以明确此行为。
编辑: