在我所工作的每家公司,我发现人们仍然在ANSI-89标准中编写SQL查询:
select a.id, b.id, b.address_1 from person a, address b where a.id = b.id
而不是ANSI-92标准:
select a.id, b.id, b.address_1 from person a inner join address b on a.id = b.id
对于这样一个非常简单的查询,可读性没有太大差异,但是对于大型查询,我发现将我的连接条件分组并列出表格可以更容易地查看我在连接中可能存在问题的位置,以及让我在WHERE子句中保留所有过滤功能.更不用说我觉得外连接比Oracle中的(+)语法更直观.
当我尝试向人们传播ANSI-92时,使用ANSI-92而不是ANSI-89有什么具体的性能优势吗?我会自己尝试,但是我们这里的Oracle设置不允许我们使用EXPLAIN PLAN - 不希望人们尝试优化他们的代码,是吗?
根据Peter Gulutzan和Trudy Pelzer的"SQL性能调优",在他们测试的六个或八个RDBMS品牌中,SQL-89与SQL-92样式连接的优化或性能没有区别.可以假设大多数RDBMS引擎在优化或执行查询之前将语法转换为内部表示,因此人类可读的语法没有区别.
我也尝试传播SQL-92语法.它获得批准后十六年,人们开始使用它的时间已经过去了!所有SQL数据库品牌现在都支持它,因此没有理由继续使用可恶的(+)
Oracle语法或*=
Microsoft/Sybase语法.
至于为什么很难打破SQL-89习惯的开发者社区,我只能假设程序员有一个庞大的"金字塔基础",他们通过复制和粘贴进行编码,使用书籍,杂志文章中的古老例子,或另一个代码库,这些人不抽象地学习新语法.有些人模式匹配,有些人通过死记硬背来学习.
不过,我逐渐看到人们比以前更频繁地使用SQL-92语法.自1994年以来,我一直在线回答SQL问题.
那么ANSI092标准包含一些非常令人发指的语法.自然连接是一个,USING子句是另一个.恕我直言,在表中添加一列不应该破坏代码,但是NATURAL JOIN会以最令人震惊的方式中断.打破"最好"的方法是编译错误.例如,如果你SELECT*的地方,增加了一个列的可能无法编译.失败的下一个最佳方法是运行时错误.它更糟糕,因为你的用户可能会看到它,但它仍然会给你一个很好的警告,你已经破坏了一些东西.如果您使用ANSI92并使用NATURAL连接编写查询,它将不会在编译时中断,并且它不会在运行时中断,查询将突然开始产生错误的结果.这些类型的错误是阴险的.报告出错,可能是财务披露不正确.
对于那些不熟悉NATURAL连接的人.它们在两个表中存在的每个列名上连接两个表.当你有一个4列密钥并且你厌倦了键入它时,这真的很酷.当Table1有一个名为DESCRIPTION的预先存在的列并且你向Table2添加一个名为的新列时,问题就出现了,哦,我不知道,像mmm这样无害的描述,现在你要加入VARCHAR2上的两个表了(1000)自由形式的领域.
除了上述问题之外,USING子句还可能导致完全模糊.在另一篇SO帖子中,有人展示了这个ANSI-92 SQL并请求帮助阅读它.
SELECT c.* FROM companies AS c JOIN users AS u USING(companyid) JOIN jobs AS j USING(userid) JOIN useraccounts AS us USING(userid) WHERE j.jobid = 123
这完全是模棱两可的.我在公司和用户表中都放了一个UserID列,没有任何抱怨.如果公司中的UserID列是最后一个修改该行的人的ID,该怎么办?
我很认真,有人可以解释为什么这种歧义是必要的吗?为什么它直接进入标准?
我认为比尔是正确的,有大量的开发人员通过编码复制/粘贴.事实上,我可以承认,就ANSI-92而言,我是一个人.我见过的每个例子都显示多个连接嵌套在括号中.诚实,这使得在sql中挑选表格充其量是困难的.但后来SQL92 evangilist解释说实际上会强制连接顺序.耶稣...我见过的所有那些复制粘贴现在实际上都在强制加入订单 - 这项工作95%的时间最好留给优化者,特别是复制/贴纸.
托马拉克说得对,
人们不会因为它在那里而改用新语法
它必须给我一些东西,我没有看到好处.如果有上行空间,那么负面影响就是信天翁太大而不容忽视.
有几个原因浮现在脑海中:
人们是出于习惯而做的
人们很懒,喜欢"旧式"加入,因为他们涉及的打字较少
初学者经常会遇到围绕SQL-92连接语法的问题
人们不会因为它在那里而改用新语法
人们不知道新的(如果你想称之为)语法的好处,主要是它使你能够在进行外连接之前过滤一个表,而不是在你拥有它之后是WHERE子句.
就我而言,我使用SQL-92语法完成所有连接,并且尽可能地转换代码.它是更清晰,更易读和更强大的方式.但是当他们认为在不改变查询结果的情况下更多打字工作会伤害他们时,很难说服某人使用新风格.
回应上面的NATURAL JOIN和USING帖子.
为什么你会看到需要使用这些 - 它们在ANSI-89中不可用,并且被添加为ANSI-92,因为我只能看到它作为捷径.
我绝不会将联接留给机会,并且总是指定表/别名和id.
对我来说,唯一的出路就是ANSI-92.它更加冗长,ANSI-89粉丝不喜欢它的语法,但它巧妙地将你的JOINS与过滤分开.
首先让我说在SQL Server中,外连接语法(*=)不会始终给出正确的结果.有时它将其解释为交叉连接而不是外连接.所以,有充分的理由停止使用它.并且外部联接语法是一个不推荐使用的功能,并且不会在SQL Server 2008之后的SQL Server的下一个版本中.您仍然可以执行内部联接,但为什么地球上有人想要?它们不清楚,难以维护.你不容易知道什么是连接的一部分,什么才是真正的where子句.
我认为你不应该使用旧语法的一个原因是理解连接以及它们做什么和不做什么对于任何编写SQL代码的人来说都是关键的一步.如果不彻底了解联接,则不应编写任何SQL代码.如果您理解它们,您可能会得出结论,ANSI-92语法更清晰,更易于维护.我从来没有遇到过一个SQL专家,他没有使用ANSI-92语法而不喜欢旧语法.
我遇到或处理过的使用旧代码的大多数人,在查询数据库时真的不理解联接,从而遇到麻烦.这是我个人的经历,所以我并不是说它总是如此.但作为一名数据专家,多年来我不得不解决这些垃圾过多的问题.