为什么SQL ANSI-92标准没有被ANSI-89更好地采用呢?

在我工作过的每个公司,我发现人们仍然在用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在他们testing的6个或8个RDBMS品牌中的“SQL Performance Tuning”,SQL-89与SQL-92风格的优化或性能没有什么不同。 人们可以假设大多数RDBMS引擎在优化或执行查询之前将语法转换为内部表示,因此人类可读的语法没有区别。

我也尝试传播SQL-92语法。 被批准16年后,人们开始使用它的时间到了! 现在,所有品牌的SQL数据库都支持它,所以没有理由继续使用可恶的(+) Oracle语法或*= Microsoft / Sybase语法。

至于为什么要打破开发者社区的SQL-89习惯是如此困难,我只能假设程序员有一个庞大的“金字塔底层”,他们使用书籍,杂志文章,或另一个代码库,这些人不抽象地学习新的语法。 有的人模式匹配,有的人死记硬背。

不过,我逐渐看到人们比以前更频繁地使用SQL-92语法。 自1994年以来,我一直在线回答SQL问题。

那么ANSI092标准包含了一些相当可恶的语法。 自然连接是一个,USING子句是另一个。 恕我直言,增加一个列的表不应该破坏代码,但一个NATURAL JOIN打破了最令人震惊的方式。 “最好的”破解方式是编译错误。 例如,如果您select某处,添加一列可能无法编译。 下一个最好的失败方法是运行时错误。 这更糟,因为你的用户可能会看到它,但它仍然给你一个很好的警告,你已经打破了一些东西。 如果您使用ANSI92并使用NATURAL连接编写查询,那么编译时不会中断,并且在运行时不会中断,查询将突然开始产生错误的结果。 这些types的bug是阴险的。 报告出错了,可能财务披露是不正确的。

对于那些不熟悉NATURAL连接的人。 他们在两个表中存在的每个列名称上连接两个表。 当你有一个4列的键,你很难打字。 问题出在Table1有一个名为DESCRIPTION的预先存在的列,并向Table2中添加一个新的列名,哦,我不知道,一些无害的,如mmm,DESCRIPTION,现在你join了VARCHAR2上的两个表(1000)字段是自由forms。

除了上面描述的问题之外,USING子句可能导致完全模糊。 在另一个SOpost中 ,有人展示了这个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 

这是完全模糊的。 我把公司和用户表中的用户ID列,并没有投诉。 如果公司中的UserID列是修改该行的最后一个人的ID,该怎么办?

我是认真的,任何人都可以解释为什么这样的歧义是必要的? 为什么它直接进入标准?

我认为Bill是正确的,因为有大量的开发人员通过编码复制/粘贴。 事实上,我承认,在ANSI-92方面,我是那种人。 我见过的每个例子都显示了多个连接嵌套在括号中。 诚实,这使得在sql中挑出表格困难。 但是一个SQL92的evangilist解释说实际上会强制一个连接命令。 耶稣…我见过的所有拷贝贴纸现在实际上是强制join订单 – 95%的时间更好的工作留给优化者, 尤其是复印/贴纸。

Tomalak说得对,

人们不会因为它在那里而转换到新的语法

它必须给我一些东西,我看不到一个好处。 如果有一个上涨的话,那么消极的信号就是一个不可忽视的信天翁。

有几个原因想到:

  • 人们出于习惯而做
  • 人们很懒,更喜欢“旧式”的join,因为他们的打字很less
  • 初学者经常会把自己的问题包装在SQL-92连接语法中
  • 人们不会因为它在那里而转换到新的语法
  • 人们并没有意识到新语法(如果你想这样称呼的话)的好处,主要是它使你能够做一个外部连接之前过滤一个表,而不是在你拥有的是WHERE子句之后。

就我而言,我将所有的连接都用SQL-92语法来完成,而且我可以在任何地方转换代码。 这是更干净,更可读和更强大的方式来做到这一点。 但是当他们认为在不改变查询结果的情况下使用更多的打字工作来伤害他们时,很难说服某人使用新的风格。

回应上面的NATURAL JOIN和USINGpost。

为什么你会看到使用这些的必要性 – 它们在ANSI-89中是不可用的,并且被添加为ANSI-92,因为我只能看到它作为一个快捷方式。

我永远不会离开一个偶然的机会,总是指定表/别名和ID。

