Robert C. Martin用SQL表示什么意思是什么?[关闭]


45

我一直在阅读/观看Robert C. Martin的很多内容。我碰到他说,由于固态硬盘,SQL是不必要的。当我搜索其他资源以进行备份时,我会收到大量随机文章,描述硬盘驱动器和固态驱动器之间的SQL性能差异(相关但与我要研究的内容无关)。

最终,我不明白他在试图达到什么目的。他是说用No-SQL技术取代SQL吗?他是说在文件系统中的文件中存储数据吗?还是他只是希望人们因为SQLi攻击而停止使用SQL /关系数据库?我担心我错过了他想表达的观点。

我将在此处提供一些链接,以便您可以直接从他的心中读懂:

  1. 鲍比表
  2. 清洁建筑讲座

首先,他指出应该从系统中完全删除SQL。

解决方案。唯一的解决方案。是从系统中完全消除SQL。如果没有SQL引擎,那么就不会有SQLi攻击。

并且尽管他谈论使用API​​替换SQL,但我不认为他的意思是将SQL放在API后面,因为前面的引用以及他在本文前面所说的。

框架无法解决问题; ...

旁注:在说SQL时,我很确定Robert意味着大多数关系数据库。也许不是全部,而是大多数。无论如何,大多数人还是使用SQL。所以...

如果不使用SQL来持久化数据,那么我们应该使用什么呢?

在回答之前,我还应该注意。罗伯特(Robert)强调,固态驱动器应该改变我们用来持久化数据的工具。SørenD.Ptæus的回答指出了这一点。

我还必须回应“但是数据完整性”组。经过进一步研究,罗伯特说我们应该使用像datomic这样的事务数据库。然后,CRUD变成CR(创建和读取),并且SQL事务完全消失。数据完整性当然很重要。

我找不到涵盖所有这些的问题。我想我正在寻找符合罗伯特指南的替代方案。Datomic是一个,但是是吗?还有哪些其他选项与这些准则匹配?它们在固态驱动器上是否更好地工作?


5
@ christo8989-“用API替换SQL是什么意思?”。我将他解释为意味着您在整个代码库中都没有文本查询语言(传递给SQL引擎)。您将此隐藏在仅公开描述查询安全机制的API后面。在API的内部,有些东西必须生成到SQL引擎的命令,但这是一个较小的表面积,您可以在其中强制使用参数绑定等,控制由谁进行更改等
。– Andrew

42
但是,但是,但是... SQL API。它是RDBMS的API。它恰好是一个非常强大的API,很容易被滥用。
Bart van Ingen Schenau,

25
如果您创建的数据库API没有文本接口,迟早有些程序员会编写如下代码:eval(request.GET["table_name"] + ".get(pk=" + request.GET["pk"] + ")"))。真正的错误不是SQL而是错误的,无知的程序员。
Lie Ryan

6
@JimmyJames SQL是一种语言,但这并不意味着它不是API。SQL是一种提供用于访问某些基础存储的API的语言。
立方'18

5
@nocomprende SQL始终被设计用于应用程序。否则,它实际上是没有用的。重点始终是为应用程序提供某种存储和检索数据的方法,而不会弄乱怪异的自定义格式,甚至不必关心数据的存储方式。
立方'18

Answers:


74

鲍勃·马丁(Bob Martin)显然在夸大其词,以使自己的观点更加清楚。但是他的意思是什么?

他是否只是希望人们由于SQLi攻击而停止使用SQL /关系数据库?

据我了解,Martin在该博客文章(您的第一个链接)中试图说服人们停止使用SQL,而不是关系数据库。这是两件事

SQL是一种功能非常强大的语言,并且在某种程度上已标准化。它允许以一种非常紧凑的方式,以一种可读,易懂,易学的方式创建复杂的查询和命令。它不依赖于另一种编程语言,因此对于大多数应用程序程序员而言,无论他们喜欢Java,C,C ++,C#,Python,Ruby,JavaScript,Basic,Go,Perl,PHP还是其他任何语言,它都可以使用。

