【问题标题】:A CTE runs well in SQL Server but does not work in Oracle 11gCTE 在 SQL Server 中运行良好,但在 Oracle 11g 中无法运行
【发布时间】:2015-06-16 08:44:17
【问题描述】:

我正在Oracle 中学习CTE,并且我已经用CTE 编写了一条SQL 语句。我在SQL Server数据库中没有发现这条SQL有任何错误,但是在Oracle 11g数据库中总是导致错误;

CREATE TABLE EMP 
   (    EMPNO numeric(4,0), 
    ENAME VARCHAR(10 ), 
    JOB VARCHAR(9 ), 
    MGR numeric(4,0), 
    HIREDATE DATE, 
    SAL numeric(7,2), 
    COMM numeric(7,2), 
    DEPTNO numeric(2,0)
   )

Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7369,'SMITH','CLERK',7902,getdate(),800,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7499,'ALLEN','SALESMAN',7698,getdate(),1600,300,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7521,'WARD','SALESMAN',7698,getdate(),1250,500,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7566,'JONES','MANAGER',7839,getdate(),2975,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7654,'MARTIN','SALESMAN',7698,getdate(),1250,1400,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7698,'BLAKE','MANAGER',7839,getdate(),2850,null,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7782,'CLARK','MANAGER',7839,getdate(),2450,null,10);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7788,'SCOTT','ANALYST',7566,getdate(),3000,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7839,'KING','PRESIDENT',null,getdate(),5000,null,10);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7844,'TURNER','SALESMAN',7698,getdate(),1500,0,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7876,'ADAMS','CLERK',7788,getdate(),1100,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7900,'JAMES','CLERK',7698,getdate(),950,null,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7902,'FORD','ANALYST',7566,getdate(),3000,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7934,'MILLER','CLERK',7782,getdate(),1300,null,10);


select * from emp;


WITH SCOTT_EMP AS(
SELECT EMPNO,MGR,ENAME,0 T FROM EMP WHERE MGR IS NULL
UNION all
SELECT E.EMPNO,E.MGR,E.ENAME,M.T+1 FROM EMP E
INNER JOIN SCOTT_EMP M ON E.MGR=M.EMPNO
)
SELECT * FROM SCOTT_EMP;

【问题讨论】:

  • 能否显示您的错误信息
  • 我想我对错误有所了解。但是如果提供了错误消息,它应该会更容易。顺便说一句,请尝试将列规范添加到您的 with。 WITH SCOTT_EMP(EMPNO,MGR,ENAME, T) AS ...
  • 第一次查看并且没有更多信息:create table-statement 之后缺少分号...第二次查看:在 oracle 中它是 sysdatenot getdate()
  • @Ionic 是对的,此查询给出ORA-32039,在第一行添加(EMPNO,MGR,ENAME,T) 即可解决。
  • 那么我的猜测是正确的。只是为了将来的问题。我将在下面单独添加答案。

标签: sql-server oracle common-table-expression


【解决方案1】:

您需要在 CTE 表达式中指定列。在 SQL Server 中,这只是一个可选属性。在 11g 中,您需要定义它们。将您的代码更改为:

WITH SCOTT_EMP(EMPNO,MGR,ENAME,T) AS(
    SELECT EMPNO,MGR,ENAME,0 T FROM EMP WHERE MGR IS NULL
    UNION all
    SELECT E.EMPNO,E.MGR,E.ENAME,M.T+1 FROM EMP E
    INNER JOIN SCOTT_EMP M ON E.MGR=M.EMPNO
)
SELECT * FROM SCOTT_EMP;

【讨论】:

  • @lonic 你提供的方法我试过了,还是不行。
【解决方案2】:

在oracle中,可以使用start with connect by达到同样的效果,不需要使用嵌套查询

准备

CREATE TABLE EMP 
   (    EMPNO numeric(4,0), 
    ENAME VARCHAR(10 ), 
    JOB VARCHAR(9 ), 
    MGR numeric(4,0), 
    HIREDATE DATE, 
    SAL numeric(7,2), 
    COMM numeric(7,2), 
    DEPTNO numeric(2,0)
   );

Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7369,'SMITH','CLERK',7902,sysdate,800,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7499,'ALLEN','SALESMAN',7698,sysdate,1600,300,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7521,'WARD','SALESMAN',7698,sysdate,1250,500,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7566,'JONES','MANAGER',7839,sysdate,2975,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7654,'MARTIN','SALESMAN',7698,sysdate,1250,1400,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7698,'BLAKE','MANAGER',7839,sysdate,2850,null,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7782,'CLARK','MANAGER',7839,sysdate,2450,null,10);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7788,'SCOTT','ANALYST',7566,sysdate,3000,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7839,'KING','PRESIDENT',null,sysdate,5000,null,10);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7844,'TURNER','SALESMAN',7698,sysdate,1500,0,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7876,'ADAMS','CLERK',7788,sysdate,1100,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7900,'JAMES','CLERK',7698,sysdate,950,null,30);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7902,'FORD','ANALYST',7566,sysdate,3000,null,20);
Insert into EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7934,'MILLER','CLERK',7782,sysdate,1300,null,10);

查询:

select empno, mgr, ename, level - 1 as T
  from emp
  start with mgr is null
  connect by prior empno = mgr;

输出:

| EMPNO |    MGR |  ENAME | T |
|-------|--------|--------|---|
|  7839 | (null) |   KING | 0 |
|  7566 |   7839 |  JONES | 1 |
|  7788 |   7566 |  SCOTT | 2 |
|  7876 |   7788 |  ADAMS | 3 |
|  7902 |   7566 |   FORD | 2 |
|  7369 |   7902 |  SMITH | 3 |
|  7698 |   7839 |  BLAKE | 1 |
|  7499 |   7698 |  ALLEN | 2 |
|  7521 |   7698 |   WARD | 2 |
|  7654 |   7698 | MARTIN | 2 |
|  7844 |   7698 | TURNER | 2 |
|  7900 |   7698 |  JAMES | 2 |
|  7782 |   7839 |  CLARK | 1 |
|  7934 |   7782 | MILLER | 2 |

【讨论】:

  • 感谢您的回答。我知道这是正确的。但我现在了解 CTE。所以我需要知道我的 SQL 中发生了什么错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-04
  • 2019-12-22
  • 2017-12-07
  • 2020-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多