这是我正在采取的课程问题的“解决方案”。但是当我将它复制到我的postgrSQL 9.5.1程序中时,它充满了错误。
CREATE RECURSIVE VIEW Ancestor AS
((SELECT parents.child AS Dec, parents.father AS Anc
FROM windsor.parents)
UNION
(SELECT parents.child AS Dec, parents.mother AS Anc
FROM windsor.parents)
UNION
(SELECT parents.Father AS Anc, Ancestor.Dec As Dec
FROM windsor.parents,Ancestor
WHERE parents.child = Ancestor.Anc)
UNION
(Select parents.mother AS Anc, Ancestor.Dec As Dec
FROM windsor.parents, Ancestor
WHERE parents.child = Ancestor.Anc))
它在行中引发错误:1,带有'AS'的语法错误。在查看了一些声明here并尝试了一些内容后,似乎将其更改为
CREATE RECURSIVE VIEW Ancestor(Anc,Dec) AS
工作,但现在它在第一次尝试在FROM
命令中调用Ancestor时抛出错误。这次的错误是:
Error: rekursiver Verweis auf Anfrage „ancestor“ darf nicht in ihrem nicht-rekursiven Teilausdruck erscheinen
SQL Status:42P19
或用我破碎的英语:
recursive call for "ancestor" mustn't be in a non-recursive part
像我说的那样,这不是我的代码。这是我参加的课程问题的“解决方案”。我正在尝试解决这个问题,但是不要因为这段代码而偏离原来的意图。
欢呼 - 雅各布斯
答案 0 :(得分:1)
错误是由于在您的视图定义中,您有两个不同的递归子句,而只有一个被允许。
在PostgreSQL manual中,递归视图定义如下:
CREATE RECURSIVE VIEW name (columns) AS SELECT ...;
相当于
CREATE VIEW name AS WITH RECURSIVE name (columns) AS (SELECT ...) SELECT columns FROM name;
必须为递归视图指定视图列列表。
(请注意您使用CREATE RECURSIVE VIEW Ancestor(Anc,Dec)
的最后一句 require )
然后,在page关于WITH RECURSIVE
:
如果指定了RECURSIVE,则它允许SELECT子查询按名称引用自身。这样的子查询必须具有
形式
non_recursive_term UNION [ ALL | DISTINCT ] recursive_term
其中递归自引用必须出现在UNION的右侧。 每个查询只允许一次递归自引用。(重点是我的)。
因此,您应该仅使用递归子选择来更改查询。
修改的
以下是一个可能的解决方案,@ JacobusConradi在下面的评论中对该查询进行了少量修改:
CREATE RECURSIVE VIEW ancestor(anc, dec) AS
SELECT father AS anc, child AS dec
FROM windsor.parents
WHERE father is not null
UNION
SELECT mother AS anc, child AS dec
FROM windsor.parents
WHERE mother is not null
UNION
SELECT anc, child AS dec
FROM windsor.parents, ancestor
WHERE dec = father OR dec = mother
修改涉及:1)消除DISTINCT(我们可以假设child
是原始表的主键,并且在任何情况下使用UNION
运算符都会自动消除重复项) ,2)添加空值测试,否则在结果中将显示具有anc
或dec
空值的元组。
答案 1 :(得分:0)
正如Renzo指出的那样,你有两个问题需要解决:
UNION
通过将UNION
的最后两个元素组合到子查询中,可以轻松解决第二个限制;而不是A UNION B UNION C UNION D
,只需说A UNION B UNION (C UNION D)
。
至于将递归调用分解为单个引用,这对于common table expression (CTE)非常简单,给你这样的东西:
CREATE RECURSIVE VIEW Ancestor(Anc,Dec) AS
SELECT parents.child AS Dec, parents.father AS Anc
FROM windsor.parents
UNION
SELECT parents.child AS Dec, parents.mother AS Anc
FROM windsor.parents
UNION
(
WITH cte AS (SELECT * FROM Ancestor)
SELECT parents.Father AS Anc, cte.Dec As Dec
FROM windsor.parents, cte
WHERE parents.child = cte.Anc
UNION
SELECT parents.Mother AS Anc, cte.Dec As Dec
FROM windsor.parents, cte
WHERE parents.child = cte.Anc
)