但是,此功能需要付出一定的代价:编写安全的SQL查询/命令比编写不安全的SQL查询/命令更困难。安全的API应该使“默认情况下”创建安全查询变得容易。可能不安全的人应该需要更多的智力或至少更多的打字努力。这就是恕我直言,为什么Martin反对使用当前形式的SQL。

问题不是新问题,并且存在比标准SQL更安全的API来访问关系数据库。例如,我认识的所有OR映射器都试图提供这样的API(尽管它们通常是为其他主要目标而设计的)。静态SQL变体使使用未经过滤的输入数据创建任何动态查询变得很困难(这不是一项新发明:通常使用静态SQL的嵌入式SQL已有30年的历史了)。

不幸的是,我不知道有哪个API像标准的,成熟的,独立于语言的那样灵活,像SQL一样强大,尤其是动态SQL。这就是为什么我对马丁关于“不使用SQL”作为解决上述问题的现实方法的建议表示怀疑。因此,阅读他的文章是对正确方向的思考,而不是您从明天起可以盲目遵循的“最佳实践”。


2
至少我们可以避免在类似ORM的东西提供的任何写操作中使用它。至于查询数据库,您无需编写自己的SQL就已经可以做很多事情。如今,只有“高级”使用数据库功能才需要编写SQL或使用复杂的数据类型(图形,地理数据,递归)。
Walfrat

7
Martin确实明确指出使用的API 应该像SQL一样强大。他认为SQL的力量是问题,而不是功能。他争辩的API应该是特定于应用程序的,并且只有应用程序绝对需要的灵活和强大,而不是更多。他专门反对发明另一种基于字符串的查询语言。
立方'18

3
@Cubic:对于Martin提到的问题,任何解决方案都可能不如SQL强大或易于使用-这就是他们的祝福和诅咒。
布朗

1
@Barmar:SQL尽可能地高级,Bob断言这显然是不安全的。
罗伯特·哈维

3
@ christo8989:我认为写一个答案来回应马丁在职业生涯中曾经写过的话或说过的话并没有多大意义。我的答案是标题中给定问题的人,主要解释了您应该理解的第一个链接中博客文章的解释。
布朗

57

鲍勃·马丁的观点就是这样。一个人的意见。

程序员应该理解他编写的系统足够好,可以对它的安全性和性能进行合理的维护。这意味着,如果您正在使用SQL数据库,则可以按照Bobby Tables 网站的指示进行:清理输入数据。 这意味着您将SQL数据库放在可以保证足够性能的计算机上。有很多众所周知的方法可以做到这些,尽管它们不能保证绝对的安全性或理想的性能,但也无济于事。

断言我们不再需要SQL是因为我们现在有了SSD。尚未发明SQL是因为还没有高速硬盘。发明它是因为我们需要一种行业标准的方式来表达数据检索概念。关系数据库系统除了速度和安全性外,还具有许多其他特性,使其非常适合业务运营。特别是ACID。数据完整性至少与速度或安全性一样重要,如果您没有数据完整性,那么保护坏数据或尽快检索坏数据又有什么意义呢?

在您将一个人的歇斯底里当作福音之前,我建议您以自己的方式了解应用程序和系统的安全性以及性能,而不是阅读随机的Internet文章。安全性,性能和健壮的系统设计要远远超过“避免使用此技术”。

我们不禁止使用厨房用刀,因为一些不幸的人设法不小心割伤了他们的手指。


16
我不会把Martin的文章解释为提倡放弃RDBMS,而是使用其他与RDBMS交互的方式,例如LINQ-to-SQL或JPA Criteria API,而不是直接在源代码中编码或处理SQL字符串。
Jules '18

27
因此,我们不应盲目听从他的话……但是他在说什么?
TRiG

33
我真正不喜欢这里的社区的一件事是,当您提出有关执行“清洁代码” /“ Bob-way叔叔”的问题时,人们会蜂拥而至,告诉您您应该如何做不同的事情。“怎么画像梵高?” -“凡高错了,应该改为像毕加索一样绘画”。
R. Schmitz '18

21
在使用参数化方法将代码与输入分离之后,对输入数据进行消毒以防止注入攻击应该是备份选项。
棘轮怪胎

17
所有技术注定要失败,并且本质上是有缺陷的。这只是时间问题。同时,我们有缺陷的和注定的技术需要做的事情。

