使用这些临时表返回选择查询的临时表创建函数

Posted

技术标签:

【中文标题】使用这些临时表返回选择查询的临时表创建函数【英文标题】:Create function with temporary tables that return a select query using these temp tables 【发布时间】:2017-09-24 11:21:11 【问题描述】:

我需要创建一个函数,它返回 SELECT 查询的结果。此 SELECT 查询是在此函数内创建的几个临时表的 JOIN。有没有办法创建这样的功能?下面是一个例子(非常简化,实际上有多个临时表,查询很长):

CREATE OR REPLACE FUNCTION myfunction () RETURNS TABLE (column_a TEXT, column_b TEXT) AS $$
BEGIN
CREATE TEMPORARY TABLE raw_data ON COMMIT DROP
AS
SELECT d.column_a, d2.column_b FROM dummy_data d JOIN dummy_data_2 d2 using (id);

RETURN QUERY (select distinct column_a, column_b from raw_data limit 100);
END;
$$
LANGUAGE 'plpgsql' SECURITY DEFINER

我得到错误:

[Error] Script lines: 1-19 -------------------------
 ERROR: RETURN cannot have a parameter in function returning set;
 use RETURN NEXT at or near "QUERY"Position: 237

对于任何明显的错误,我提前道歉,我是新手。

Psql 版本是 PostgreSQL 8.2.15 (Greenplum Database 4.3.12.0 build 1)

【参考方案1】:

最新版本的 Greenplum 数据库 (5.0) 基于 PostgreSQL 8.3,它支持 RETURN QUERY 语法。刚刚测试了你的功能:

PostgreSQL 8.4devel (Greenplum Database 5.0.0-beta.10+dev.726.gd4a707c762 build dev)

【讨论】:

【参考方案2】:

这可能在 Postgres 中引发的最可能错误:

错误:列“foo”指定了多次

意思是,两个表中至少包含一个列名(id 除外,它通过USING 子句折叠到一个实例中)。这不会在允许重复输出列名称的普通 SQL SELECT 中引发异常。但是您不能创建具有重复名称的表。

这个问题也适用于 Greenplum(就像你后来声明的那样),它是 不是 Postgres。它于 2005 年从 PostgreSQL 分叉出来并单独开发。当前的 Postgres 手册几乎不再适用。看Greenplum documentation。

psql 只是标准的 PostgreSQL 交互式终端程序。显然,您使用的是 PostgreSQL 8.2.15 附带的那个,但 RDBMS 仍然是 Greenplum,而不是 Postgres。

语法修复(对于 Postgres,就像你第一次标记,仍然相关):

CREATE OR REPLACE FUNCTION myfunction()
  RETURNS TABLE (column_a text, column_b text) AS
$func$
BEGIN
   CREATE TEMPORARY TABLE raw_data ON COMMIT DROP AS
   SELECT d.column_a, d2.column_b  -- explicit SELECT list avoids duplicate column names
   FROM   dummy_data   d
   JOIN   dummy_data_2 d2 using (id);

   RETURN QUERY
   SELECT DISTINCT column_a, column_b
   FROM   raw_data
   LIMIT  100;
END
$func$  LANGUAGE plpgsql SECURITY DEFINER;

该示例不需要临时表 - 除非您在同一事务中的函数调用之后访问临时表 (ON COMMIT DROP)。否则,一个普通的 SQL 函数在各个方面都更好。 Postgres Greenplum的语法:

CREATE OR REPLACE FUNCTION myfunction(OUT column_a text, OUT column_b text)
  RETURNS SETOF record AS
$func$
   SELECT DISTINCT d.column_a, d2.column_b
   FROM   dummy_data   d
   JOIN   dummy_data_2 d2 using (id)
   LIMIT  100;
$func$  LANGUAGE plpgsql SECURITY DEFINER;

同样重要的是,it should also work for Greenplum。

这个函数唯一剩下的原因是SECURITY DEFINER。否则,您可以只使用简单的 SQL 语句(可能作为准备好的语句)。

RETURN QUERY 在 2008 年被添加到 PL/pgSQL 的 8.3 版中, Greenplum 的分支之后几年。可能会解释您的错误消息:

ERROR: RETURN cannot have a parameter in function returning set;
use RETURN NEXT at or near "QUERY" Position: 237

除此之外:LIMIT 没有 ORDER BY 会产生任意结果。我想你已经知道了。


如果由于某种原因您确实需要临时表并且无法升级到 Greenplum 5.0 like A. Scherbaum suggested,您仍然可以使其在 Greenplum 4.3.x 中工作(就像在 Postgres 8.2 中一样)。将 FOR 循环与 RETURN NEXT 结合使用。 例子:

plpgsql error "RETURN NEXT cannot have a parameter in function with OUT parameters" in table-returning function How to use `RETURN NEXT`in PL/pgSQL correctly? Use of custom return types in a FOR loop in plpgsql

【讨论】:

以上是关于使用这些临时表返回选择查询的临时表创建函数的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL临时表使用方法

基本sql语句--临时表

MySQL中的临时表使用方法讲解

数据库教程MySQL 临时表

sql如何创建临时表

关于mysql建立临时表的问题(新手入门)