从返回表(或setof记录)的函数中检索列

时间:2016-03-17 15:54:44

标签: postgresql

所有时间我都有这个问题的变体,而不记得如何解决方法,只有" oop如此简单,但如何?" ...也许有一些模式和最佳方式使用每种模式。让我们看看主要的一个,例如unnest()ts_stat()

首先,好的例子,没有问题,因为unnest()只返回一列:

SELECT * FROM unnest(array[1,2,3]) t(id); -- is ok, the int columns there!
SELECT unnest(array[1,2,3]) t(id); -- is ok, the int columns

WITH t AS (SELECT unnest(array[1,2,3]) as id)
 SELECT id, unnest(array[4,id]) as x
 FROM t;  -- more complex, but ok!

现在是一个返回已定义 SETOF RECORD 的函数,

SELECT * FROM ts_stat('SELECT kx FROM terms where id=2') -- GOOD
-- show all word|ndoc|nentry columns

SELECT ts_stat('SELECT kx FROM terms where id=2') as x -- BAD
-- because lost columns, show only "x" column... but works

-- NOTE: you can imagine any other function, as json_each(), etc.

请参阅GOOD / BAD注意事项......所以,这是问题:一个SETOF RECORD,其中包含更多的一列。在最简单的(unnest以上)情况下,解决方案是在" FROM侧"中使用,作为表格;但是,当RECORD有多个字段时,就会出现问题。

--MAIN EXAMPLE FOR THE DISCUSSION:
WITH t AS (SELECT unnest(array[1,2,3]) as id)
 SELECT id, ts_stat('SELECT kx FROM terms where id='||id) as x
 FROM t;  -- BAD, but works...

现在,在这个主要示例中,无法在" FROM侧"中使用ts_stat(),因此,表征模式一个函数在我们需要列的查询中返回TABLE或SETOF RECORD,但该函数不能在" FROM侧"

问题:这个模式的通用(和最优雅)解决方案是什么?如何(语法模式)显示列?

注意:另一个问题是,如果你不记得确切的解决方案的语法,你会尝试不起作用的东西......在这种情况下是一个错误:

WITH t AS (SELECT unnest(array[1,2,3]) as id)
 SELECT id, x.word, x.ndoc, x.nentry 
 FROM (
      SELECT t.nsid, 
             ts_stat('SELECT kx FROM terms where id='||id) as x
      FROM t
  ) s;

SQL PARSER ERROR(PostgreSQL 9.5):没有表" x"在FROM子句中

1 个答案:

答案 0 :(得分:1)

您应该从不SELECT列表中使用set-returning-function (SRF)。主要示例应使用隐式LATERAL JOIN

编写
SELECT v.id, x.*
FROM (VALUES (1),(2),(3)) v(id)
JOIN ts_stat('SELECT kx FROM terms where id=' || v.id) x ON true;

此处隐含lateral join,因为SRF可以引用FROM子句之前指定的关系中的列,而不使用关键字LATERAL。在上面的示例中,SRF ts_stat()对列和关系v(id)进行横向引用。您也可以使用例如子查询但您必须明确使用关键字LATERAL

请注意,虽然您可以在选择列表中使用SRF,但不建议使用它。您提供了unnest(anyarray)的示例,这是有趣的,因为还有重载的变体unnest(anyarray, ...)(即一次调用中不需要多个数组),当在选择列表中使用时会抛出错误; in只能用作行源。你不应该在选择列表中使用SRF的原因是当使用多个SRF时,没有明显的解决方案,每个SRF产生不同数量的行。