15

他到底在说什么?

他是说用No-SQL技术取代SQL吗?

TL; DR:是(某种)

在最近一次与您所链接的话题基本相同的话题中,他说:“数据库是一个细节。为什么我们有数据库?”

他声称数据库的出现是为了使从旋转磁盘的数据访问更容易,但是由于新技术和他所谓的“持久性RAM”,将来“ [...]不会有磁盘”,而且易于实现。使用程序员使用的结构(例如哈希表或树)存储数据。

他继续预测,由于关系数据库的新竞争,整个关系数据库将在很大程度上消失:

如果我是Oracle,我会很害怕,因为我的存在之所以从我的内心深处蒸发。[...]数据库存在的原因正在消失。

可能会有一些关系表存活下来,但是现在有一些健康的竞争

所以不,对他而言,这不仅与SQL注入有关,尽管他认为SQL在这方面存在固有的缺陷


作者注:

这篇文章中的陈述仅是为了理解Robert C. Martin在该主题上的观点而引述,并不代表作者的观点。有关更差异化的观点,请参见Robert Harvey的答案


2
“永久RAM”似乎仅解决了使用数据库来序列化当前应用程序状态的问题,而没有考虑向前或向后的兼容性。当然,某些数据库是以这种方式使用的,但绝不是全部(我意识到这是马丁在说的,不是您在说的)。
立方'18

7
因此,马丁实际上是在说数据库的唯一点是通过慢速存储进行抽象吗?哇。然后,这支持了罗伯特·哈维(Robert Harvey)的回答:他的观点应以大盐为准。例如,此观点未能考虑DB的价值在于维持一致且持久的数据模型。他对“持久性RAM”(SSDs)中的数据结构的想法既缓慢又开辟了数据丢失的可能性,即使NoSQL DB经常使用日记和不可变的数据结构来安全地更新持久性记录。
阿蒙(Amon)

3
@amon是的,罗伯特·哈维(Robert Harvey)提供正确的观点是正确的。但是由于OP特别询问了Robert C. Martin想要说什么,所以我抄录了他“较新的”演讲的一部分。
索伦D.Ptæus

3
@amon-参见上方Doc Brown回答的第一句话。马丁经常发表自己的观点夸大其词的说法,以使观点明白。他并不是说所有数据库操作都可以用内存中的存储来代替,他的意思不仅仅是拥有应用程序中某种以某种形式接触SQL的组件,这是一个巨大的安全隐患,应该从根本上避免案件,但从他的话来看,他可以被解释为这样说。但是他真正想做的只是让每个人停下来思考:SQL / RDBMS是否适合我的应用程序?
Jules '18

12
@Jules我知道他经常夸大其词。但是,鉴于他的影响力和声誉,“鲍勃叔叔”并没有在他夸大其词时以及他实际上在说什么意思时弄清楚了。如果他本来应该教些东西,那么对他所说的一切进行双重猜测和重新解释直到可行为止是不可行的,特别是因为他自己没有反映或批评自己的想法。在某个时候,说“不听他说”更容易,甚至说:Bob叔叔被认为有害
阿蒙

11

SQL是一个细节。细节知识不应传播。

随着SQL在代码中越来越多的地方被使用,您的代码越来越依赖于它。

随着学习越来越多的SQL技巧,您使用SQL解决了越来越多的问题。这意味着切换到另一个API以持久化不仅仅涉及翻译。您必须解决自己没有意识到的问题。

您在数据库之间甚至遇到了这种切换。一个提供花哨的whizzbang功能5,因此您在许多地方使用它仅发现花哨的whizzbang功能5是专有的,现在您遇到了许可问题,这将花费很多钱。因此,您需要做很多工作,在使用功能5的任何地方进行挖掘,然后自己解决问题,然后才发现您还在使用whizzbang功能3。

使Java如此可移植的原因之一就是CPU的某些功能不可用。如果它们可用,我会使用它们。突然有CPU无法使用我的Java代码,因为它们没有这些功能。数据库功能相同。

在没有意识到的情况下牺牲自己的独立性很容易。SQL不是一个选择。如果您决定使用SQL,则将它放在一个地方。以无法制造的方式制造。

