"ERROR: column ... specified more than once" in VIEW definition

"ERROR: column ... specified more than once" in VIEW definition

这是 的后续问题。我有一个存储函数 f1,它有两个参数 returns 一个 table,有 5 列;目前 returned 值是常量,稍后将根据参数计算它们。

我还有一个 table t1,其中有两列在类型上对应于 f1 的参数。

我现在想定义一个视图 v1,它包含从 f1 编辑的所有行 return 的并集,用于存储在 t1 中的所有参数对。对于给定的示例值,结果应为:

+---+---+---+---+---+---+---+
| 2 | 3 | a | b | 1 | c | d |
+---+---+---+---+---+---+---+
| 4 | 5 | a | b | 1 | c | d |
+---+---+---+---+---+---+---+

如果去掉前两列,也可以。请注意,对于某些参数值,f1 可以 return 多行。

我试过以下语句,但它给了我这个错误信息:

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;

我建议 LATERAL 加入 SELECT 查询:

CREATE VIEW v1 AS
SELECT f.*
FROM   t1
     , f1 (t1.c1, t1.c2) AS f;  -- implicit CROSS JOIN LATERAL

由于函数定义中定义的列名已经符合您的要求,您也可以从视图定义中删除列名。

无论如何,创建视图都适用于早期绑定。意思是,只有在创建时选择的列才会包含在视图中。如果您稍后将函数定义更改为 return 一个附加列,那么视图中将不包含 。 (如果删除或重命名列,则会破坏视图。)

可以 也可以在 SELECT 列表中包含 set-returning 函数 f1(..),几乎 效果一样。差异:

  • Set-returning SELECT 列表中的函数违反了 SQL 标准,并且被一些人反对。也不能移植到其他一些 RDBMS。由于 Postgres 在 Postgres 9.3 中引入了(标准 SQL)LATERAL,因此通常更可取。

  • SELECT 列表中的 set-returning 函数(实际上是相关子查询)等同于 LEFT JOIN LATERAL ... ON true,即它保留t1,即使函数没有 return 任何行。 CROSS JOIN LATERAL 像上面 删除 行,其中 f1() 没有 return 行。

  • 可以从函数SELECT (f1(...)).*, ...中分解明确定义的行类型return,但函数可能是对 return 类型中的每一列重复计算,而不是仅计算一次。

相关及更多详情: