如何在其他过程中使用在存储过程中创建的查询
How to use query created in stored procedure in other procedure
sql 过程创建临时 table 应该在其他 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)
哪个允许定义外部table?
在实际应用中 select f_createquery 中的语句很大且耗时,应该只评估一次。
将 select * from tehing
替换为 f_usequery()
中的动态 sql 可能有效,但这会阻止程序在 运行 时编译。是否有更好的解决方案或可以更好地传递给其他存储过程,e.q。喜欢参数 ?
或者 f_createquery 是否应该使用固定名称 tehing 创建临时 table?
如果 f_createquery()
产生临时 table tehing
那么它不应该 return 任何东西。您的函数应如下所示:
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
table ,就像使用其他 table:
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;
请注意,临时 table 在会话结束时被删除。
您还可以集成这 2 个函数,这样您就可以调用 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;
请注意,这现在是一个 plpgsql
函数,因此语法略有不同。
结构
with tehing as (
select * from f_createquery() _
)
select * from f_usequery() _
将不起作用,因为您重新声明 tehing
作为 CTE 的结果。相反,f_usequery()
与 tehing
临时 table 一起工作,您可以从中 select 或对 f_usequery()
:
的结果进行进一步分析
SELECT f_createquery(); -- this creates the tehing temporary table
SELECT * FROM f_usequery(); -- this operates on the tehing table and returns some results
SELECT *
FROM tableX
JOIN f_usequery() USING (kuupaev)
WHERE kuupaev < '2015-09-19';
简单案例:CTE
如果您可以在 单个 查询中完成所有操作,您通常根本不需要临时 table 或函数。 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;
如果你需要临时工 table
临时 table 仅当您确实需要 运行 使用昂贵查询的结果进行多次查询时才有意义。或者,如果您需要在 table 或其他内容上创建索引。
尝试创建临时文件 table:
CREATE TEMP TABLE tehing AS
SELECT current_date AS kuupaev; -- expensive query here
如果 table 已经存在,你会得到一个错误,这也没关系。
然后 运行 您的查询使用 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" 的 any table。但是您只对存在该名称的 temporary table 感兴趣。默认情况下,临时模式在搜索路径中排在第一位:
- How does the search_path influence identifier resolution and the "current schema"
相关:
- How to check if a table exists in a given schema
sql 过程创建临时 table 应该在其他 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)
哪个允许定义外部table? 在实际应用中 select f_createquery 中的语句很大且耗时,应该只评估一次。
将 select * from tehing
替换为 f_usequery()
中的动态 sql 可能有效,但这会阻止程序在 运行 时编译。是否有更好的解决方案或可以更好地传递给其他存储过程,e.q。喜欢参数 ?
或者 f_createquery 是否应该使用固定名称 tehing 创建临时 table?
如果 f_createquery()
产生临时 table tehing
那么它不应该 return 任何东西。您的函数应如下所示:
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
table ,就像使用其他 table:
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;
请注意,临时 table 在会话结束时被删除。
您还可以集成这 2 个函数,这样您就可以调用 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;
请注意,这现在是一个 plpgsql
函数,因此语法略有不同。
结构
with tehing as (
select * from f_createquery() _
)
select * from f_usequery() _
将不起作用,因为您重新声明 tehing
作为 CTE 的结果。相反,f_usequery()
与 tehing
临时 table 一起工作,您可以从中 select 或对 f_usequery()
:
SELECT f_createquery(); -- this creates the tehing temporary table
SELECT * FROM f_usequery(); -- this operates on the tehing table and returns some results
SELECT *
FROM tableX
JOIN f_usequery() USING (kuupaev)
WHERE kuupaev < '2015-09-19';
简单案例:CTE
如果您可以在 单个 查询中完成所有操作,您通常根本不需要临时 table 或函数。 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;
如果你需要临时工 table
临时 table 仅当您确实需要 运行 使用昂贵查询的结果进行多次查询时才有意义。或者,如果您需要在 table 或其他内容上创建索引。
尝试创建临时文件 table:
CREATE TEMP TABLE tehing AS
SELECT current_date AS kuupaev; -- expensive query here
如果 table 已经存在,你会得到一个错误,这也没关系。
然后 运行 您的查询使用 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" 的 any table。但是您只对存在该名称的 temporary table 感兴趣。默认情况下,临时模式在搜索路径中排在第一位:
- How does the search_path influence identifier resolution and the "current schema"
相关:
- How to check if a table exists in a given schema