SQL存在安全性问题,而我们正在转向持久性内存模型,这并不意味着SQL注定要失败。它只是表明它是一种选择。如果您想保留做出选择的权利,则必须完成工作。


可能值得注意的是,80年代和Bob叔叔的数据库移动历史相当糟糕。当管理迫使一个数据库管理员进入生活时,他使用平面文件系统解决了所有问题。这一事件将他推向了出色的咨询职业。(他在他的一本早期的干净书中讲述了这个故事,忘记了哪一个)。他知道如何在没有DB的情况下解决问题,并且对于那些像使用它们那样表现的人几乎没有耐心。

他还讲述了一个有关推迟将数据库添加到应用程序的故事,直到客户要求将其添加到最后一刻,并在一天之内将其添加为可选功能。我的猜测是他认为这是我们大多数人将DB当作瘾的方式。他试图向我们展示如何消除这种习惯。


1
爱因斯坦,戈什,当然。

1
啊,不知道爱因斯坦认识鲍勃。或者鲍勃是上帝。尽管听起来好像很有趣,但它很有特色。
candied_orange

9
@nocomprende您生活在稳定的励志海报上吗?
candied_orange

2
但是鲍勃上帝。至少有一些。
彼得·莫滕森

3
我拒绝相信上帝擅长公开演讲。
candied_orange

5

第一个引号中的引号是(强调我的),

解决方案。唯一的解决方案。是从系统中完全消除SQL。如果没有SQL引擎,那么就不会有SQLi攻击。

用什么代替SQL?API当然!而不是使用文本语言的API。而是使用一组适当的数据结构和函数调用来访问必要数据的API。

反对是让应用程序程序员使用SQL。

建议的解决方案是让他们改用API:这不是SQL且不允许注入。

IMO,此类API的示例可能包括:

  • http://bobby-tables.com/csharp建议C#程序员可以使用ADO.NET API。

    这不是一个完美的例子,因为ADO.NET是一个广泛的或深层的(即功能强大或通用的)API,它允许其用户输入原始(或原始的)SQL。

  • 一些SQL开发人员或数据库管理员建议对数据库进行配置,使其仅允许通过(数量有限的专家编写的)存储过程进行访问,并且不应允许应用程序开发人员编写自己的(危险的)SQL查询

  • “从系统中消除SQL”的另一种方法是将数据库(公开SQL)放置在其他系统上,该系统可通过REST API或类似方法进行访问。

因此,IMO,整体解决方案或系统仍然可以使用数据库(特别是考虑到数据库引擎实现了有用的ACID属性并且可以很好地扩展等等),尝试不使用它或编写特定于应用程序的一个)。

如果数据库的SQL API对应用程序开发人员是隐藏的,而在某些其他API(例如ADO,ORM,Web服务等)的后面,则满足rant的要求。

更一般地说,我认为这意味着具有特定于应用程序的DAL(“数据访问层”或“数据库抽象层”)。DAL将应用程序与如何以及在何处存储和/或提取数据的细节隔离开来。DAL可以使用SQL数据库来实现,也可以不使用。


我从事的产品正是在30年前就做到了。而且,底层数据库甚至还不支持SQL。并且,相关表集存储在数据库中(等待它……)。这个想法的人真的很聪明。虽然不再是程序员。

我喜欢这个答案,但我认为他可能不会这么说。他还指出,“ Framework无法解决问题...”。从您的答案看来,您似乎在说使用Linq-to-Sql可以,但是不是一个处理该问题的框架吗?
christo8989 '18

@ christo8989我不知道。他提到了Hibernate作为无法处理该问题的框架的示例。确实,OWASP说:“ Hibernate不授予对SQL注入的免疫性,可以随意使用api。HQL(SQL的Hibernates子集)没有什么特别之处,可以使它变得或多或少容易受到攻击。” 我提到的某些API可能是更好的隔离器,根本不会暴露SQL。也许您可以使用Hibernate来实现DAL(但它本身并不是完全绝缘的DAL)。
ChrisW '18

