ORA-01731:遇到圆形视图定义

时间:2009-10-01 02:44:36

标签: sql oracle plsql

我们正从sql server端迁移到oracle。

在sqlserver上我们曾经有过如下的视图

create view blah
AS 
Select column1, 
       column2
 FROM  blah;

但在oracle上执行此操作会产生循环视图错误。

这是不允许在甲骨文那边?

4 个答案:

答案 0 :(得分:5)

您无法拥有视图引用。它在逻辑上没有意义。视图本质上是一个缓存查询,其结果显示为表。查询如何引用自身?

实际上,Oracle中不允许使用循环视图定义。如果您有循环视图定义,那么您的数据库代码中可能存在应该解决的错误。也许从SQL服务器到Oracle的转换是有缺陷的,并且意外地引入了这个循环定义?

答案 1 :(得分:2)

您实际上可以在ORACLE中执行此操作,但它更脆弱,因为您需要明确列出CTE的输出列。因此,如果更改表格,则需要手动更新CTE。

以下是我们的数据库中的一个示例,显示了如何计算记录的层次深度...

CREATE OR REPLACE VIEW deploy.PHARMACYDISPENSE_EX
AS 
   WITH SRC (
        PDID, WAREID, GCN_SEQNO, QTY, UOFM, XACTDTTM, CREATEDON, PROCESSEDON, 
        XACTTYPE, OPDID, CLOSEDON, BYPASSEDON, BYPASSEDBY, ITEMNO, LOTNO, 
        EXP_DATE, VOLUMETYPE, POTYPE, DEPTH
   ) AS (
        SELECT D.PDID, D.WAREID, D.GCN_SEQNO, D.QTY, D.UOFM, D.XACTDTTM, 
               D.CREATEDON, D.PROCESSEDON, D.XACTTYPE, D.OPDID, D.CLOSEDON, 
               D.BYPASSEDON, D.BYPASSEDBY, D.ITEMNO, D.LOTNO, D.EXP_DATE, 
               D.VOLUMETYPE, D.POTYPE, 0 FROM deploy.PHARMACYDISPENSE D 
        WHERE OPDID IS NULL
        UNION ALL
        SELECT D.PDID, D.WAREID, D.GCN_SEQNO, D.QTY, D.UOFM, D.XACTDTTM, 
               D.CREATEDON, D.PROCESSEDON, D.XACTTYPE, D.OPDID, D.CLOSEDON, 
               D.BYPASSEDON, D.BYPASSEDBY, D.ITEMNO, D.LOTNO, D.EXP_DATE, 
               D.VOLUMETYPE, D.POTYPE, (S.DEPTH + 1) 
        FROM deploy.PHARMACYDISPENSE D JOIN SRC S ON S.PDID = D.OPDID
)
SELECT PD.*
FROM SRC PD;

这里的重要部分是WITH SRC (<output column list>) AS ...。您需要输出列列表。所以它有可能,并且确实有效,它只需要比SQL Server中更多的代码。

答案 2 :(得分:0)

你的例子不完整 - 至少没有显示相关部分。:


-- create a table
CREATE TABLE Scrap
(fieldName  VARCHAR2(20));
-- create a view
CREATE VIEW ScrapVW1
AS
SELECT * FROM Scrap;
-- create a second view that uses the first view
CREATE VIEW ScrapVW2
AS
SELECT * FROM Scrap
UNION ALL
SELECT * FROM ScrapVW1;
-- recreate the first view that references the 2nd view which contains a reference to itself
CREATE OR REPLACE VIEW SCRAP_VW1
AS
SELECT * FROM ScrapVW2;

尝试重新创建ScrapVW1时出现循环引用错误。我猜你的转换中会发生一些无意的名称冲突。如果它非常复杂,我将摆脱'CREATE OR REPLACE VIEW'语法,只需使用CREATE VIEW,然后会给你'ORA-00955名称已经使用'错误。

答案 3 :(得分:0)

Oracle处理的分层问题显然不同于SQL。您可以使用clause

来连接,而不是使用自我参照视图
    SELECT employee_id, last_name, manager_id
   FROM employees
   CONNECT BY PRIOR employee_id = manager_id;