5

这可能是因为我累了,或者我是 postgres 的新手。但是,我试图在函数中使用临时表,而 postgres 抱怨“关系不存在”。但是,如果我采用函数的主体并执行它,它就可以正常工作。下面是我正在尝试创建的函数类型的示例。请记住,我已经删除了所有有趣的东西,以至于它几乎可以显示我的问题。

CREATE OR REPLACE FUNCTION dbo.somefunc() RETURNS void AS
$BODY$ 

CREATE TEMPORARY TABLE work_list
(
    name text,
    level smallint
);

insert into work_list
    (name, level)
values
    ('someone', 25);

$BODY$
LANGUAGE sql VOLATILE;

我收到的投诉在插入语句中。实际投诉是:

ERROR:  relation "work_list" does not exist

postgres 不支持函数中的临时表吗?或者是否有一些我错过的语法东西让我窒息并且它给了我一个虚假的错误?

4

2 回答 2

4

Postgres 对您尝试创建的函数运行一些简单的检查,并且它(正确地)发现该表work_list(尚)不存在。我看到两个选项:

1.“假装直到你成功”

在创建函数之前实际创建(临时)表。临时表将在会话结束时消失,但是一旦创建了函数,您就已经通过了这个测试。
显然,在同一会话中运行该函数之前,您必须删除该表以避免冲突。不过更好的是:CREATE TEMP TABLE IF NOT EXISTS在你的函数中使用(Postgres 9.1+)。如果表已经存在,您可能想要截断它......

但是(请参阅下面的评论),引用手册

SQL 函数的整个主体在执行之前都会被解析。虽然 SQL 函数可以包含更改系统目录的命令(例如CREATE TABLE),但在对函数中的后续命令进行解析分析期间,这些命令的效果将不可见。因此,例如,如果打包到单个 SQL 函数中,将无法按预期工作,因为 foo 在解析命令 CREATE TABLE foo (...); INSERT INTO foo VALUES(...);时还不存在。在这种情况下,建议使用 PL/pgSQL 而不是 SQL 函数。INSERT

大胆强调我的。

2. 改用 PL/pgSQL

plpgsql 中的检查不太彻底。如果 Postgres 仍然抱怨(在这种情况下没有),您也可以使用EXECUTE.

旁白:在许多情况下,没有临时表的性能更高的解决方案即将到来......

于 2013-10-14T07:21:57.567 回答
0

结合这两个陈述。通过执行“select into”类型语法来创建临时表。这样你就可以做到。 CREATE TEMP TABLE SomeTable AS SELECT * FROM OtherTable ;

于 2014-10-30T22:57:41.700 回答