对我来说,唯一的办法就是ANSI-92。 这是更详细的,ANSI-89追随者不喜欢的语法,但它整齐地将您的连接从您的过滤分离。

首先让我说,在SQL Server中,外部连接语法(* =)并不总是给出正确的结果。 有些时候,它认为这是一个交叉连接而不是一个外连接。 所以对,有一个很好的理由停止使用它。 而且这个外部连接语法是一个不推荐使用的特性,在SQL Server 2008之后的SQL Server的下一个版本中将不会出现。你仍然可以执行内部连接,但为什么人们会想要? 他们不清楚,更难以维持。 你不会轻易知道什么是连接的一部分,什么是真正的where子句。

我相信你不应该使用旧的语法的一个原因是理解联接,他们做什么和不做什么对于任何编写SQL代码的人来说都是关键的一步。 您不应该完全不了解连接写任何SQL代码。 如果你理解得很好,你可能会得出结论,ANSI-92语法更清晰,更容易维护。 我从来没有遇到过一个没有使用ANSI-92语法而优先于旧语法的SQL专家。

我遇到或处理过的大多数人使用旧的代码,在查询数据库时真的不理解连接,从而陷入困境。 这是我个人的经历,所以我不是说这总是对的。 但作为一名数据专家,多年来我不得不通过这些垃圾来解决这个问题。

我在学校学习ANSI-89并在工业上工作了几年。 然后我离开了DBMS的神话般的世界8年。 但后来我回来了,这个新的ANSI 92的东西被教导。 我已经学习了Join On语法,现在我实际上教SQL,并推荐新的JOIN ON语法。

但是我看到的缺点是相关的子查询对于ANSI 92的join似乎并没有什么意义。 当连接信息被包含在WHERE中时,相关的子查询在WHERE中“连接”似乎都是正确和一致的。 在ANSI 92表中,连接条件不在WHERE和子查询“join”中,语法看起来不一致。 另一方面,试图“解决”这种不一致可能会使情况变得更糟。

我不知道答案是肯定的..这是一场宗教战争(albiet比Mac-Pc或其他人less)

一个猜测是,直到最近,甲骨文,(也可能是其他供应商)没有采用ANSI-92标准(我认为这是在Oracle v9或其附近),因此,对于在公司工作的DBA / Db开发人员仍然在使用这些版本,(或想要在可能使用这些版本的服务器上移植的代码,他们必须坚持旧标准…

真的很遗憾,因为新的连接语法更具可读性,旧的语法在几个logging良好的情况下会产生错误的(错误的)结果。

  • 具体来说,外部连接时,在连接的“外部”一侧的表中的非连接相关列上有条件筛选谓词。

惯性和实用性。

ANSI-92 SQL就像触摸式input。 从某种理论的angular度来看,有一天它可能会使一切变得更好,但是现在我可以用四根手指更快地打字。 我必须倒退才能前进,不能保证会有回报。

编写SQL大约占我工作的10%。 如果我需要ANSI-92 SQL来解决ANSI-89 SQL无法解决的问题,那么我将使用它。 (事实上​​,我在Access中使用它)。如果一直使用它,将会帮助我更快地解决现有的问题,我会花时间来吸收它。 但是我可以在不考虑语法的情况下抽出ANSI-89 SQL。 我付钱解决问题 – 考虑SQL语法是浪费我的时间和我的雇主的钱。

有一天,年轻的Grasshopper,你会捍卫你对年轻人使用ANSI-92 SQL语法的抱怨,你应该使用SQL3(或其他)。 然后你会明白的 🙂

我有一个查询最初是为SQL Server 6.5编写的,它不支持SQL 92连接语法,即

 select foo.baz from foo left outer join bar on foo.a = bar.a 

被写成

 select foo.baz from foo, bar where foo.a *= bar.a 

查询已经存在了一段时间,相关的数据已经积累起来,使查询运行速度太慢,接近90秒完成。 到这个问题出现的时候,我们升级到了SQL Server 7。

在索引和其他复活节游戏之后,我将连接语法改为符合SQL 92。 查询时间下降到3秒。

有一个很好的理由切换。

转发从这里 。

我可以从普通开发人员的angular度回答,知道足够的SQL来理解这两种语法,但是每次我需要的时候仍然使用插入的确切语法… :-P(我不整天都在做SQL ,不时修正一些问题。)

其实,我发现第一种forms更直观,两张表之间没有明显的层次关系。 事实上,我学习SQL与可能旧书,显示第一种forms,可能不会帮助… 😉
我在Google的sql selectsearch中find的第一个参考(它主要回答法语答案)首先显示了旧的格式(然后解释第二个格式)。

只是在“为什么”的问题上提出一些提示……我应该在这个主题上阅读一本好的,现代的书(DB不可知论者)。 如果有人有build议…

我不能说所有的学校,但是在我的大学里,当我们在做我们课程的SQL模块时,他们没有在那个老的VAX系统上教ANSI-92,他们教ANSI-89。 直到我开始在Access中使用查询devise器构build一些查询,然后深入SQL代码,我才暴露给ANSI-92。 意识到我不知道它是如何完成连接,或者我开始深入挖掘语法的含义,所以我可以理解它。

鉴于现有的文件在许多情况下并不完全直观,而且人们倾向于坚持自己所知,在许多情况下,为了完成工作而不努力学习,容易明白为什么收养这么久。

当然,还有那些技术布道者喜欢修补和理解,往往是那些采用“更新”原则的types,并试图转换其余的types。

奇怪的是,在我看来,很多程序员退学并停止前进, 以为是因为这是他们所教的,这就是这样做的。 直到你脱盲为止,你才意识到学校只是为了教你基本的知识,给你足够的理解去学习其他的知识,而且你几乎不知道什么是知识的表面。 现在继续这个道路是你的工作。

当然,这只是我的经验。

1)写入OUTER JOIN的标准方法,而不是* =或(+)=

