使用查询生成器而不是使用原始SQL有什么好处吗?
例如
$q->select('*')
->from('posts')
->innerJoin('terms', 'post_id')
->where(...)
vs:
SELECT * FROM posts WHERE ...
我看到许多框架都使用这些抽象层,但是我无法理解其好处。
使用查询生成器而不是使用原始SQL有什么好处吗?
例如
$q->select('*')
->from('posts')
->innerJoin('terms', 'post_id')
->where(...)
vs:
SELECT * FROM posts WHERE ...
我看到许多框架都使用这些抽象层,但是我无法理解其好处。
Answers:
通过框架很好地编写SQL的抽象就是抽象。
手工编写SQL本身并没有那么糟糕,但是您开始遇到转义和清理问题,这变得一团糟。抽象层可以在后台处理所有这些工作,从而使您的代码干净整洁,并且无需进行大量mysql_real_escape_string()
调用等操作。
另外,这带来了考虑SQL不同方言的可能性。并非所有数据库的构建都相同,并且关键字或某些功能的语法可能会有所不同。使用抽象层可以动态地为变量生成正确的语法。
尽管抽象层会带来性能上的损失,但与您收到的代码的整洁性和健壮性相比,它通常可以忽略不计。
查询构建器是我的宠儿,所以我写了自己的Framework(Apeel)来避免使用它们!
如果您使用PDO(我绝对会建议您这样做),那么将为您处理输入。
就像其他人所说的那样,尽管它们确实使在数据库之间切换变得更加容易,但是它们倾向于支持“最低公分母”功能,或者对于更高级的功能要么不支持,要么性能较差。
从1986年左右开始,我就一直在开发具有数据库的系统,并且在所有这些时间里,除了需要更好的性能时,我很少遇到公司实际更改他们使用的数据库。如果您要更改数据库以获得更好的性能,那么花时间手动优化查询以从新数据库中获得最大收益就变得更加有意义,而不是为了简单起见而选择查询构建器。
花费大量时间来掌握查询生成器的qwirks(然后在切换到更好的查询器时重新学习)将花费在学习如何优化SQL上的工作效率更高。
无论如何,这就是为什么不使用它的原因,尽管有些人喜欢它们。
从理论上讲?是。Glenn Nelson指出了他们如何经常为您提供帮助。(如果它是一个好的查询生成器)。
在实践中?并不总是符合理论并可能导致问题。假设您正在针对一些流行的DBMS使用查询生成器,并且一切都变了。然后,客户要求您打他们的DBMS,其中包含您选择的查询生成器无法处理的一些怪癖。(当我不得不使用旧版本的Pervasive时遇到了这个问题。)
但!您绝对应该做的是分离出数据访问层,并确保可以根据需要交换一个新的数据访问层。这样一来,您便可以使用具有所有功能的酷炫的查询生成器,但是如果您需要为有关的数据库插入使用该奇数伪SQL的新查询生成器。
我认为查询生成器的日常实用好处是代码重用和遵循DRY原理的能力。
使用查询生成器,您可以将重复的SQL部分放入方法中。然后使用这些方法来编写复杂的SQL。一个示例是例如可重用的JOIN子句:
function joinTaskWithClient($queryBuilder) {
$queryBuilder->join('task', 'contract', 'task.contract_id = contract.id')
->join('contract', 'client', 'contract.client_id = client.id');
}
因此用法是:
$queryBuilder->select('client.name')
->from('client')
->where('task.id=:task')->setParameter('task', 42);
joinTaskWithClient($queryBuilder);
您可能会注意到-与手动收集SQL字符串的情况相比,使用查询生成器可以按任何顺序添加SQL部分(例如,在WHERE后面的JOIN部分)。另外,您可以阅读有关构建器模式的信息, 以了解其目的和优势。
我同意转义和消毒,但是也可以不使用查询生成器来实现。关于数据库类型/方言抽象-这是相当理论上和可疑的好处,实际上很少使用。
我将根据我的自定义SQL构建器(方言)的自述文件提供答案
(纯文本如下,删除了特定于库的引用)
要求
特征
我认为上述功能和要求概述了使用SQL抽象生成器的原因
大多数SQL构建器都支持上述大多数功能(尽管据我所知,我不认为所有列出的功能都受支持)
用例示例:
最后,我有一个用例的例子。我正在构建一个应用程序,其中基础数据库模式(wordpress)不适合需要完成的数据查询类型,另外还必须使用一些WP表(例如,帖子)(因此具有全新的表)所有应用程序数据都不是一种选择)。
在那种情况下,能够创建类似MVC的应用程序,在其中可以通过自定义/动态条件查询模型,这使得查询硬编码几乎是一场噩梦。想象一下,必须支持使用联接查询多达2-3个表,并过滤条件以查看将哪个表与哪些表联接,并且还要照顾所需的别名等等。
显然,这是一个查询抽象用例,而且,它甚至需要(或至少从中受益)具有定义自定义软视图 (联合表的集合,就好像它们是适合该模型的一个自定义表)的能力。 。然后,它变得更加容易,清洁,模块化和灵活。在另一方面,应用程序(代码)还使用查询抽象层作为(数据库模式)规范化工具。有人说,这是面向未来的。
如果明天人们决定需要一些额外的选项或数据,则很容易将它们添加到模型中几行就可以了,并且可以正常工作。另外,如果明天人们决定不再使用wordpress(因为应用程序松散地耦合到wordpress作为插件),那么在几行中更改(只是定义)模型也相对容易代码以适应新的架构。
明白了吗?
通常,这些查询的某些参数确实是某些值而不是常量。现在,它们中的许多基本上已从用户表单帖子中派生。因此,SQL注入攻击有很多可能性。因此,固有的查询格式确实需要完全验证。
现在,这并不是说我们不信任开发人员,但是查询的形成可能很容易,但是在所有地方重复所有可能的验证检查可能只是意味着您有时可能会偶然错过或修改查询,但不修改查询但不要不会更新验证检查。一些新手甚至可能知道错过这一点的所有危险。因此,查询构建器的抽象是非常必要的。
我曾经以为查询生成器是GUI应用程序,可让您在后台生成SQL时选择表并以图形方式进行联接,但现在我知道您也将查询生成器称为API,这些API提供了不必创建纯SQL查询的方式,让您自己抽象出SQL风格的潜在差异。
使用这样的查询生成器是很好的,但是我倾向于认为严重依赖它们的人通常不会问DBA:“嘿,这是我经常使用的查询,请从中创建一个视图”。
不要误会我的意思。
我认为您应该针对视图而不是针对表编写查询。不是出于安全或过滤的考虑,这是有充分理由的,但是出于相同的原因,您应该针对接口而不是针对具体类进行编码:解耦。视图就像“合同”,在OOP中,界面就像“合同”一样。您可以更改基础表,但是只要您强制视图对程序员显示相同的“契约”,代码就不会中断。
同样,不要误会我的意思,您可以使用查询生成器查询视图,但是许多视图作为一个迁移过程而存在,这是必须编写查询并询问您的DBA的产物:“请创建这个,请” 。
我是否认为通过不编写查询无法检测到创建某些视图的需要是错误的吗?
令我担心的另一件事是,新手程序员不必掌握SQL,这是人类创造的最精美的技术之一。