在我跟SQL Server打交道的6年中,对于某些任务而言是选择存储过程还是动态生成的SQL字符串,一直以来都争论不休。 当我们有一个相对修改较少或者很容易把参数包含在存储过程的语法中的函数时,存储过程是很有用的。另外一方面,动态SQL则通常是一个快速解决的工作。同时,它也被用于处理几乎需要整体从头开始组装的事务;比如,一大堆不同的参数、正在被查询的表单等等都会根据语句的不同而发生变化。
但是,即使这样,存储过程仍然是适和的,并且就长期而言,它是一个较好的选择。 规则 大多数SQL Server程序员尝试将代码整合到存储过程是基于以下几个原因的。 性能。这是一个“众所周知”的事实……
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
在我跟SQL Server打交道的6年中,对于某些任务而言是选择存储过程还是动态生成的SQL字符串,一直以来都争论不休。
当我们有一个相对修改较少或者很容易把参数包含在存储过程的语法中的函数时,存储过程是很有用的。另外一方面,动态SQL则通常是一个快速解决的工作。同时,它也被用于处理几乎需要整体从头开始组装的事务;比如,一大堆不同的参数、正在被查询的表单等等都会根据语句的不同而发生变化。但是,即使这样,存储过程仍然是适和的,并且就长期而言,它是一个较好的选择。
规则
大多数SQL Server程序员尝试将代码整合到存储过程是基于以下几个原因的。
性能。这是一个“众所周知”的事实,但是,还是需要不断强调。存储过程的缓存和重用比动态SQL更有效率。虽然,对于存储过程的速度仍然有着争议,但是,毫无疑问,在大型的多用户应用中,它们显示出更好的性能。
一致性。作为一名程序员,调用一个可以在多个上下文使用的存储过程要比在不同的地方重写相同的SQL字符串(这样做可能还会出现错误)要简单得多。同时,这也使得在整个大型的应用中增量的更新代码也容易得多;相关的存储过程引用可以更容易地进行修改。而要在整个应用中替换一个动态生成的SQL代码段的所有的实例是很难做到的,没有人愿意这样做。
安全性。存储过程可以通过一种方法来在某些函数上实现细粒度的安全性,特别是当我们的数据库在同一时间被多个的应用使用时。动态生成SQL语句实际上并不“归属于”任何人——唯一的有效权限就是用于运行它们的用户上下文——因此,它们很难确保安全性。
异常。有些人使用动态SQL而不是存储过程是有原因的。然而,经过仔细观察,他们的决定是源于他们并不知道现在有多少T-SQL函数可以产生相同的效果。
快速部署。这个可能是使用动态SQL最常见的理由。在一个指定的应用上下文中,比起在后台开发一个存储过程,创建一个SQL字符串并将它传输到SQL Server可以更简单和更快速。
问题在于,如果这个快速的方法遍布整个应用——或者变得越来越大。原本只是完成事务的一个简便的方法,结果转变为一个长期维护的噩梦。就长期而言,任何需要发送多个查询的应用都必须由可管理的存储过程替代。
在多数据库或者表上工作。我常看到的另外一个使用(滥用)动态SQL的情况是,创建一系列的T-SQL语句,其中每一个都针对不同表或者数据库。另外一个处理多数据库的方法是使用微软的存储过程:sp_MSforeachdb,它可以接受一个T-SQL语句作为参数并且在我们所连接的SQL Server实例上的每个数据库上运行该语句。由于过程本身是非正式文档化的,并且在某个时刻终止退出或者停止工作,因此这并不是一个好的解决方法。
将字段或者表单作为参数传递。有些语句根本不适合在一个存储过程中实现。比如,将一个字段或者表名称作为参数(或者参数的一部分)传输给一个SQL,这在存储过程的上下文中是不允许的。
解决这个问题的一个可行的方法是,创建一个存储过程并封装EXEC sp_executesql语句。本质上,就是使用一个存储过程来生成动态SQL。这甚至可以用来动态地创建一个只在所需的特定表或者字段上工作的存储过程,因此,它可以在将来重用。然而,其中一个风险是,如果我们没有事先整理好数据,那么它可能成为SQL注入式攻击的载体。
很多涉及动态传输参数的环境都可以在存储过程的上下文中进行处理。一个类似的情况是使用动态排序关键字,其中被传输的参数将被用在一个ORDER BY语句中。如果可能的参数数量是相对较少的,那么我们可以简单地使用一个ORDER BY CASE语句和参数来进行彻底的处理。如果我们想传输一个参数来选择一个查询的TOP n行记录,那么我们可以使用存储过程上下文中的SET ROWCOUNT来实现完全相同的效果。
我必须指出的一点是,如果你总是发现自己被迫需要传递表名称或者字段名称作为参数,那么真正的问题可能并不是SQL Server的局限性,而是数据设计并不满足你的实际要求。情况并不总是这样,但是它经常出现,因此,你可能得仔细地查看下你的数据库模式是如何创建的,以便确保不是设计上的问题。不要陷入设计糟糕的数据库的泥潭中,也不要想让它完成根本不可能实现的工作。
作者
Serdar Yegulalp从1994年到2001年为Windows杂志写作,覆盖了广泛的技术方面。他现在是《The Windows 2000 Power Users Newsletter》一书的出版者,辛勤钻研他擅长的Windows NT, Windows 2000 and Windows XP领域,并为TechTarget写专栏。
翻译
TechTarget中国特约技术编辑,某高校计算机科学专业教师和网络实验室负责人,曾任职某网络国际厂商,关注数据中心、开发运维、数据库及软件开发技术。有多本关于思科数据中心和虚拟化技术的译著,如《思科绿色数据中心建设与管理》和《基于IP的能源管理》等。
相关推荐
-
云端SQL Server高可用性最佳做法
与内部部署相比,在云端运行SQL Server可为数据库软件用户提供更多的灵活性和可扩展性,也可能更省钱。但云 […]
-
绘制数据关系图的利器:SQL Server 图像数据库工具
SQL Server 2017新增了图形数据库功能,你可以使用图结构来表示不同数据元素之间的关系。
-
如何在Azure部署时选择合适的SQL Server?
想要在Azure上运行SQL Server,企业一般会面临两种选择:在Azure虚拟机上安装SQL Server或使用Azure SQL Database。
-
Linux支持的引入 推动了SQL Server 2016集成服务的发展
随着SQL Server的不断发展,集成服务也在发生相应的变化。在最新的SSIS更新中,增加Linux支持和SQL Server 2016升级向导。