sql过程创建应该在其他sql过程中使用的临时表。 我试过了
CREATE or replace FUNCTION f_createquery()
RETURNS TABLE ( kuupaev date
) AS $f_createquery$
-- actually this is big and time consuming select statement which should evaluated only once:
select current_date as kuupaev
$f_createquery$ LANGUAGE sql STABLE;
CREATE or replace FUNCTION f_usequery()
RETURNS TABLE ( kuupaev date
) AS $f_usequery$
-- big query tehing is used several times in query:
select kuupaev from tehing
union all
select kuupaev+1 from tehing
union all
select kuupaev+2 from tehing
$f_usequery$ LANGUAGE sql STABLE;
with tehing as (
select * from f_createquery() _
)
select * from f_usequery() _
但收到错误
ERROR: relation "tehing" does not exist
tehing包含由存储过程创建的临时数据,它在数据库中不存在。如何允许其他存储过程使用它? 如何修复Postgres 9.1+?
是否有像
这样的东西external table (kuupaev date)
允许定义外部表? 在实际应用中,f_createquery中的select语句很大且很耗时,应该只评估一次。
将select * from tehing
替换为f_usequery()
中的动态sql可能有效但这可以防止在运行时编译过程。是否有更好的解决方案或tehing更好地通过其他存储过程,e.q。喜欢参数?
或者f_createquery应该创建具有固定名称tehing的临时表吗?
答案 0 :(得分:2)
如果In [15]: import pandas as pd
In [16]: df = pd.DataFrame([['67:01'],['11:11'],['59:59'],['09:08']],columns=['Used'])
In [17]: df
Out[17]:
Used
0 67:01
1 11:11
2 59:59
3 09:08
In [18]: import datetime
In [19]: df.Used.apply(lambda x: datetime.timedelta(minutes=int(x.split(':')[0]), seconds=int(x.split(':')[1])))
Out[19]:
0 01:07:01
1 00:11:11
2 00:59:59
3 00:09:08
Name: Used, dtype: timedelta64[ns]
生成临时表df.Used.apply(lambda x: float(x.split(':')[0]) + float(x.split(':')[1])/60)
,则它不应返回任何内容。您的功能应如下所示:
f_createquery()
然后,您可以像使用其他任何表一样使用当前会话中的tehing
表 :
CREATE FUNCTION f_createquery() RETURNS void AS $f_createquery$
CREATE TEMPORARY TABLE tehing AS
SELECT current_date AS kuupaev; -- complex query here
$f_createquery$ LANGUAGE sql STABLE;
请注意,会话结束时会删除临时表。
您还可以集成这两个功能,这样您就可以调用tehing
而无需担心先调用另一个函数:
CREATE FUNCTION f_usequery() RETURNS TABLE (kuupaev date) AS $f_usequery$
SELECT kuupaev FROM tehing
UNION ALL
SELECT kuupaev+1 FROM tehing
UNION ALL
SELECT kuupaev+2 FROM tehing;
$f_usequery$ LANGUAGE sql STABLE;
请注意,现在这是一个f_usequery()
函数,因此语法略有不同。
构造
CREATE FUNCTION f_usequery() RETURNS TABLE (kuupaev date) AS $f_usequery$
BEGIN
PERFORM 1 FROM information_schema.tables WHERE table_name = 'tehing';
IF NOT FOUND THEN -- temp table tehing does not exist
CREATE TEMPORARY TABLE tehing AS
SELECT current_date AS kuupaev; -- etc, etc
END IF;
RETURN QUERY
SELECT kuupaev FROM tehing
UNION ALL
SELECT kuupaev+1 FROM tehing
UNION ALL
SELECT kuupaev+2 FROM tehing;
END; $f_usequery$ LANGUAGE plpgsql STABLE;
不会工作,因为你因CTE而重新宣布plpgsql
。相反,with tehing as (
select * from f_createquery() _
)
select * from f_usequery() _
适用于tehing
临时表,您可以从中选择或使用f_usequery()
的结果进行进一步分析:
tehing
答案 1 :(得分:0)
如果您可以在单个查询中执行所有操作,则通常不需要临时表或函数。 CTE完成工作:
WITH tehing AS (
SELECT current_date AS kuupaev -- expensive query here
)
SELECT kuupaev FROM tehing
UNION ALL
SELECT kuupaev+1 FROM tehing
UNION ALL
SELECT kuupaev+2 FROM tehing;
如果您实际上必须使用昂贵查询的结果运行多个查询,那么临时表才有意义。或者,如果您需要在表格上创建索引。
尝试创建临时表:
CREATE TEMP TABLE tehing AS
SELECT current_date AS kuupaev; -- expensive query here
如果表格已经存在,则会出现错误,这也很好
然后使用tehing
运行您的查询。
如果你真的需要一个避免这个错误的函数(我怀疑):
CREATE FUNCTION f_create_tbl()
RETURNS text AS
$func$
BEGIN
IF to_regclass('pg_temp.tehing') IS NULL THEN -- temp table does not exist
CREATE TEMP TABLE tehing AS
SELECT current_date AS kuupaev; -- expensive query here
RETURN 'Temp table "tehing" created.';
ELSE
RETURN 'Temp table "tehing" already exists';
END IF;
END
$func$ LANGUAGE plpgsql;
呼叫:
SELECT f_create_tbl();
该函数无法声明为STABLE
,它是VOLATILE
函数(默认值)。
这样的测试会非常不准确:
PERFORM 1 FROM information_schema.tables WHERE table_name = 'tehing';
它会在搜索路径中找到名为“tehing”的任何表。但您只对存在该名称的临时表感兴趣。默认情况下,临时模式首先位于搜索路径中:
相关: