为什么Oracle没有抛出一个不明确的列引用"这里?

时间:2018-03-27 10:46:28

标签: sql oracle

我在这里有几个SQL查询 -

WITH emp AS
         (SELECT 1 AS empid, 'Adam' AS ename, 10 AS deptno, 'Broker' AS description FROM dual
          UNION ALL
          SELECT 2, 'Bob', 20, 'Accountant' FROM dual
          UNION ALL
          SELECT 3, 'Charles', 30, 'Programmer' FROM dual
          UNION ALL
          SELECT 4, 'Dan', 10, 'Manager' FROM dual
          UNION ALL
          SELECT 5, 'Eric', 10, 'Salesman' FROM dual
          UNION ALL
          SELECT 6, 'Franc', 20, 'Consultant' FROM dual),
     dept AS
         (SELECT 10 AS deptno, 'Accounts' AS dname, 100 employment_type_id FROM dual
          UNION ALL
          SELECT 20, 'Broking', 100 FROM dual
          UNION ALL
          SELECT 30, 'Corporate Relations', 200 FROM dual),
     employment_type AS
         (SELECT 100 AS employment_type_id, 'Permanent' AS description FROM dual
          UNION ALL
          SELECT 200, 'Contract' FROM dual)
/* --- Query 1
select e.ename, d.dname, e.description
  from emp e
       inner join dept d on e.deptno = d.deptno
       inner join employment_type e on d.employment_type_id = e.employment_type_id
-- */
-- /* Query 2
SELECT e.ename, d.dname, e.description
  FROM employment_type e
       INNER JOIN dept d ON e.employment_type_id = d.employment_type_id
       INNER JOIN emp e ON d.deptno = e.deptno
-- */
;

正如您在两个查询中看到的,表empemployment_type的别名是相同的,即e

当我通过说e.description选择列时,我不会收到类似

的错误
  

模糊列参考

莫尔沃尔,两个查询的结果是不同的!在第一个中,emp.description被选中,而在第二个中,employment_type.description被选中。

请让我知道为什么会发生这种情况,以及如何避免因此引起的混乱。

2 个答案:

答案 0 :(得分:1)

Oracle SQL从未完全符合任何ANSI / ISO SQL标准。 例如,它从未支持AS子句中的from

select *from dual AS d; -- fails

合规性的当前状态(Oracle {12 Oracle Compliance To Core SQL:2011) 表明ANSI SQL的各种功能主要部分支持,例如:

...
E031, Identifiers:
    Oracle supports this feature, with the following exceptions:
    ...

或,

E051, Basic query specification
    Oracle fully supports the following subfeatures:
    ...

虽然它没有说明含糊不清的别名(或范围变量正式),但您可以设想差异可以比页面中所述的更深入。

我目前知道在这种情况下无法使Oracle报告模糊,但仅仅注意使你的别名不同并不是我认为的那么难。

您可能想知道ANSI SQL Standard是否准确地说明不允许在同一范围内重复的别名。 它在第2部分的 7.6 部分中,SQL:Foundation 文档的SQL:2011标准。 (您可以从www.wiscorp.com下载草稿)。 具体来说,在语法规则,10)的小节中,它说(我把它剪了一下):

10) Let RV be a range variable that is exposed by TR. Let RV1 be a range variable that is exposed by a <table reference> TR1 that has the same scope clause as TR. 
   a) If RV is a <table name>, then
      i) If RV1 is a <table name>, then RV1 shall not be equivalent to RV.
      ii) Otherwise, RV1 shall not be equivalent to the <qualified identifier> of RV.
   b) Otherwise
      i) If RV1 is a <table name>, then the <qualified identifier> of RV1 shall not be equivalent to RV.
      ii) Otherwise, RV1 shall not be equivalent to RV.

这里RV是可变范围,您可以看到最后一个选择适用于两个别名的情况。

我们知道主要的SQL品牌实施此检查(SQL Server,MySQL,PostgreSQL),因此这些信息应该是准确的,尽管来自草案。

答案 1 :(得分:0)

您可以尝试以下查询来获得结果:

这适用于:获取emp表描述

/* --- Query 1

select e.ename, d.dname, e.description
  from emp e
       inner join dept d on e.deptno = d.deptno
       inner join employment_type et on d.employment_type_id = et.employment_type_id
-- */


-- /* Query 2
SELECT e.ename, d.dname, em.description
  FROM employment_type e
       INNER JOIN dept d ON e.employment_type_id = d.employment_type_id
       INNER JOIN emp em ON d.deptno = em.deptno
-- */

根据你的代码:

您首先使用别名查询&#39; e&#39;对于emp表(作为第一个表)。 所以它从你指定的第一个表中获得描述(emp表)。

与查询2相同: 它参考表就业类型(作为第一表) 所以它得到了描述。