2)NATURAL JOIN

3)在数据库引擎上,ANSI-92趋势更为优化。

4)手动优化:

假设我们有下一个语法(ANSI-89):

 (1)select * from TABLE_OFFICES to,BIG_TABLE_USERS btu where to.iduser=tbu.iduser and to.idoffice=1 

它可以写成:

 (2)select * from TABLE_OFFICES to inner join BIG_TABLE_USERS btu on to.iduser=tbu.iduser where to.idoffice=1 

但也如:

 (3)select * from TABLE_OFFICES to inner join BIG_TABLE_USERS btu on to.iduser=tbu.iduser and to.idoffice=1 

它们都是(1),(2),(3)返回相同的结果,但是它们的优化方式不同,它依赖于数据库引擎,但大部分都是:

  • (1)它由数据库引擎决定优化。
  • (2)它join两个表,然后做每个办公室的filter。
  • (3)使用idoffice过滤BIG_TABLE_USERS,然后连接两个表。

5)更长的查询不那么凌乱。

Oracle并没有很好地实现ANSI-92。 我遇到了一些问题,尤其是因为Oracle应用程序中的数据表非常好地赋予列。 如果联接中的列数超过了1050列(这在Apps中很容易实现),那么您将得到这个虚假的错误,这绝对没有逻辑意义:

 ORA-01445: cannot select ROWID from a join view without a key-preserved table. 

重新编写查询以使用旧式连接语法会使问题消失,这似乎直接指向了ANSI-92连接的实施。

在我遇到这个问题之前,我是ASNI-92的一个坚定的推动者,因为它减less了偶然交叉连接的机会,这对于老式语法来说太容易了。

但是,现在我觉得要坚持下去要困难得多。 他们指出Oracle的糟糕实施,并说:“我们会这样做,谢谢。”

人们使用ANSI-89的理由来自于我的实践经验,与老年和年轻的程序员,学员和应届gradle生:

  • 他们从他们看到的现有代码(而不是书本)学习SQL,并从代码学习ANSI-89
  • ANSI-89是因为less打字
  • 他们不考虑这个问题,用一种或其他的方式,甚至不知道哪一个被认为是新的或旧的,也不关心
  • 代码也是与下一个维护代码的程序员的沟通的想法不存在。 他们认为他们与电脑交谈,电脑不在乎。
  • “干净的编码”的艺术是未知的
  • 编程语言和SQL的知识特别差,他们复制和粘贴到别处find的东西
  • 个人喜好

我个人更喜欢ANSI-92,并改变我在ANSI-89语法中看到的每一个查询,有时只是为了更好地理解手头的SQL语句。 但是我意识到,我所工作的大多数人没有足够的技巧来在许多桌子上写作连接。 他们尽可能地进行编码,并在第一次遇到SQL语句时使用他们记忆的内容。

Interesting Posts