1
@ christo8989 augustl.com/blog/2016/...表明Datomic是(只),另一种包装/层左右(可能-SQL)数据库- “Datomic不直接写入文件系统相反,你可以使用一个号码。各种数据库作为Datomic的存储后端:任何SQL JDBC数据库,等等。”
ChrisW

应该注意的是,避免在ADO.NET中进行SQL注入解决方案并不那么复杂-在SQL中使用占位符,在命令中使用参数,并设置所述参数的值。
泽夫·斯皮茨

3

从安全角度或从SQL的角度来看,每个人似乎都在回答这个问题。

我看过罗伯特·马丁(Robert Martin)的一次演讲,他在演讲中谈到作为程序员,我们使用许多不同的数据结构,这些数据结构对于我们的特定程序是最佳的。因此,与其将所有数据通用地存储在表格结构中,不如将数据存储在哈希表,树等中,这样我们就可以获取数据并直接跳入程序。

我将他的信息解释为仅说我们应该暂时放弃关于持久性存储的当前假设,以考虑除陈旧的SQL表格格式之外的其他未来可能性。SSD是一种候选解决方案,但不是唯一的解决方案。


他对多用户并发读取/写入数据有何看法?
ChrisW

1
@ChrisW我不认为这是实现的问题,而是寻求更好地进行持久性数据存储的方法的高级想法。
基南

@ChrisW他还谈到了事务数据库。将源代码控制技术用作您的持久性工具。这样,您只需创建和读取与事务和更新相比并发友好得多的文件。
christo8989 '18

@Keenan因此,他并没有真正通过实施提供解决方案。他只是说,想想可能是什么?
christo8989 '18

1
@ christo8989他是否亲自领导过解决计算机科学中持久性存储问题的候选解决方案,我不知道。这超出了OP的范围。Bob叔叔全是关于插件体系结构的。当前应用程序开发的行业标准与数据库紧密耦合并围绕该数据库构建应用程序,该应用程序依赖于数据库,而数据库则应依赖于该应用程序。相反,鲍勃叔叔提出“数据库是一个细节”,应该脱钩和更换。
基南

2

实际上,他不会显式地使用数据库和SQL。第一个参考文献是一个众所周知的问题,第二个参考文献听起来像是在咆哮。虽然,我将其解释为使用数据库而不使用SQL的充分理由。在我看来,这甚至不是合理的建议。

不幸的是,他正在使用的示例是一个众所周知的示例,并提供了众所周知的解决方案。通常是在程序员没有意识到自己在做什么的时候发生的。例如,构造包含SQL的字符串,例如:

    my $sql="select a from b where a=$ui_val;";
    prepare($sql)
    execute($sql)

相对于

    my $sql="select a from b where a=?;";
    prepare($sql)
    execute($sql,$ui_val);

这是一个DBI perl,例如ruby on rails代码的示例。他提供的rails代码很容易在安全与不安全之间混淆。就像许多ORM一样,它隐藏了SQL的底层,因此您经常要处理一个为您构造和执行sql的接口。这听起来像API会为您做什么吗?

我对第一个参考文献的解释是,他建议我们应该替换一个解决方案众所周知的问题。

不幸的是,他没有提到如果正确完成此操作,将使代码更易于编写和更具可读性,但是如果操作得当,则实际上可能更难编写且可读性更差。此外,他没有提到SQL确实非常易于阅读,并且可以执行您通常期望的功能。

他部分正确,最终我们将拥有一个无限大且快速的内存和一个无限快速的处理器。直到我们从限制计算的当前物理学中滑出,他才是正确的。

是的,旋转磁盘已成为过去,现在我们使用SSD。磁盘每次数据传输大约需要10毫秒,而SSD数据访问时间大约需要0.5毫秒(500微秒)。RAM大约为100纳秒,处理器的工作时间为100皮秒。这就是为什么我们需要数据库的核心。数据库管理旋转磁盘或具有主内存的SSD之间的数据传输。SSD的问世并未消除对数据库的需求。


4
我了解,“停止使用SQL”(引自第一个链接)听起来很像他在说不使用SQL。
布朗

6
这是一个字序问题。实际上,这最初是一个电报:USING SQL STOP

6
@nocomprende所以你是说他是比赛条件的受害者?好,哎呀 他本可以通过使用SQL事务来避免这种情况。
康拉德·鲁道夫

