11

免责声明:我是开发人员,而不是 DBA。

我一直是 Oracle 中 USING 子句的忠实拥护者,因为我不小心偶然发现了它,并用它代替了老式的 ON 子句来连接事实表和维度表。对我来说,它创建了一个更简洁的 SQL 并生成了一个更简洁的结果集,没有不必要的重复列。

但是,昨天一位同事要求我将我所有的 USING 子句转换为 ON。我会和他核实一下,问他的理由是什么。他与数据库的工作比我更密切,所以我认为他有一些充分的理由。

我没有收到他的回复(我们在不同的时区工作),但我想知道是否有关于使用“使用”条款的任何指导方针或最佳实践?我用谷歌搜索了很多,但没有找到任何确定的东西。事实上,我什至在任何地方都没有进行过好的辩论。

有人可以对此有所了解吗?或者提供一个关于该主题的良好讨论的链接?

谢谢!

4

3 回答 3

27

您可能已经意识到这种区别,但是从文档中

ON条件使用该ON子句指定连接条件。WHERE这样做可以让您指定与子句中的任何搜索或过滤条件分开的连接条件。

USING ( column )当您指定两个表中具有相同名称的列的等值连接时,该USING column子句指示要使用的列。仅当两个表中的连接列具有相同名称时,才能使用此子句。在此子句中,不要使用表名或表别名来限定列名。

所以这些是等价的:

select e.ename, d.dname
from emp e join dept d using (deptno);

select e.ename, d.dname
from emp e join dept d on d.deptno = e.deptno;

在很大程度上,您使用的是样式问题,但是(至少)有两种情况您不能使用using:(a)当两个表中的列名不同时,以及(b)当你想使用加入列:

select e.ename, d.dname, d.deptno
from emp e join dept d using(deptno);

select e.ename, d.dname, d.deptno
                         *
ERROR at line 1:
ORA-25154: column part of USING clause cannot have qualifier

您当然可以省略限定符 and select ..., deptno,只要您没有另一个表具有未使用它连接的同一列:

select e.ename, d.dname, deptno
from emp e join dept d using (deptno) join mytab m using (empno);

select e.ename, d.dname, deptno
                         *
ERROR at line 1:
ORA-00918: column ambiguously defined

在这种情况下,您只能选择合格的m.deptno. (好吧,这是相当做作的......)。

我可以看到避免的主要原因using只是一致性。由于您有时无法使用它,因此偶尔切换到on这些情况可能会有点刺耳。但同样,这更多的是关于风格,而不是任何深层的技术原因。

也许您的同事只是在强加(或建议)编码标准,但只有他们知道。如果您被要求更改您编写的一些正在审核的新代码或旧代码,也不是很清楚。如果是后者,那么无论他们偏爱的原因是什么on,我认为您需要获得单独的理由来修改经过验证的代码,因为即使重新测试修改后的代码也存在引入新问题的风险——除了成本之外/努力参与返工和重新测试。

不过,有几件事让我对你的问题感到震惊。首先,您将on语法描述为“老式”,但我认为这不公平 - 两者都是有效的和最新的(我认为从 SQL:2011 开始,但需要引用!)。和这个:

生成更简洁的结果集,没有不必要的重复列。

...我认为建议您使用select *,否则您只需选择其中一个值,尽管限定符有几个额外的字符。对于临时查询和某些子查询以外的任何内容,使用select *通常被认为是不好的做法(例如此处)。

于 2013-04-23T07:51:12.223 回答
2

相关问题

似乎主要区别在于语法:列在USING连接中合并。

在所有情况下,这意味着您无法从特定表访问连接列的值,实际上某些 SQL 将无法编译,例如:

SQL> WITH t AS (SELECT 1 a, 2 b, 3 c FROM dual),
  2       v AS (SELECT 1 a, 2 b, 3 c FROM dual)
  3  SELECT t.* FROM t JOIN v USING (a);

SELECT t.* FROM t JOIN v USING (a)
         ^    
ORA-25154: column part of USING clause cannot have qualifier

在外部联接中,这意味着您无法访问外部表值:

SQL> WITH t AS (SELECT 1 a, 2 b, 3 c FROM dual),
  2       v AS (SELECT NULL a, 2 b, 3 c FROM dual)
  3  SELECT * FROM t LEFT JOIN v USING (a)
  4   WHERE v.a IS NULL;

 WHERE v.a IS NULL
         ^
ORA-25154: column part of USING clause cannot have qualifier

USING这意味着此反连接语法与该子句没有等价物:

SQL> WITH t AS (SELECT 1 a, 2 b, 3 c FROM dual),
  2       v AS (SELECT NULL a, 2 b, 3 c FROM dual)
  3  SELECT * FROM t LEFT JOIN v ON v.a = t.a
  4   WHERE v.a IS NULL;

         A          B          C A          B          C
---------- ---------- ---------- - ---------- ----------
         1          2          3  

除此之外,一旦 SQL 有效,我不知道有任何区别。

但是,由于这种语法似乎不太常用,如果存在仅影响USING子句的特定错误,我不会感到惊讶,尤其是在引入 ANSI SQL 的早期版本中。我在 MOS 上没有找到任何可以证实这一点的东西,部分原因是USING这个词在错误描述中无处不在。

如果不使用此功能的原因是由于错误,那么在我看来,举证责任在于您的同事:必须引用/记录错误,以便在修复错误后最终解除禁令(数据库升级...)。

如果原因是装饰性的或编码约定的一部分,那么它肯定也必须记录在案。

于 2013-04-23T07:51:50.057 回答
0

使用 USING 你也不能像这样进行连接: select a.id,aval,bval,cval from a left join b on a.id = b.id left join c on c.id = b.id;

即,仅在与 B 表中的一行匹配时才给出 C 中的列。

于 2015-02-03T16:03:30.850 回答