可能的重复:
在存储过程与代码中保留 SQL 的优缺点是什么
只是好奇使用存储过程与从数据库获取数据的其他形式的优缺点。确保速度、准确性和安全性的首选方法是什么(我们不想要 sql 注入!)。
(我应该将此问题发布到另一个堆栈交换站点吗?)
可能的重复:
在存储过程与代码中保留 SQL 的优缺点是什么
只是好奇使用存储过程与从数据库获取数据的其他形式的优缺点。确保速度、准确性和安全性的首选方法是什么(我们不想要 sql 注入!)。
(我应该将此问题发布到另一个堆栈交换站点吗?)
Stackoverflow 上有几个关于这个问题的问题。我真的不认为你会在这里得到一个“正确”的答案,两者都可以很好地工作,而且都可以工作得非常糟糕。我认为如果您使用的是 Java,那么一般模式是使用像 Hibernate/JPA 这样的 ORM 框架。只要您正确使用该框架,就可以完全避免 SQL 注入攻击。我对 .Net 开发人员的经验是,他们更有可能使用存储过程支持的持久性,但这似乎比以前更加开放。NHibernate 和其他 MS 技术似乎都越来越受欢迎。
我个人的观点是,一般来说,ORM 可以为您节省大量冗长编码的时间,因为它可以自动生成您在典型 CRUD 类型系统中使用的大部分 SQL。要获得这一点,您可能会放弃一点性能和一些灵活性。如果您的系统是中低容量(每天有成千上万个请求),那么 ORM 就可以满足您的需求。如果您开始每天处理数百万个请求,那么您可能需要一些更裸机的东西,例如直接 SQL 或存储过程。请注意,ORM 不会阻止您更直接地访问数据库,它通常不是您会使用的。
最后一点,我认为 ORM 持久性使应用程序更易于测试。如果您在大部分持久性中使用存储过程,那么您几乎肯定会开始在这些过程中获得一堆业务逻辑。要测试它们,您必须实际保存数据并与数据库交互,这使得测试变得缓慢而脆弱。使用 ORM 框架,您可以避免大部分测试,或者在您真正想要测试持久性时使用内存数据库。
看:
这在 Programmers SE 上可能会更好,但我会在这里回答。
CRUD 存储过程曾经是,有时仍然是在 SQL DBMS 上进行数据持久性和检索的最佳实践。每个这样的 DBMS 都有存储过程,因此无论编码语言和 DBMS 是什么,实际上都可以保证您能够使用该解决方案,并且使用该解决方案的代码可以指向任何具有正确存储过程的 DB,它会以最少的代码更改工作(在不同的 DBMS 中调用 SP 时需要进行一些语法更改;这些通常被集成到语言的库支持中以访问特定 DBMS 上的 SP)。也许最大的优势是集中访问表数据;您可以像 Fort Knox 一样锁定表本身,并根据需要将 SP 的访问权限分配给更有限的用户帐户。
但是,它们有一些缺点。首先,SP 很难进行 TDD,因为这些工具实际上并不存在于数据库 IDE 中;您必须在执行 SP 的其他代码中创建测试(因此测试必须使用预期的测试数据设置数据库)。从技术角度来看,这样的测试不是也不可能是“单元测试”,它是对小而窄的功能区域的小而窄的测试,它没有副作用(例如读取/写入文件系统) )。此外,SP 是在对功能进行所需更改时必须更改的另一层。向查询结果添加新字段需要更改表、检索源代码和 SP. 添加新方法来搜索特定类型的记录需要创建和测试语句,然后封装在 SP 中,并在 DAO 上创建相应的方法。
可用的新最佳实践 IMO 是一个称为对象关系映射器或 ORM 的库。ORM 抽象了实际的数据层,因此您需要的是代码对象本身,并且您根据这些对象的属性而不是表数据来查询它们。这些查询几乎总是代码可配置的,并根据您在对象模型和数据模型之间定义的一个或多个“映射”转换为 DBMS 的 SQL 风格(类型 A 的对象作为记录保存在表 B 中,该属性 C 被写入字段 D)。
优点是代码更灵活,实际上以这些代码对象的形式查找数据。查询的条件通常可以在代码中自定义;如果需要具有不同 WHERE 子句的新查询,您只需编写查询,ORM 会将其转换为新的 SQL 语句。因为 ORM 是唯一实际使用 SQL 的地方(并且大多数 ORM 使用系统存储的过程来执行可用的参数化查询字符串)注入攻击几乎是不可能的。最后,根据语言和 ORM,可以对查询进行编译器检查;在 .NET 中,可以使用一个名为 Linq 的库,它提供 SQL 风格的关键字语法,然后将其转换为方法调用,然后将其提供给“查询提供程序”,该“查询提供程序”可以将这些方法调用转换为数据存储。s 本机查询语言。这也允许在代码中测试查询;您可以验证所使用的查询是否会在给定代表实际 DBMS 的内存对象集合的情况下产生所需的结果。
ORM 的缺点是 ORM 库通常是特定于语言的;Hibernate 可以在 Java 中使用,NHibernate(以及 L2E 和 L2SQL)在 .NET 中,以及一些类似的库,如 PHP 中的 Pork,但是如果您使用更旧或更深奥的语言进行编码,则根本没有可用的类型。另一个是安全性变得有点棘手。大多数 ORM 需要直接访问表才能查询和更新它们。一些人会容忍被指向用于检索的视图和用于更新的 SP(允许分离视图/SP 和表安全性以及限制可检索字段的能力),但现在您正在混合两全其美;您仍然必须定义映射,但现在您在数据层中也有代码。克服这个问题的最简单方法是在其他地方实施您的安全性;强制应用程序使用 Web 服务获取数据,该服务使用 ORM 提供数据并具有特定的、有限的“前门”。此外,许多 ORM 在以某些方式使用时会出现一些性能问题;大多数设计用于“延迟加载”数据,在实际需要数据的那一刻而不是之前检索数据,当您不需要您要求的每条记录时,这会提高前期性能。但是,当您确实需要您要求的每条记录时,这会产生额外的往返行程。您必须以特定方式构建查询来绕过这种预期的用例行为。在实际需要数据的那一刻而不是之前检索数据的位置,当您不需要您要求的每条记录时,这会提高前期性能。但是,当您确实需要您要求的每条记录时,这会产生额外的往返行程。您必须以特定方式构建查询来绕过这种预期的用例行为。在实际需要数据的那一刻而不是之前检索数据的位置,当您不需要您要求的每条记录时,这会提高前期性能。但是,当您确实需要您要求的每条记录时,这会产生额外的往返行程。您必须以特定方式构建查询来绕过这种预期的用例行为。
哪个更好?你必须做出决定。我现在可以告诉你,使用 ORM 比 SP 更容易设置和正常工作,并且更容易对模式和查询进行更改(并限制范围)。在现代开发公司中,首要任务是使其首先工作,然后使其表现良好和/或防止入侵,这是一个巨大的优势。在大多数情况下,您认为安全是一个问题,其实不是,当安全确实是一个问题时,将解决方案放在 DB 层通常是错误的,因为 DBMS 是最后一道防线防止入侵;如果必须依靠 DBMS 本身来阻止不想要的事情发生,那么您在它上面的许多软件和固件层中都没有这样做(甚至鼓励它发生)。
根据所有数据库问题的答案“取决于”。但是,由于计划缓存,存储过程在速度方面肯定会有所帮助(尽管正确参数化的 SQL 也会从中受益)。准确性也不例外——不正确的查询无论是否在存储过程中都是不正确的。在安全性方面,它们可以提供一种有用的方式来限制用户的访问——因为您不需要让他们直接访问基础表——您可以只允许他们执行您想要的存储过程。然而,关于这个话题有很多很多问题,我建议你搜索一下并找出更多。