为什么不爱SQL?

时间:2009-10-29 12:27:12

标签: sql frameworks

我最近听说过SQL是一种糟糕的语言,似乎太阳下的每个框架都预先打包了一个数据库抽象层。

根据我的经验,SQL通常是管理数据输入和输出的更简单,更通用,更方便程序的方式。我使用的每个抽象层似乎都是一种显着有限的方法,没有真正的好处。

是什么让SQL如此糟糕,为什么数据库抽象层有价值?

29 个答案:

答案 0 :(得分:122)

这部分是主观的。所以这是我的观点:

SQL具有伪自然语言风格。发明人认为他们可以像英语一样创建语言,并且数据库查询将非常简单。一个可怕的错误。除了琐碎的情况外,SQL很难理解。

SQL是声明性的。您不能告诉数据库 它应该做什么,只是你想要的结果。如果您不必关心性能,这将是完美且非常强大的。所以你最终写了SQL - 阅读执行计划 - 改写SQL试图影响执行计划,你想知道为什么你不能自己编写执行计划

声明性语言的另一个问题是某些问题更容易以命令式方式解决。因此,您要么使用其他语言编写(您需要标准SQL,可能需要数据访问层),要么使用特定于供应商的语言扩展,例如编写存储过程等。这样做你可能会发现你正在使用你见过的最糟糕的语言之一 - 因为它从未被设计成用作命令式语言。

SQL 很旧。 SQL已经标准化,但为时已晚,许多供应商已经开发了语言扩展。所以SQL最终出现在几十种方言中。这就是为什么应用程序不可移植以及拥有DB抽象层的一个原因。

但这是真的 - 没有可行的替代方案。所以我们都将在未来几年内使用SQL。

答案 1 :(得分:58)

除了所说的所有内容之外,技术并不一定要使抽象层变得有价值

如果你正在做一个非常简单的脚本或应用程序,你可以在任何你喜欢的代码中混合使用SQL调用。但是,如果您正在执行复杂的系统,则在单独的模块中隔离数据库调用是一种很好的做法,因此它会隔离您的SQL代码。它提高了代码的可读性,可维护性和可测试性。它允许您快速调整系统以适应数据库模型的变化,而不会破坏所有高级别的东西等。

SQL很棒。它上面的抽象层使它更大!

答案 2 :(得分:53)

抽象层的一个方面是,SQL实现往往或多或少彼此不兼容,因为标准略有模糊,而且因为大多数供应商都在那里添加了自己的(非标准)附加组件。也就是说,为MySQL数据库编写的SQL可能与Oracle数据库的工作方式不太相似 - 即使它“应该”。

但是,我同意SQL比大多数抽象层更好。这不是SQL的错,它被用于它不是为它设计的东西。

答案 3 :(得分:36)

SQL从几个来源变得糟糕:

  • 对命令语言不感兴趣的程序员。
  • 必须每天处理许多不兼容的基于SQL的产品的顾问
  • 非关系数据库供应商试图打破市场上关系数据库供应商的束缚
  • 像Chris Date这样的关系数据库专家将SQL的当前实现视为不足

如果你坚持使用一个DBMS产品,那么我绝对同意SQL DB比竞争对手更通用,质量更高,至少在你达到模型内在的可扩展性障碍之前。但是你真的想写下一个Twitter,还是只是想让一些会计数据保持整齐有序?

对SQL的批评通常是批评RDBMS的标志。 RDBMSes似乎不理解的是,他们很好地解决了一大类计算问题,并且他们在这里使我们的生活更轻松,而不是更难。

如果他们认真批评SQL本身,他们就会像Tutorial D和Dataphor那样支持。

答案 4 :(得分:22)

这并不是那么可怕。当一种新的“范式”出现时,这个行业的一个不幸的趋势是废弃以前可靠的技术。在一天结束时,这些框架很可能使用SQL与数据库进行通信,那么它怎么会这么糟糕呢?也就是说,拥有“标准”抽象层意味着开发人员可以专注于应用程序代码而不是SQL代码。如果没有这样一个标准层,每次开发系统时都可能会编写一个轻量级的层,这样做会浪费精力。