也许这是Visual Basic和Fortran的很短的混合。到底会在哪里结束?

1
@KonradRudolph:好吧,我想我们同意几乎没有人会直接从汇编中使用TSX。将有更高层次的抽象。这些抽象事务将是SQL事务吗?我想不是。作为一种解释型语言,SQL会带来性能开销。当您访问旋转硬盘上的数据时,这并不重要。但是,当访问RAM中的数据时,这是无法承受的。
MSalters

2

回答

他只是想让人们因为SQLi攻击而停止使用SQL /关系数据库吗?

“ Bobby Tables”文章似乎暗示了这一点,这本身就是不使用SQL的原因:

解决方案。唯一的解决方案。是从系统中完全消除SQL。如果没有SQL引擎,那么就不会有SQLi攻击。

他可能还有其他原因要在其他地方讨论。我不知道,因为我不太了解他的很多东西。

离题

这部分并不是真正的答案,但我认为SQL的价值问题要有趣得多(显然其他人也是如此)。

我在使用SQL方面有很多经验,我认为我对SQL的优缺点有一定的了解。我个人认为它已经被过度使用和滥用,但是我们永远不应该使用它的想法有点愚蠢。我们必须选择“永远使用SQL”或“永远不要使用SQL”的想法是错误的二分法。

至于SQL注入是不使用SQL的理由,那是可笑的。通过一个非常简单的解决方案,这是一个众所周知的问题。该参数的问题在于SQLi并不是唯一存在的漏洞。如果您认为使用JSON API可以确保您的安全,那么您将大吃一惊。

我认为每个开发人员都应该观看标题为“ 13号星期五:攻击JSON-AlvaroMuñoz和Oleksandr Mirosh-AppSecUSA 2017”的视频。

如果您没有时间或兴趣来研究它,请遵循以下要点:许多JSON反序列化库都具有远程代码执行漏洞。如果您使用的是XML,那么您还有更多的担忧。从架构中禁止SQL不会使您的系统安全。


没有人声称禁止SQL本身可以使您的系统安全。Bob叔叔声称它可以使您的系统安全,并且鉴于SQL注入仍然是十多年来Web应用程序安全性的最大风险,我认为您不应该轻视行业需要改进其与数据库进行通信的方式。
meriton-罢工

@meriton对不起,但是“解决方案,唯一的解决方案”似乎很清楚。SQLi问题的解决方案是已知的,而且非常简单。那些不愿意使用prepare语句的人将创建不安全的系统,无论他们是否停止使用SQL。这些是非专业人士,需要开始遵循基本的良好做法或找到新工作。
JimmyJames

2

我只想谈一个简短的声明:

还是他只是希望人们因为SQLi攻击而停止使用SQL /关系数据库?

不。那是一个错误的假设。我们不能说我们必须停止使用汽车,因为它们对死于车祸的人负责。以相同的方式,SQL /关系数据库(或此上下文中的任何其他数据库,如RDBMS)都不对攻击者可以在Web应用程序上执行的恶意SQL有效负载负责。我确信作者不是那个意思,因为为此目的有一个完整的SQL注入预防备忘单


2
自动驾驶汽车将预防约98%的车祸。我们需要信任的机器,嘿嘿嘿嘿。

3
“我们不能说我们必须停止使用汽车(除非出于特殊和/或受到严格控制的情况除外),因为它们对在交通事故中丧生的人负责。” —乌姆。我们绝对可以这样说。许多有理智的人都这样做。
康拉德·鲁道夫'18

1
您基本上是在说:用Java开发的应用程序被黑了,所以我们必须停止使用Java。拒绝投票就足够了,对于其余的事情,我并不是在这里教给您常识。@KonradRudolph
Billal Begueradj,

2
@BillalBEGUERADJ这在某种程度上是错误的对等(因为没有什么东西可以安全地被黑客入侵),但也不是完全不对。例如,如果您在系统编程范围之外使用C,那么您做错了。无论如何,我没有拒绝您的回答,但这错误的:因为与您的主张相反,这就是鲍勃·马丁所说的(正如其他答案所示)。
康拉德·鲁道夫'18

2

Martin的问题似乎在于程序员直接从用户输入构建动态SQL ,例如(原谅,我主要是C和C ++程序员):

sprintf( query, "select foo from bar where %s;", user_input );

绝对是导致胃灼热的秘诀(因此Bobby Tables带)。任何将这样的代码放入生产系统中的程序员都应该得到满足。

您可以通过使用准备好的语句并适当清理输入内容来缓解(如果不能完全消除)该问题。如果您可以将SQL隐藏在API后面,以使程序员不会直接构建查询字符串,那就更好了(这是Martin所倡导的一部分)。

但是,要完全摆脱SQL,我认为这是不切实际或不可取的。关系模型很有用,这就是为什么它们首先存在的原因,而SQL可能是使用关系模型的最佳接口。

与往常一样,这是使用正确工具完成工作的问题。如果您的购物车应用程序不需要完整的关系模型,则不要使用关系模型(这意味着您不需要使用SQL)。有时您确实需要一个关系模型,那么几乎可以肯定您将使用SQL。


虽然sprintf不含有那种消毒的是SQL要求,其设计专门用于此目的的功能做的,并且是完全安全的。示例:实体框架中的SqlQuery
罗伯特·哈维

@RobertHarvey:我想是这样。就我而言,我主要是在C和C ++中进行服务器端工作,因此我仍然偶尔看到(非常罕见的)仅使用sprintf动态SQL 的人的示例,这不是您的工作方式。
约翰·博德

1

您链接的两个来源传达了不同的消息:

博客文章说,数据访问逻辑在运行时不应该以文本形式存在,以免与不可靠的用户输入混合在一起。也就是说,博客文章通过串联字符串来谴责编写查询。

讲座是不同的。第一个区别是语调:讲座进行了推测,并提出了质疑,但没有谴责。他并不是说数据库是邪恶的,而是向我们挑战了没有数据库的持久性。他认为,自从关系数据库普及以来的30年中,许多事情发生了变化,并着重指出了可能会影响我们对持久性技术选择的两个方面:

  • 存储空间增加了约100万倍-价格可比!因此,无需保存存储,特别是不再需要删除。通过使用仅追加存储,可以简化并发控制,因为不需要读锁。这可以消除交易的需要。
  • 访问时间减少了,因为现在大多数数据集都可以放入RAM中,从而大大减少了读取延迟。

这些变化的环境会改变最佳的持久性技术吗?有趣的是,鲍伯叔叔没有说-大概是因为他觉得没有答案适合所有程序。这就是为什么他警告我们将对持久性技术的选择视为一个细节,而不是将其融入石碑中,并将其作为已有的智慧传递给我们的同行。

是否存在替代方案?

不用字符串就可以编写数据访问逻辑。在Java领域中,您可以使用QueryDSL,其中使用从数据库架构生成的类型安全的Fluent API描述查询。这样的查询可能如下所示:

JPAQuery<?> query = new JPAQuery<Void>(entityManager);
Customer bob = query.select(customer)
  .from(customer)
  .where(customer.firstName.eq("Bob"))
  .fetchOne();

如您所见,查询逻辑不是用字符串表示的,从而清楚地将查询的可信结构与不可信的参数分开(当然,QueryDSL永远不会在查询文本中包含参数,而是使用准备好的语句来分隔查询(在JDBC级别的参数)。要使用QueryDSL实现SQL注入,您必须编写自己的解析器来解析字符串并将其转换为语法树,即使这样做,您可能也不会添加对诸如讨厌的东西的支持select ... into file。简而言之,QueryDSL使SQL注入变得不可能,并且还提高了程序员的生产率并提高了重构安全性。防止了对Web应用程序安全性的最大风险,该风险已经存在了足够长的时间,可以产生运行中的漏洞,并提高了开发人员的生产力?我敢说,如果您仍然将查询写为字符串,那就错了。

至于关系数据库的替代方案,很奇怪地知道postgres的多版本并发控制正是Bob叔叔正在谈论的那种仅追加数据结构,尽管他可能考虑了更多的事件存储事件源。一般而言,这种模式也非常适合将当前状态保存在RAM中的概念。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.