从返回表(或记录集)的函数中检索列
Posted
技术标签:
【中文标题】从返回表(或记录集)的函数中检索列【英文标题】:Retrieval of columns from functions that returns table (or setof record) 【发布时间】:2016-03-17 15:54:43 【问题描述】:一直以来我都有这个问题的变体,不记得如何解决,只有“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.
查看好/坏注意事项...所以,这就是问题:包含多于一列的 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 的函数记录,在我们需要列的查询中,但函数不能在“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): FROM 子句中没有表“x”。
【问题讨论】:
【参考方案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 可以在不使用关键字 LATERAL
的情况下引用 FROM
子句之前指定的关系中的列。在上面的示例中,SRF ts_stat()
横向引用列和关系 v(id)
。您也可以使用例如子查询,但您必须明确使用关键字LATERAL
。
请注意,虽然您可以在选择列表中使用 SRF,但不鼓励使用它。您提供了unnest(anyarray)
的示例,这很有趣,因为还有重载变体unnest(anyarray, ...)
(即在一次调用中取消嵌套多个数组)在选择列表中使用时会引发错误; in 只能用作行源。不应在选择列表中使用 SRF 的原因是,在使用多个 SRF 时没有明显的解决方案,每个 SRF 产生不同的行数。
【讨论】:
好(!),这是“解决方案模式”。并且“永远不要在 SELECT 列表中使用 set-returning-function”是一个很好的规则。对于pg9+,不言而喻的理想解决方案是LATERAL JOIN
,你能举个例子吗? (将相同的查询转换为横向连接查询)
答案中的示例已经是隐式横向连接。有关更多解释,请参阅更新的答案。
糟糕,抱歉,这个评论问题的正确文本是“你能展示和明确的例子吗?”,使用 LATERAL 子句
...关于我的NOTE,PARSER ERROR,对你来说似乎是一个解析器BUG?
来吧,彼得。我添加了相关文档的链接并详细说明了横向连接。一点点自助在这里会有很长的路要走。如果您有一个特定与这篇文章相关的问题在查看文档之后,那么我很乐意提供帮助,但 SO 不是school。以上是关于从返回表(或记录集)的函数中检索列的主要内容,如果未能解决你的问题,请参考以下文章