答案 5 :(得分:16)

SQL用于管理和查询基于SET的数据。它经常被用来做更多的事情,边缘案件有时会导致沮丧。

SQL的实际使用可能受基础数据库设计的影响,SQL可能不是问题,但设计可能 - 当您丢弃与错误设计相关的遗留代码时,更改会更加隐蔽且成本更高恭维(没有人愿意回去“修复”那些“有效”并达到目标的东西)

木匠可以用锤子敲打钉子,用锯子锯木材,用平面锯光滑的木板。可以使用锤子和飞机“锯”,但是它很令人沮丧。

答案 6 :(得分:11)

我不会说这太可怕了。它不适合某些任务。例如:你不能用SQL编写好的过程代码。我曾被迫使用SQL进行集合操作。我整整一个周末都想到了这一点。

SQL是为关系代数设计的 - 这就是它应该被使用的地方。

答案 7 :(得分:9)

  

我最近听说过SQL是一种糟糕的语言,似乎太阳下的每个框架都预装了数据库抽象层。

请注意,这些图层只是将自己的内容转换为SQL。对于大多数数据库供应商而言SQL是与引擎通信的唯一方式。

  

根据我的经验,SQL通常是管理数据输入和输出的更简单,更通用,更方便程序的方式。我使用的每个抽象层似乎都是一种显着有限的方法,没有真正的好处。

......我刚才描述的原因。

数据库图层不会添加任何内容,只是限制你。他们使查询更加简单,但从未提高效率。

根据定义,数据库层中没有任何内容不在SQL

  

是什么让SQL如此可怕,为什么数据库抽象层有价值?

SQL是一种很好的语言,然而,使用它需要一些大脑扭曲。

理论上,SQL是声明性的,即您声明要获得的内容,引擎以最快的方式提供它。

实际上,有很多方法可以制定正确的查询(即返回正确结果的查询)。

优化器能够使用一些预定义的算法构建乐高城堡(是的,它们是多个),但它们无法制作新的算法。它仍然需要SQL开发人员来帮助他们。

但是,有些人希望优化器能够生成“可能的最佳计划”,而不是“在给定SQL引擎实现的情况下,此查询可用的最佳计划”。

众所周知,当计算机程序无法满足人们的期望时,会受到指责,而不是期望。

然而,在大多数情况下,重新制定查询可以确实产生最佳计划。有些任务是不可能的,但SQL这些案例的新增和不断增长的数量越来越少。

但是,如果供应商提供对“获取索引范围”,“rowid”等行等的函数的低级访问权,那将会很不错,例如{{1}编译器允许您将程序集嵌入到语言中。

我最近在我的博客上写了一篇关于此的文章:

答案 8 :(得分:7)

我是一个巨大的ORM倡导者,我仍然相信SQL非常有用,尽管它可以用它来做可怕的事情(就像其他事情一样)。

我认为SQL是一种超级高效的语言,没有代码重用或可维护性/重构作为优先级。

因此,闪电般快速处理是首要任务。这是可以接受的。你必须要注意权衡,这对我来说是相当可观的。

从美学的角度来看,作为一种语言,我觉得它缺少一些东西,因为它没有OO概念等等 - 这对我来说感觉就像是非常古老的学校程序代码。但它是做某些事情的最快方式,而且这是一个强大的利基!

答案 9 :(得分:7)

我想说框架中包含的数据库抽象层是一件好事,因为它解决了两个非常重要的问题:

  1. 它使代码保持不同。通过将SQL放入另一层,这通常非常薄,应该只进行查询和结果切换的基础知识(以标准化方式) ),让您的应用程序免于SQL的混乱。这与Web开发人员(应该)将CSS和Javascript放在单独的文件中的原因相同。如果可以避免,不要混合语言

  2. 许多程序员都很擅长使用SQL。无论出于何种原因,大量开发人员(尤其是Web开发人员)在使用SQL或RDBMSes方面似乎非常非常糟糕一般来说。他们将数据库(和扩展的SQL)视为他们必须经历的肮脏的中间人来获取数据。这导致了极其糟糕的数据库,没有索引,表格以可疑的方式堆叠在表格之上,以及写得非常糟糕的查询。或者更糟糕的是,他们试图过于笼统(专家系统,任何人?),并且无法以任何有意义的方式合理地关联数据。

  3. 不幸的是,有时某人试图解决他们使用的问题和工具的方式,无论是由于无知,固执还是其他特征,都是彼此直接对立,并且好运试图说服他们这样做。因此,除了仅仅是一个好的做法之外,我认为数据库抽象层是一种安全网,因为它不仅使SQL不受开发人员的影响,而且使得他们的代码更容易重构,因为所有查询都在一个地方。

答案 10 :(得分:6)

SQL非常适合某些类型的任务,尤其是操作和检索数据。

但是,SQL缺少(或仅部分实现)几个用于管理变更和复杂性的重要工具:

  • 封装:SQL的封装机制很粗糙。编写SQL代码时,您必须了解有关数据实现的所有信息。这限制了您可以实现的抽象的数量。

  • 多态性:如果要对不同的表执行相同的操作,则必须编写两次代码。 (人们可以通过富有想象力地使用观点来缓解这种情况。)

  • 可见性控制:没有标准的SQL机制可以将代码段彼此隐藏或将它们分组为逻辑单元,因此每个表,过程等都是 即使是不受欢迎的,也可以从其他所有人那里获得。

  • 模块化版本控制

最后,在SQL中手动编写CRUD操作(并编写代码以将其连接到其他应用程序的其余部分)是重复且容易出错的。

现代抽象层提供了所有这些功能,并允许我们在隐藏破坏性重复实现细节的同时使用最有效的SQL。它提供了帮助克服the object-relational impedance mismatch的工具,使面向对象软件开发中的数据访问变得复杂。

答案 11 :(得分:5)

IMO,我看到人们对SQL的问题与关系设计和SQL语言本身无关。它与数据层建模的学科有关,这在很多方面与建模业务层或接口根本不同。与使用数据库的多个应用程序的数据层相比,表示层建模中的错误通常更容易纠正。这些问题与在SOA设计中建模服务层时遇到的问题相同,您必须考虑服务的当前使用者以及输入和输出合同。

SQL旨在与关系数据库模型进行交互。还有其他数据模型已经存在了一段时间,但无论使用何种理论模型,都存在正确设计数据层的规则,因此,开发人员通常对SQL的困难通常与强制非关系的尝试有关。数据模型到关系数据库产品上。

答案 12 :(得分:5)

SQL基于集合论,而大多数高级语言最近都是面向对象的。对象程序员通常喜欢在对象中思考,并且必须进行心理转换以使用基于Set的工具来存储他们的对象。一般来说,对于OO程序员来说,只需在自己选择的语言中剪切代码并在应用程序代码中执行类似object.save或object.delete的操作,而不必编写sql查询并调用数据库来实现同样的结果。

当然,有时候对于复杂的东西,SQL更容易使用,效率也更高,因此掌握这两种技术是件好事。

答案 13 :(得分:4)

首先,它们使得参数化查询变得微不足道,保护您免受SQL注入攻击。从这个角度来看,使用原始SQL风险更大,也就是说,从安全角度来看更容易出错。他们还经常在您的数据库中提供面向对象的视角,使您无需进行此翻译。

答案 14 :(得分:4)

最近听到了很多?我希望你不要把它与NoSql运动混淆。据我所知,主要是一群人使用NoSql进行高可扩展性的Web应用程序,并且似乎忘记了SQL是非“高可扩展性Web应用程序”场景中的有效工具。

抽象层业务只是要整理面向对象代码和基于表格的代码之间的区别,例如SQL喜欢谈论。通常这会导致在两者之间写下大量的锅炉板和无聊的转换代码。 ORM自动执行此操作,从而为业务对象人员节省时间。

答案 15 :(得分:4)

对于有经验的SQL程序员来说,坏的方面是

  • 冗长
  • 正如许多人所说,SQL是声明性的,这意味着优化不是直接的。就像赛道比赛一样,它就像拉力赛一样。
  • 试图解决所有可能的方言并且不支持任何方言的快捷方式的框架
  • 没有简单的版本控制。

对于其他人,原因是

  • 一些程序员对SQL不好。可能是因为SQL使用集合操作,而编程语言在对象或功能范例中工作。集合思考(联合,产品,交叉)是一个人们没有的习惯问题。
  • 有些操作并不是不言自明的:即,首先不清楚 过滤不同的设置。
  • 方言太多了

SQL框架的主要目标是减少您的输入。他们以某种方式做,但往往只是为了非常简单的查询。如果你尝试做一些复杂的事情,你必须使用字符串并输入很多东西。尝试处理一切可能的框架,比如SQL Alchemy,变得太大了,就像另一种编程语言一样。

[26.06.10更新]最近我与Django ORM module合作。这是我见过的唯一有价值的SQL框架。而且这个让很多人都在忙着做事。复杂的聚合虽然有点困难。

答案 16 :(得分:3)

SQL是一种非常好的数据操作语言。从开发人员的角度来看,我不喜欢的是改变数据库不会在编译时破坏你的代码......所以我使用抽象来增加这个功能,代价是性能和SQL语言的表达能力,因为在大多数应用程序中,您不需要SQL拥有的所有东西。

SQL受到憎恨的另一个原因是关系数据库。

CAP定理变得流行:

  

你想要什么目标?   共享数据系统?

     
      
  • 强大的一致性:所有客户都会看到相同的视图,即使存在   更新
  •   
  • 高可用性:所有客户端都可以找到一些数据副本,即使在   存在失败
  •   
  • 分区容差:系统属性即使在系统中也能保留   分区
  •   
     

该定理表明你可以随时   只有三个CAP中的两个   属性同时

关系数据库地址强一致性和分区容差。

因此越来越多的人意识到关系数据库不是银弹,并且越来越多的人开始拒绝支持高可用性,因为高可用性使得水平扩展更容易。水平缩放因为我们已达到limit of Moore law而受欢迎,因此缩放的最佳方法是添加更多机器。

如果关系数据库被拒绝,SQL也会被拒绝。

答案 17 :(得分:3)

•每个供应商都扩展了SQL语法以满足他们的需求。因此,除非你做的事情相当简单,否则你的SQL代码是不可移植的。

•SQL的语法不是正交的;例如,select, insert, update,delete语句都具有完全不同的语法结构。

答案 18 :(得分:3)

SQL并不是一种可怕的语言,有时它与其他人的表现不太好。

例如,如果您的系统想要将所有实体表示为某种OO语言或其他OO语言中的对象,那么将其与SQL结合而不使用任何类型的抽象层可能会变得相当麻烦。将复杂的SQL查询映射到OO世界并不容易。为了缓解这些世界之间的紧张关系,插入了额外的抽象层(例如,OR-Mapper)。

答案 19 :(得分:3)

SQL有许多缺陷,正如其他一些海报所指出的那样。尽管如此,我更喜欢在人们提供的许多工具上使用SQL作为替代方案,因为“简化”通常比它们应该简化的事情更复杂。

我的理论是,SQL是由一群象牙塔蓝色滑雪者发明的。整个非程序性结构。听起来很棒:告诉我你想要什么,而不是你想怎么做。但在实践中,通常更容易实现这些步骤。通常这似乎是试图通过描述汽车在完成后应该如何执行来提供汽车维修说明。是的,你可以说,“我希望这辆车能够再次达到每加仑30英里的速度,然后用这样的嗡嗡声来运行...嗯...等等”但是对每个人来说都不会更容易只是说,“更换火花塞”?即使您确定如何以非过程术语表达复杂查询,数据库引擎通常会提出一个非常低效的执行计划来实现。我认为通过添加标准化方法来告诉它首先读取哪个表以及使用什么索引,SQL会得到很大改善。

处理空值会让我发疯!是的,从理论上讲,当有人说“嘿,如果null表示未知,那么在已知值中添加未知值应该给出一个未知值时,它一定听起来很棒。毕竟,根据定义,我们不知道未知值是什么“。从理论上讲,绝对正确。在实践中,如果我们有10,000个客户并且我们确切地知道9,999欠我们多少​​钱,但是对于最后一个欠款有一些疑问,管理层说,“我们的应收账款总额是多少?”,是的,数学上正确的答案是“我不知道”。但实际答案是“我们计算的是4,327,287.42美元,但有一个帐户存在问题,因此这个数字并不准确”。我敢肯定,如果不是一定数量,管理层会更愿意接近,而不是空洞的凝视。但是SQL坚持这种数学上原始的方法,所以你做的每一个操作,你都需要添加额外的代码来检查空值并处理它们。

所有这一切,我仍然宁愿使用SQL而不是基于SQL构建的一些层,这只是创建了我需要学习的另一整套内容,然后我必须知道最终这将被转换为SQL ,有时我可以信任它正确有效地进行翻译,但是当事情变得复杂时我不能,所以现在我必须知道额外的层,我仍然需要知道SQL,我必须知道它是如何的要转换为我可以欺骗该层欺骗SQL做正确的事情。 Arggh。

答案 20 :(得分:2)

不喜欢SQL,因为SQL在语法,语义和当前使用方面都很糟糕。我会解释一下:

  • 它的语法是一个cobol弹片,所有cobol批评都适用于此(在较小程度上,公平)。试图成为自然语言,而不是实际上试图解释自然语言创建arbirtrary语法(是DROP TABLE或DROP,UPDATE TABLE,UPDATE或UPDATE IN,DELETE或DELETE FROM ...)和语法怪物如SELECT(多少页面做它填补?)
  • 语义也有很大的缺陷,Date非常详细地解释了它,但是只需要注意三值布尔逻辑并不适合关系代数,其中一行只能是或不是表的一部分< / LI>
  • 使用编程语言作为数据库的主要(通常是唯一的)接口被证明是一个非常糟糕的选择并且它创建了一个新的安全漏洞类别

答案 21 :(得分:2)

如果你没有太多使用SQL,我认为主要问题是缺乏优秀的开发人员工具。

如果您对SQL有很多经验,那么您可能会因为缺乏对执行计划的控制而感到沮丧。这是向供应商指定SQL的方式中的固有问题。我认为SQL需要成为一种更强大的语言来真正利用底层技术(这是非常强大的)。

答案 22 :(得分:2)

快速,给我写SQL来分页一个在MySQL,Oracle,MSSQL,PostgreSQL和DB2中工作的数据集。

哦,对,标准SQL没有定义任何运算符来限制返回的结果数以及从哪一行开始。

答案 23 :(得分:2)

与纯SQL一起生活真的可以成为一个维护地狱。对我来说,ORM的最大优势是能够安全地重构代码而无需繁琐的“数据库重构”过程。有很好的单元测试框架和OO语言的重构工具,但我还是要看看Resharper的SQL对应物。例如。

仍有所有DAL在幕后都有SQL,你仍然需要了解它才能理解你的数据库发生了什么,但每天使用好的抽象层变得更容易。

答案 24 :(得分:2)

我同意你的观点,但回答你的问题,使得SQL如此“糟糕”的一件事是数据库供应商(Sql Server,Oracle等)之间缺乏T-SQL的完全标准化,这使得SQL代码不太可能是完全便携的。数据库抽象层解决了这个问题,虽然性能成本很高(有时非常严重)。

答案 25 :(得分:1)

我同意这里的大多数帖子,关于SQL效用的辩论主要是主观的,但我认为这对你的业务需求更具主观性。

Stefan Steinegger指出,声明性语言很适合指定你想要的东西,而不是你想要的。这意味着从高级角度来看,您的各种SQL实现都是不错的:也就是说,如果您只想获取一些数据并且没有其他任何事情,那么您可以通过编写相对简单的查询并选择SQL的实现来满足自己这适合你。

如果你的工作水平较低,你需要自己优化所有这些,那就远非理想。使用另一层抽象可能会有所帮助,但如果您真正想要做的是指定优化查询的方法等等,那么在尝试优化时添加中间人会有点直觉。

我对SQL的最大问题就像其他“标准化”语言一样,实际标准很少。我几乎不愿意在Sybase和MySQL之间学习一种全新的语言,这样我就不会混淆这两种惯例。

答案 26 :(得分:0)

我不喜欢SQL,但我也不想把它写成我正在开发的部分。 DAL与产品上市速度无关 - 实际上,我从未想过DAL实现会比代码中的直接查询更快。但DAL的目标是抽象。抽象是有代价的,而且需要更长时间才能实现。

但是,好处是巨大的。在代码周围编写本机测试,使用表达类,强类型数据集等。我们使用各种“DAL”,这是在C#中使用Generics的纯DDD实现。所以我们有通用的存储库,工作单元实现(基于代码的事务)和逻辑分离。我们可以做很少的事情来模拟我们的数据集,并在数据库实现之前实际开发。构建这样的框架有一个前期成本,但业务逻辑再次成为该节目的明星非常好。我们现在将数据作为资源使用,并使用我们在代码中原生使用的语言来处理它。这种方法的另一个好处是它提供了清晰的分离。例如,我不再在网页中看到数据库查询。是的,该页面需要数据。是的,涉及数据库。但是现在,无论我从哪里提取数据,都有一个(也是唯一一个)进入代码并找到它的地方。对于较小的项目可能没什么大不了的,但是当你在一个站点中有数百个页面或在桌面应用程序中有几十个窗口时,你真的可以欣赏它。

作为一名开发人员,我受雇使用我的逻辑和分析技能来实现业务需求 - 我们的框架实现使我现在可以提高工作效率。作为一名经理,我宁愿让我的开发人员使用他们的逻辑和分析技能来解决问题,而不是编写SQL。事实上,我们可以构建一个使用数据库而不需要数据库直到接近开发周期结束的整个应用程序是一件很美妙的事情。它并不意味着对数据库专业人员的打击。有时,数据库实现比解决方案更复杂。 SQL(在我们的例子中,视图和存储过程,特别是)是一个抽象点,代码可以将数据作为服务使用。在数据和开发团队之间存在明确分离的商店中,这有助于消除等待数据库实施和更改的持有模式。开发人员可以专注于问题域而无需将鼠标悬停在DBA上,而DBA可以专注于正确的实施,而无需开发人员立即

答案 27 :(得分:0)

这里的很多帖子似乎都认为SQL很糟糕,因为它没有“代码优化”功能,而且你无法控制执行计划。

SQL引擎擅长的是为书面指令提出执行计划,面向数据,实际的内容。如果您想要超越编程方面的外观,您会发现在应用程序层之间传递的数据多于字节数。

答案 28 :(得分:0)

虽然SQL确实完成了工作,但肯定存在问题......


  • 它同时尝试高级和低级抽象 ,而 ... 奇数。也许它应该是两个或更多不同层次的标准。
  • 标准 是一个巨大的失败。当一个标准激起一切,要求太多,要求太少,或者出于某种原因无法实现激励供应商和实现者产生严格一致的可互操作的完整实现的部分社会目标时,很多事情都会出错。你当然不能说SQL已经做了这些。看看其他一些标准并注意到标准的成功或失败显然是获得的有用合作的一个因素:
    • RS-232(,指定不够,甚至哪个引脚发送和哪个引脚接收是可选的,sheesh。你可以遵守但仍然无法实现。成功互操作的机会:真的很低,直到IBM PC制定了事实上有用的标准。)
    • IEEE 754-1985浮点(错误,超越:没有一台超级计算机或科学工作站或RISC微处理器曾采用它,尽管最终在20年后我们能够很好地在HW中实现它。至少世界最终会成长。)
    • C89,C99,PCI,USB,Java(良好,无论是标准还是规范,他们成功地激发了几乎所有人的严格合规性,并且合规性导致了成功的互操作。)
  • 无法选择世界上最重要的数据库 。虽然这更像是数据点而不是理由,但Google Bigtable不是SQL而不是关系的事实对于SQL来说是一种反成就。