从游标返回表

Posted

技术标签:

【中文标题】从游标返回表【英文标题】:Returning a table from a cursor 【发布时间】:2013-07-10 04:21:21 【问题描述】:

我有一个函数可以根据客户 ID 返回一个计算值表。我需要为所有客户获取价值;我做了一个游标,但我不能让它返回集合。

客户表:

id    name
----  ----
CN102 Dude
CN103 Guy
CN104 Mate

功能:

SELECT * FROM get_custom_fields('CN104');

name  field_value
----  -----
POP    9
Z44   blue
POP    19

请注意,可能有多行具有相同的名称。 这是我的光标:

CREATE OR REPLACE FUNCTION my_cursor () 
RETURNS SETOF RECORD AS $$
DECLARE
    v_customer_rec RECORD;
    v_pop RECORD;
BEGIN
    FOR v_customer_rec IN SELECT ucn FROM customer LOOP
        SELECT INTO v_pop field_value from get_custom_fields(v_customer_rec.ucn) where custom_field='POP';
        RAISE NOTICE 'Customer % Value %', v_customer_rec.ucn,v_pop;
        --   RETURN QUERY select field_value from get_custom_fields(v_customer_rec.ucn) where custom_field='POP';
    END LOOP;
    RETURN;
END;
$$ LANGUAGE plpgsql;

这会返回:

db=# select my_cursor();
NOTICE:  Customer CN102 Value (5)
NOTICE:  Customer CN103 Value (12)
NOTICE:  Customer CN104 Value (9)
NOTICE:  Customer CN104 Value (19)
 my_cursor 
-------------
(0 rows)

所以我知道它应该工作。但是如果使用RETURN QUERY(如代码中所述)我会收到以下错误:

ERROR:  set-valued function called in context that cannot accept a set
CONTEXT:  PL/pgSQL function "my_cursor" line 9 at RETURN QUERY

如何让它返回表或集合中的值?

我想得到:

ucn   field_value
----- -----------
CN102 5
CN103 12
CN104 9
CN104 19

【问题讨论】:

函数active_customers()在哪里定义的? 我没有包含它,因为它只是在顶部吐出了客户表。假装它是来自客户的精选 *。 那么你应该在你的问题中使用select * from customer。请修复它,所以它对公众有意义,而不仅仅是对你。在您的问题下方使用edit ... 【参考方案1】:

您的(简化的)函数可能如下所示:

CREATE OR REPLACE FUNCTION my_cursor() 
  RETURNS SETOF RECORD AS
$func$
DECLARE
   _ucn text;
BEGIN

FOR _ucn IN
    SELECT ucn FROM customer
LOOP
    RETURN QUERY
    SELECT *
    FROM   get_custom_fields(_ucn)
    WHERE  name = 'POP';
END LOOP;

RETURN;

END
$func$ LANGUAGE plpgsql;

我在这里假设ucn 的数据类型为text

但实际上,您应该定义RETURN 类型,以避免每次调用都必须提供列定义列表。如果你只想要列field_value,它是text

CREATE OR REPLACE FUNCTION my_cursor() 
  RETURNS SETOF text AS
$func$
DECLARE
   _ucn text;
BEGIN

FOR _ucn IN
    SELECT ucn FROM customer
LOOP
    RETURN QUERY
    SELECT field_value
    FROM   get_custom_fields(_ucn)
    WHERE  name = 'POP';
END LOOP;

RETURN;

END
$func$ LANGUAGE plpgsql;

或者对每行多列使用RETURNS TABLE()

CREATE OR REPLACE FUNCTION my_cursor() 
  RETURNS TABLE(ucn text, field_value text) AS
$func$
DECLARE
   _ucn text;
BEGIN

FOR _ucn IN
    SELECT c.ucn FROM customer c
LOOP
    RETURN QUERY
    SELECT g.ucn, g.field_value
    FROM   get_custom_fields(_ucn) g
    WHERE  g.name = 'POP';
END LOOP;

RETURN;

END
$func$ LANGUAGE plpgsql;

请注意,RETURN 类型的列在函数体中是可见的。对同名的列进行表限定以避免命名冲突。

【讨论】:

非常感谢,第二个版本完美运行。我尝试了第一个,但我无法让它返回一张桌子。问题是某些客户将有多个 POP 值(已编辑问题),因此输出应类似于: ucn field_vaule ----- ----------- CN102 5 CN103 12 CN103 66 CN104 9 @RaiderofthelostBBS:我添加了另一个来覆盖它。 @RaiderofthelostBBS:关于格式化:点击[添加评论]下的帮助链接,同时写一个寻求帮助。或者看here。 :)

以上是关于从游标返回表的主要内容,如果未能解决你的问题,请参考以下文章

ibatis 怎么返回oracle游标

MySQL 存储过程,获取使用游标查询的结果集

SQLite SELECT MAX() 查询返回 null 到游标?

在 UDF 中使用游标,返回具有不同表名称的列

如何从 plsql 函数创建和返回游标?

python cx_Oracle 游标不返回有效查询的行