postgresql Postgres 从动态 sql 字符串创建本地临时表(提交删除时)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12217782/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Postgres creating a local temp table (on commit drop) from a dynamic sql string
提问by Hassan Syed
I have a query string generated in a postgres UDF, i'd like to put it's result in a temp table to perform joins against (I'm using LIMIT
and OFFSET
, and I don't want to join against other ttables only to end up choping the data off at the end --i.e., the LIMIT operator in the query plan). I attempt to create the temp table with the following statement.
我有一个在 postgres UDF 中生成的查询字符串,我想把它的结果放在一个临时表中来执行连接(我正在使用LIMIT
and OFFSET
,我不想加入其他 ttables 只是为了最终切碎最后关闭数据——即查询计划中的 LIMIT 运算符)。我尝试使用以下语句创建临时表。
CREATE LOCAL TEMP TABLE query_result ON COMMIT DROP AS EXECUTE query_string_;
But I get the following error notice :
但我收到以下错误通知:
********** Error **********
ERROR: prepared statement "query_string_" does not exist
SQL state: 26000
Context: SQL statement "CREATE LOCAL TEMP TABLE query_result ON COMMIT DROP AS EXECUTE query_string_"
PL/pgSQL function "search_posts_unjoined" line 48 at SQL statement
Additionally, I tried preparing the statemen, but I couldn't get the syntax right either.
此外,我尝试准备 statemen,但我也无法正确使用语法。
The UDF in question is :
有问题的UDF是:
CREATE OR REPLACE FUNCTION search_posts_unjoined(
forum_id_ INTEGER,
query_ CHARACTER VARYING,
offset_ INTEGER DEFAULT NULL,
limit_ INTEGER DEFAULT NULL,
from_date_ TIMESTAMP WITHOUT TIME ZONE DEFAULT NULL,
to_date_ TIMESTAMP WITHOUT TIME ZONE DEFAULT NULL,
in_categories_ INTEGER[] DEFAULT '{}'
)
RETURNS SETOF forum_posts AS $$
DECLARE
join_string CHARACTER VARYING := ' ';
from_where_date CHARACTER VARYING := ' ';
to_where_date CHARACTER VARYING := ' ';
query_string_ CHARACTER VARYING := ' ';
offset_str_ CHARACTER VARYING := ' ';
limit_str_ CHARACTER VARYING := ' ';
BEGIN
IF NOT from_date_ IS NULL THEN
from_where_date := ' AND fp.posted_at > ''' || from_date_ || '''';
END IF;
IF NOT to_date_ IS NULL THEN
to_where_date := ' AND fp.posted_at < ''' || to_date_ || '''';
END IF;
IF NOT offset_ IS NULL THEN
offset_str_ := ' OFFSET ' || offset_;
END IF;
IF NOT limit_ IS NULL THEN
limit_str_ := ' LIMIT ' || limit_;
END IF;
IF NOT limit_ IS NULL THEN
END IF;
CREATE LOCAL TEMP TABLE un_cat(id) ON COMMIT DROP AS (select * from unnest(in_categories_)) ;
if in_categories_ != '{}' THEN
join_string := ' INNER JOIN un_cat uc ON uc.id = fp.category_id ' ;
END IF;
query_string_ := '
SELECT fp.*
FROM forum_posts fp' ||
join_string
||
'WHERE fp.forum_id = ' || forum_id_ || ' AND
to_tsvector(''english'',fp.post_text) @@ to_tsquery(''english'','''|| query_||''')' ||
from_where_date ||
to_where_date ||
offset_str_ ||
limit_str_
|| ';';
CREATE LOCAL TEMP TABLE query_result ON COMMIT DROP AS EXECUTE query_string_;
RAISE NOTICE '%', query_string_;
RETURN QUERY
EXECUTE query_string_;
END;
$$ LANGUAGE plpgsql;
And it works when the statement in question is removed.
当有问题的语句被删除时它会起作用。
回答by Erwin Brandstetter
Use instead:
改用:
EXECUTE '
CREATE TEMP TABLE query_result ON COMMIT DROP AS '|| query_string_;
EXECUTE
the whole statement.
The syntax formCREATE TABLE foo AS EXECUTE <query>
isn't valid.LOCAL
is just a noise word and ignored in this context.
EXECUTE
整个声明。
语法形式CREATE TABLE foo AS EXECUTE <query>
无效。LOCAL
只是一个干扰词,在这种情况下被忽略。
More details in the manual.