以一个简单的查询存储过程为例,简单说一下sql的几种写法

最近发现还有不少做开发的小伙伴 , 在写存储过程的时候 , 在参考已有的不同的写法时 , 往往很迷茫 , 
不知道各种写法孰优孰劣 , 该选用哪种写法 , 以及各种写法的优缺点 , 本文以一个简单的查询存储过程为例 , 简单说一下各种写法的区别 , 以及该用那种写法
专业DBA以及熟悉数据库的同学请无视 。
废话不多说 , 上代码说明 , 先造一个测试表待用 , 简单说明一下这个表的情况
类似订单表 , 订单表有订单ID , 客户ID , 订单创建时间等 , 查询条件是常用的订单ID , 客户ID , 以及订单创建时间
create table SaleOrder(idint identity(1,1),OrderNumberint,CustomerIdvarchar(20),OrderDatedatetime,Remarkvarchar(200))GOdeclare @i int=0while @i<100000begininsert into SaleOrder values (@i,CONCAT('C',cast(RAND()*1000 as int)),GETDATE()-RAND()*100,NEWID())set @i=@i+1endcreate index idx_OrderNumber on SaleOrder(OrderNumber)create index idx_CustomerId on SaleOrder(CustomerId)create index idx_OrderDate on SaleOrder(OrderDate)生成的测试数据大概就是这个样子的

以一个简单的查询存储过程为例,简单说一下sql的几种写法

文章插图
 
下面演示说明几种常见的写法以及每种写法潜在的问题
更多linux内核视频教程文本资料免费获取后台私信【内核】 。
以一个简单的查询存储过程为例,简单说一下sql的几种写法

文章插图
 

以一个简单的查询存储过程为例,简单说一下sql的几种写法

文章插图
 
第一种常见的写法:拼凑字符串 , 用EXEC的方式执行这个拼凑出来的字符串 , 不推荐
以一个简单的查询存储过程为例,简单说一下sql的几种写法

文章插图
 
create proc pr_getOrederInfo_1(@p_OrderNumberint,@p_CustomerIdvarchar(20) ,@p_OrderDateBegindatetime,@p_OrderDateEnddatetime)asbeginset nocount on;declare @strSql nvarchar(max);set @strSql= 'SELECT [id],[OrderNumber],[CustomerId],[OrderDate],[Remark]FROM [dbo].[SaleOrder] where 1=1 ';/*这种写法的特点在于将查询SQL拼凑成一个字符串 , 最后以EXEC的方式执行这个SQL字符串*/if(@p_OrderNumber is not null)set @strSql = @strSql + ' and OrderNumber = ' + @p_OrderNumberif(@p_CustomerId is not null)set @strSql = @strSql + ' and CustomerId= '+ ''''+ @p_CustomerId + ''''if(@p_OrderDateBegin is not null)set @strSql = @strSql + ' and OrderDate >= ' + '''' + cast(@p_OrderDateBegin as varchar(10)) + ''''if(@p_OrderDateEnd is not null)set @strSql = @strSql + ' and OrderDate <= ' + '''' + cast(@p_OrderDateEnd as varchar(10)) + ''''print @strSqlexec(@strSql);end假如我们查询CustomerId为88 , 在2016-10-1至2016-10-3这段时间内的订单信息 , 如下 , 带入参数执行
exec pr_getOrederInfo_1@p_OrderNumber= null,@p_CustomerId= 'C88',@p_OrderDateBegin= '2016-10-1' ,@p_OrderDateEnd= '2016-10-3'首先说明 , 这种方式执行查询是完全没有问题的如下截图 , 结果也查出来了(当然结果也是没问题的)
以一个简单的查询存储过程为例,简单说一下sql的几种写法

文章插图
 
我们把执行的SQL打印出来 , 执行的SQL语句本身就是就是存储过程中拼凑出来的字符串 , 这么一个查询SQL字符串
SELECT [id],[OrderNumber],[CustomerId],[OrderDate],[Remark]FROM [dbo].[SaleOrder] where 1=1and CustomerId= 'C88'and OrderDate >= '2016-10-1'and OrderDate <= '2016-10-3'那么这种存储过程的有什么问题 , 或者直接一点说 , 这种方式有什么不好的地方
其一 , 绕不过转移符(以及注入问题)
在拼凑字符串时 , 把所有的参数都当成字符串处理 , 当查询条件本身包含特殊字符的时候 , 比如 ' 符号 , 
或者其他需要转义的字符时 , 你拼凑的SQL就被打断了
举个不恰当的例子 , 比如字符串中 @p_CustomerId中包含 ' 符号 , 直接就把你拼SQL的节凑给打乱了
拼凑的SQL就变成了这个样子了 , 语法就不通过 , 更别提执行
SELECT [id],[OrderNumber],[CustomerId],[OrderDate],[Remark]FROM [dbo].[SaleOrder]where 1=1and CustomerId= 'C'88'


推荐阅读