3

假设以下,相当简单的数据库:

CREATE TABLE test_table(
  name TEXT,
  data JSONB
);
INSERT INTO test_table VALUES ('name1', '{"a": 1, "b": 2}'), ('name2', '{"c": 3, "d": 4, "e": 5}');

所以我们有下表:

# SELECT * FROM test_table ;
 name  |           data
-------+--------------------------
 name1 | {"a": 1, "b": 2}
 name2 | {"c": 3, "d": 4, "e": 5}
(2 rows)

现在我看到了这样的查询:

# SELECT * FROM test_table CROSS JOIN JSONB_EACH(test_table.data);

返回以下结果:

 name  |           data           | key | value
-------+--------------------------+-----+-------
 name1 | {"a": 1, "b": 2}         | a   | 1
 name1 | {"a": 1, "b": 2}         | b   | 2
 name2 | {"c": 3, "d": 4, "e": 5} | c   | 3
 name2 | {"c": 3, "d": 4, "e": 5} | d   | 4
 name2 | {"c": 3, "d": 4, "e": 5} | e   | 5
(5 rows)

我的问题是我不明白这里发生了什么。一方面,这看起来像一个LATERAL连接,因为右侧 JOIN指的是左侧,结果是完全合乎逻辑的。另一方面,手册是这样说的:

(没有LATERAL,每个子项SELECT都是独立评估的,因此不能交叉引用任何其他FROM项目。)

还有这个:

列源表必须是INNERLEFT加入到LATERAL 项目 […]

(见这里),当然CROSS JOIN不会返回n × m 行(如本页所述)。

我的问题是:上面的查询结果与手册不矛盾吗?如果不是,这是否意味着JSONB_EACH以某种方式受到特殊对待?(我会感到惊讶。)

4

1 回答 1

5

如果不是,这是否意味着 JSONB_EACH 以某种方式受到特殊对待?

是的,因为它是一个表函数(又名“设置返回函数”)

从手册中引用

FROM 中出现的表函数也可以以关键字 LATERAL 开头,但对于函数,关键字是可选的;在任何情况下,函数的参数都可以包含对前面 FROM 项提供的列的引用。

(强调我的)

于 2019-10-08T05:42:28.957 回答