"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 类型中的每一列重复计算,而不是仅计算一次。
相关及更多详情:
这是 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 类型中的每一列重复计算,而不是仅计算一次。
相关及更多详情: