最近,我听到很多信息,说SQL是一种可怕的语言,而且似乎在阳光下的每个框架都预先包装了一个数据库抽象层。
但是以我的经验来看,SQL通常是管理数据输入和输出的更容易,更通用且对程序员更友好的方法。我使用的每个抽象层似乎都是一种有限的方法,没有真正的好处。
是什么使SQL如此可怕,为什么数据库抽象层很有价值?
最近,我听到很多信息,说SQL是一种可怕的语言,而且似乎在阳光下的每个框架都预先包装了一个数据库抽象层。
但是以我的经验来看,SQL通常是管理数据输入和输出的更容易,更通用且对程序员更友好的方法。我使用的每个抽象层似乎都是一种有限的方法,没有真正的好处。
是什么使SQL如此可怕,为什么数据库抽象层很有价值?
Answers:
这部分是主观的。所以这是我的意见:
SQL有一个 伪自然语言样式。发明人相信他们可以创建像英语一样的语言,并且数据库查询将非常简单。一个可怕的错误。除了极少数情况外,SQL很难理解。
SQL是声明性的。你不能告诉数据库如何应该做的东西,你想要的结果正是。如果您不必在意性能,那将是完美而强大的功能。因此,您最终要编写SQL-读取执行计划-改写SQL试图影响执行计划,并且您想知道为什么不能自己编写执行计划。
声明性语言的另一个问题是某些问题更容易以命令式方式解决。因此,您可以使用另一种语言(需要标准SQL并可能需要数据访问层)来编写它,也可以使用供应商特定的语言扩展,例如编写存储过程等。这样做可能会发现您正在使用的是您见过的最糟糕的语言之一,因为它从未被设计为用作命令式语言。
SQL 很老了。SQL已经标准化,但是为时已晚,许多供应商已经开发了其语言扩展。因此,SQL变成了数十种方言。这就是应用程序不可移植的原因,也是拥有数据库抽象层的原因之一。
但这是真的-没有可行的替代方案。因此,我们都将在未来几年中使用SQL。
除了所说的一切之外,使抽象层变得有价值的技术也不一定很糟糕。
如果您正在做一个非常简单的脚本或应用程序,则可以在任意位置将SQL调用混入代码中。但是,如果您使用的是复杂的系统,则将数据库调用隔离在单独的模块中是一个好习惯,因此它也隔离了您的SQL代码。它提高了代码的可读性,可维护性和可测试性。它使您可以快速使系统适应数据库模型的变化,而无需分解所有高级内容等。
SQL很棒。它上面的抽象层使它变得更大!
抽象层的一个方面是这样的事实,即由于标准有点模棱两可,而且大多数供应商都在此添加了自己的(非标准)附加功能,因此SQL实现彼此之间或多或少地不兼容。也就是说,为MySQL数据库编写的SQL与“ Oracle数据库”可能无法完全类似地工作,即使“应该”也是如此。
不过,我同意,SQL比目前大多数抽象层都要好。SQL并非用于非设计用途,这并不是SQL的错。
SQL从以下几个方面入迷:
如果您坚持使用一种DBMS产品,那么我绝对同意SQL DB比其竞争对手更具通用性和更高的质量,至少直到您遇到模型固有的可伸缩性障碍之前。但是,您是真的要编写下一个Twitter,还是只是要保持一些会计数据的组织性和一致性?
对SQL的批评通常是对RDBMSes的批评的代表。RDBMS的批评者似乎不理解的是,它们很好地解决了一大类计算问题,并且它们在这里使我们的生活更轻松,而不是更艰难。
如果他们认真批评SQL本身,那么他们会支持Tutorial D和Dataphor等工作。
没那么可怕。当出现新的“范例”时,废除以前的可靠技术是该行业的不幸趋势。归根结底,这些框架最有可能使用SQL与数据库进行通信,这怎么可能会很糟糕呢?也就是说,拥有“标准”抽象层意味着开发人员可以专注于应用程序代码,而不是SQL代码。没有这样的标准层,您可能在每次开发系统时都编写一个轻量级的层,这很浪费精力。
我不会说这很糟糕。这不适用于某些任务。例如:您不能使用SQL编写好的过程代码。我曾经被迫使用SQL进行集合操作。我花了整个周末才弄清楚。
SQL是为关系代数设计的-应该在此处使用它。
最近,我听到很多信息,说SQL是一种可怕的语言,而且似乎在阳光下的每个框架都预先包装了一个数据库抽象层。
请注意,这些图层只是将自己的内容转换为SQL
。对于大多数数据库供应商而言,这SQL
是与引擎通信的唯一方法。
但是以我的经验来看,SQL通常是管理数据输入和输出的更容易,更通用且对程序员更友好的方法。我使用的每个抽象层似乎都是一种有限的方法,没有真正的好处。
……我刚才描述的原因。
数据库层不添加任何内容,它们只是限制了您。它们无疑使查询更简单,但从未如此高效。
根据定义,在数据库层中没有什么不在SQL
。
是什么使它
SQL
如此可怕,为什么数据库抽象层很有价值?
SQL
是一种不错的语言,但是使用它需要花些时间。
理论上, SQL
是声明性的,也就是说,您声明要获得的内容,然后引擎以最快的方式提供它。
实际上,有许多方法可以制定正确的查询(即返回正确结果的查询)。
优化程序可以使用一些预定义的算法来构建Lego城堡(是的,它们是多个),但是他们无法制定新的算法。仍然需要SQL
开发人员来协助他们。
但是,有些人希望优化器产生“可能的最佳计划”,而不是“在给定的实施情况下,此查询可用的最佳计划”。 SQL
引擎 ”。
众所周知,当计算机程序不能满足人们的期望时,应归咎于程序而不是期望。
但是,在大多数情况下,重新构造查询实际上可以产生最佳计划。但是,在不可能的SQL
情况下会有一些任务,但是随着这些案例的不断更新和改进,其数量越来越少。
但是,如果供应商提供了对功能的低级访问,例如“获取索引范围”,“按行获取rowid
”等,那将很好,就像C
编译器允许您将程序集直接嵌入到语言中一样。
我最近在我的博客上写了一篇关于此的文章:
我会说框架附带的数据库抽象层是一件好事,因为它解决了两个非常重要的问题:
它使代码与众不同。 通过将SQL放到通常很薄的另一层中,该层通常仅应进行查询和结果的传递(以标准化方式),这可以使您的应用程序摆脱SQL的混乱。这是Web开发人员(应)将CSS和Javascript放在单独文件中的相同原因。如果可以避免,请不要混用多种语言。
许多程序员只是在使用SQL方面很不好。 无论出于何种原因,大批开发人员(尤其是Web开发人员)似乎在使用SQL或RDBMS方面都非常非常糟糕。他们将数据库(以及扩展的SQL)视为必须获取数据的肮脏的小中间人。这导致考虑周全的数据库没有索引,以可疑的方式将表堆叠在表的顶部,并且编写的查询也很差。或更糟糕的是,它们试图变得过于笼统(专家系统,有人吗?),并且无法以任何有意义的方式合理地关联数据。
不幸的是,有时由于无知,固执或其他特质,某人尝试解决问题的方式和所使用的工具彼此直接对立,并且很幸运地试图说服他们。因此,除了作为一种好的做法之外,我还认为数据库抽象层是一种安全网,因为它不仅使SQL不在开发人员的视线之外,而且使他们的代码重构起来非常容易,因为所有查询都在一个地方。
SQL对于某些类型的任务非常有用,特别是处理和检索数据集。
但是,SQL缺少(或仅部分实现)用于管理变更和复杂性的几个重要工具:
封装:SQL的封装机制很粗糙。编写SQL代码时,您必须了解有关数据实现的所有知识。这限制了您可以实现的抽象量。
多态性:如果要对不同的表执行相同的操作,则必须编写两次代码。(可以通过富有想象力的使用视图来减轻这种情况。)
可见性控制:没有标准的SQL机制可用于将代码段彼此隐藏或将它们分组为逻辑单元,因此,即使不需要,每个表,过程等也可以相互访问。
模块化和版本控制
最后,在SQL中手动编码CRUD操作(并编写代码以将其连接到其他应用程序)是重复性的,而且容易出错。
现代化的抽象层提供了所有这些功能,并允许我们在隐藏破坏性,重复性实现细节的地方使用最有效的SQL。它提供了一些工具来帮助克服对象关系阻抗不匹配的问题,这使面向对象软件开发中的数据访问变得复杂。
一方面,它们使使用参数化查询变得微不足道,从而保护您免受SQL注入攻击。从这个角度来看,使用原始SQL的风险更大,也就是说,从安全角度来看更容易出错。他们还经常在您的数据库上提供面向对象的观点,使您不必进行此转换。
$dbh->do("DELETE FROM my_table WHERE some_value = ?", undef, $target_value);
那里。做完了
对于有经验的SQL程序员来说,不利的一面是
对于其他人,原因是
SQL框架的主要目标是减少输入。它们以某种方式做到了,但通常仅用于非常简单的查询。如果您尝试做一些复杂的事情,则必须使用字符串并输入很多内容。试图处理一切可能的框架(例如SQL Alchemy)变得太大,就像另一种编程语言一样。
[26.06.10更新]最近,我使用Django ORM模块。这是我见过的唯一有价值的SQL框架。而这一点使得处理很多东西成为可能。不过,复杂的集合体要难一些。
SQL并不是一种可怕的语言,有时它在其他语言中的表现不太好。
例如,如果您有一个系统想要用某种OO语言或另一种语言将所有实体表示为对象,那么在没有任何抽象层的情况下将其与SQL结合起来将变得相当麻烦。没有简单的方法可以将复杂的SQL查询映射到OO-world。为了缓解这些世界之间的紧张关系,插入了其他抽象层(例如OR-Mapper)。
SQL是用于数据操作的非常好的语言。从开发人员的角度来看,我不喜欢的是更改数据库不会在编译时破坏您的代码...因此,我使用抽象技术来添加此功能,但会牺牲性能和SQL语言的表现力,因为在大多数应用程序中,您不需要SQL拥有的所有东西。
讨厌SQL的另一个原因是由于关系数据库。
该CAP定理变成流行:
您可能希望共享数据系统有哪些目标?
- 强大的一致性:即使有更新,所有客户端也会看到相同的视图
- 高可用性:即使存在故障,所有客户端都可以找到数据的某些副本
- 分区容限:即使对系统进行分区,系统属性也会保留
定理指出,您始终只能同时拥有三个CAP属性中的两个
关系数据库地址具有很强的一致性和分区容忍性。
因此,越来越多的人意识到关系数据库不是万灵药,并且越来越多的人开始拒绝使用数据库以支持高可用性,因为高可用性使横向扩展变得更加容易。因为我们已经达到摩尔定律的极限,所以水平缩放获得了普及,所以,因此最好的缩放方法是添加更多的机器。
如果关系数据库被拒绝,SQL也将被拒绝。
正如这里的其他一些提示所指出的那样,SQL有许多缺陷。尽管如此,我还是更喜欢使用SQL,而不是人们提供的许多其他工具,因为“简化”通常比他们应该简化的东西更复杂。
我的理论是,SQL是由一群象牙色的蓝色滑雪者发明的。整个非程序结构。听起来很棒:告诉我您想要什么,而不是想要如何做。但是在实践中,仅给出步骤通常会更容易。通常,这似乎是试图通过描述完成后汽车的性能来提供汽车保养说明。是的,您可以说,“我希望汽车再次达到每加仑30英里,并以这种嗡嗡声……嗯……等等来运行。”但是,每个人都不会更容易只是说:“更换火花塞”?即使您确实想出了如何以非过程性术语来表达复杂的查询,数据库引擎也常常会提出效率很低的执行计划。
空值的处理使我发疯!是的,从理论上讲,当有人说:“嘿,如果null表示未知,那么将未知值添加到已知值应该会得到未知值。”毕竟,根据定义,我们不知道未知值是什么”。从理论上讲,绝对正确。在实践中,如果我们有10,000个客户,并且我们确切知道有9,999欠我们多少钱,但是最后一个欠我们多少钱,还有一个问题,管理层说:“我们的应收帐款总额是多少?”,是的,在数学上是正确的答案是“我不知道”。但是实际的答案是“我们计算了$ 4,327,287.42,但是有一个帐户有问题,所以这个数字不准确”。我敢肯定,如果没有确定的数字,管理层宁愿闭嘴也不愿空白。
话虽这么说,我还是宁愿使用SQL而不是在SQL之上构建的某个层,它只是创建了我需要学习的另一整套东西,然后我必须知道最终它会被翻译成SQL,有时我可以相信它能正确有效地进行翻译,但是当事情变得复杂时,我就不知道了,所以现在我必须了解额外的层,我仍然必须了解SQL,而且我必须知道它将如何翻译我可以欺骗该层,诱使SQL执行正确的操作。啊
•每个供应商都扩展了SQL语法以适合他们的需求。因此,除非您做的非常简单,否则您的SQL代码是不可移植的。
•SQL的语法不是正交的;例如,select, insert, update,
和delete
语句都具有完全不同的语法结构。
insert
和update
运算符之间,它们在语义上几乎相同,但在语法上却完全不同。
我同意您的观点,但要回答您的问题,使SQL如此“糟糕”的一件事是数据库供应商(Sql Server,Oracle等)之间缺乏完整的T-SQL标准化,这使得SQL代码不太可能成为完全便携。数据库抽象层解决了此问题,尽管这会带来性能损失(有时会非常严重)。
很快,请给我写SQL来对可在MySQL,Oracle,MSSQL,PostgreSQL和DB2中使用的数据集进行分页。
哦,对了,标准SQL并没有定义任何运算符来限制返回结果的数量以及从哪一行开始。
对SQL没有爱,因为SQL在语法,语义和当前用法方面都很糟糕。我会解释:
我同意这里的大多数帖子,关于SQL实用程序的辩论主要是主观的,但是我认为在您的业务需求的本质上,它更具主观性。
正如Stefan Steinegger指出的那样,声明性语言非常适合于指定您想要的内容,而不是您想要的方式。这意味着从高层的角度来看,您的各种SQL实现都是不错的:也就是说,如果您只想获取一些数据而没有其他事项,则可以编写相对简单的查询并选择SQL实现来满足自己的需求。那很适合您。
如果您的工作水平要低得多,并且您需要自己优化所有这些,那么这远非理想。使用更多的抽象层可以有所帮助,但是如果您真正想做的是指定优化查询的方法等等,那么在尝试进行优化时添加中间人有点反常的感觉。
我对SQL的最大疑问是与其他“标准化”语言一样,真正的标准很少。我几乎希望在Sybase和MySQL之间学习一种全新的语言,以免使这两个约定混淆。
虽然SQL确实完成了工作,但肯定存在问题...
我不喜欢SQL,但是我也不想写它作为我正在开发的一部分。DAL并不是要加快产品上市的速度-实际上,我从未想到过会有比直接查询代码更快的DAL实现。但是DAL的目标是抽象。抽象是有代价的,在这里实现将花费更长的时间。
好处是巨大的。使用表达类,强类型数据集等围绕代码编写本机测试。我们使用各种“ DAL”,这是在C#中使用泛型的纯DDD实现。因此,我们有了通用存储库,工作单元实现(基于代码的事务)和逻辑分离。我们可以轻松完成模拟数据集之类的事情,并在数据库实现之前进行实际开发。建立这样的框架需要一笔前期费用,但是很高兴业务逻辑再次成为展会的明星。现在,我们将数据作为资源使用,并使用代码中本机使用的语言来处理数据。这种方法的另一个好处是它提供了清晰的分隔。例如,我不再在网页中看到数据库查询。是的,该页面需要数据。是的,涉及数据库。但是现在,无论我从哪里提取数据,都只有一个(只有一个)地方可以找到代码并找到它。在较小的项目上可能没什么大不了的,但是当您在一个站点中拥有数百个页面,或者在桌面应用程序中拥有数十个窗口时,您确实可以欣赏它。
作为一名开发人员,我被聘用来使用我的逻辑和分析技能来实现业务需求-我们的框架实现使我现在的工作效率更高。作为一名经理,我宁愿让我的开发人员使用他们的逻辑和分析技能来解决问题,而不是编写SQL。我们可以构建一个使用数据库的整个应用程序而无需在开发周期结束之前拥有数据库这一事实,这是一件很美的事情。这并不意味着要打击数据库专业人员。有时,数据库实现比解决方案更复杂。SQL(在我们的例子中是Views和Stored Procs)是一个抽象点,代码可以将数据作为服务使用。在商店中,数据团队和开发团队之间存在明确的界限,这有助于消除等待数据库实现和更改的等待模式。开发人员可以将精力集中在问题域上,而无需将其悬停在DBA上,而DBA可以将精力集中在正确的实现上,而开发人员无需使用它现在。