这是earlier one的后续问题。我有一个存储函数f1
,它接受两个参数返回一个包含5列的表;现在返回的值是常量,稍后它们将从参数计算。
我还有一个表t1
,其中有两列在类型上与f1
的参数相对应。
我现在要定义一个视图v1
,其中包含f1
为t1
中存储的所有参数对返回的所有行的并集。对于给定的示例值,结果应为:
+---+---+---+---+---+---+---+
| 2 | 3 | a | b | 1 | c | d |
+---+---+---+---+---+---+---+
| 4 | 5 | a | b | 1 | c | d |
+---+---+---+---+---+---+---+
如果前两列被剥离,那也没关系。请注意,f1
可以为某些参数值返回多行。
我已经尝试了以下语句,但它给了我这个错误消息:
ERROR: column "c4" specified more than once
CREATE VIEW v1 (c1, c2, c3, c4, c5)
AS SELECT * FROM
(SELECT c1, c2 FROM t1) AS x,
f1 (x.c1, x.c2);
我做错了什么?
以下是设置示例的前述陈述:
CREATE OR REPLACE FUNCTION f1 (a1 INTEGER, a2 INTEGER)
RETURNS TABLE (c1 VARCHAR(20), c2 VARCHAR(20), c3 INTEGER, c4 VARCHAR(20), c5 VARCHAR(128))
AS $$
SELECT 'a'::VARCHAR(20), 'b'::VARCHAR(20), 1::INTEGER, 'c'::VARCHAR(20), 'd'::VARCHAR(128);
$$ LANGUAGE SQL;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INTEGER, c2 INTEGER);
INSERT INTO t1 (c1, c2)
VALUES (2,3), (4,5);
DROP VIEW IF EXISTS v1;
答案 0 :(得分:1)
我建议在LATERAL
查询中加入SELECT
:
CREATE VIEW v1 AS
SELECT f.*
FROM t1
, f1 (t1.c1, t1.c2) AS f; -- implicit CROSS JOIN LATERAL
由于函数定义中定义的列名称已经匹配了您想要的列名称,因此您也可以从视图定义中删除列名称。
无论如何,创建视图都适用于早期绑定。意思是,只有在创建时选择的列才会包含在视图中。如果您稍后更改函数定义以返回其他列,则视图中包含 。 (如果删除或重命名列,则会破坏视图。)
你可以还在f1(..)
列表中包含设置返回函数SELECT
,几乎效果相同。差异:
SELECT
列表中的设置返回函数违反了SQL标准,并且有些人不赞同。也不能移植到其他一些RDBMS。由于Postgres在Postgres 9.3中引入了(标准SQL)LATERAL
,因此通常更可取。
SELECT
列表中的集合返回函数(实际上是相关子查询)相当于LEFT JOIN LATERAL ... ON true
,即保留t1
的所有行,即使函数不返回任何行。上面的CROSS JOIN LATERAL
删除了<{1}}不返回行的行。
你可以分解从f1()
函数返回的明确定义的行类型,但是可以对返回类型中的每一列重复计算该函数,而不是一次仅
相关和更多细节: