为什么Oracle不在这里抛出"含糊不清的列引用"?

Rac*_*cha 5 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
-- */
;
Run Code Online (Sandbox Code Playgroud)

正如你可以在两个查询看到表的别名empemployment_type是相同的,即e.

当我选择一个列时,我e.description不应该得到类似的错误

模糊列参考

Morevoer,两个查询的结果是不同的!在第一个中,emp.description在第二个中employment_type.description被选中,被选中.

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

wol*_*ats 1

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

select *from dual AS d; -- fails
Run Code Online (Sandbox Code Playgroud)

目前的合规性状态( Oracle 12c 的Oracle Compliance To Core SQL:2011)表明 ANSI SQL 的各种功能大多得到部分支持,例如:

...
E031, Identifiers:
    Oracle supports this feature, with the following exceptions:
    ...
Run Code Online (Sandbox Code Playgroud)

或者,

E051, Basic query specification
    Oracle fully supports the following subfeatures:
    ...
Run Code Online (Sandbox Code Playgroud)

虽然它没有说任何关于不明确的别名(或正式的范围变量)的信息,但您可能会想到差异很容易比页面中所述的更深。

我目前不知道如何让 Oracle 在这种情况下报告歧义,但在我看来,只要注意使别名清晰并不难。

您可能想知道 ANSI SQL 标准是否明确规定同一范围内不允许使用重复的别名。在SQL:2011 标准的SQL/Foundation 文档第 2 部分第 7.6节中确实如此。(您可以从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.
Run Code Online (Sandbox Code Playgroud)

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

我们知道主要的 SQL 品牌都实施了这项检查(SQL Server、MySQL、PostgreSQL),因此尽管这些信息只是草稿,但它应该是准确的。