SQL Server如何在IN条件时使用参数查询

作者:翅膀的初衷 来源:本站原创 发布时间:2015-01-16 查看数:10457

常规情况下,如果使用IN条件查询数据时,应避免使用参数化查询,类于如下代码

select * from my_user where userid in (1,2,3)

您应该直接拼成上图格式,而不是这么写:

set @idstr = '1,2,3'
select * from my_user where userid in (@idstr)

原因是系统会认为你要的代码是 userid in ('1,2,3') 而不是你预期的 userid in (1,2,3)

但是有时,我们却遇某些特殊情况,必须在有参数的情况下使用in,怎么办?

场景一:我有一个存储过程,数据传进来本来就是参数,而我也必须使用in来查询。

很多朋友图简单,直接使用字符串相拼,再使用exec 执行。这方法是可行的,但是却存在安全漏洞,而且有某些特殊情况下,是无法使用exec的。

场景二:我有一个存储过程,数据传进来本来就是参数,而我也必须使用in来查询。而且业务逻辑很复杂,要使用使局部临时表,在包含in的语句中也要进行临时表操作,之外也要进行临时表操作。那么在这种情况下,如果你直接exec,你会发现exec里面的SQL语句,无法访问外面的语句创建的临时表。

还好,在sql server 2008中,开始支持表值函数,我们可以自己分隔字符,通过表值函数,返回数据表即可。

定义

表值函数返回 table。对于内嵌表值函数,没有函数主体;表是单个 SELECT 语句的结果集。对于多语句表值函数,在 BEGIN...END 块中定义的函数主体包含 TRANSACT-SQL 语句,这些语句可生成行并将行插入将返回的表中。

语法

CREATE FUNCTION [ owner_name.] function_name
( [ { @parameter_name [AS] scalar_parameter_data_type [ = default ] } [ ,...n ] ] )
RETURNS table
[ WITH {Encryption | Schemabinding }]
[ AS ]
RETURN( select 语句)

那么,在场景二的T-SQL,那么就可以这么写了:先创建一个表值函数

Create FUNCTION  Split
( 
  @SplitString nvarchar(max), 
  @Separator char(1)=',' 
) 
RETURNS @SplitStringsTable TABLE 
( 
 [value] varchar(max) 
) 
AS 
BEGIN 
  DECLARE @CurrentIndex int; 
  DECLARE @NextIndex int; 
  DECLARE @ReturnText nvarchar(max); 
  SELECT @CurrentIndex=1; 
  WHILE(@CurrentIndex<=len(@SplitString)) 
  BEGIN 
    SELECT @NextIndex=charindex(@Separator,@SplitString,@CurrentIndex); 
    IF(@NextIndex=0 OR @NextIndex IS NULL) 
    SELECT @NextIndex=len(@SplitString)+1; 
    SELECT @ReturnText=substring(@SplitString,@CurrentIndex,@NextIndex-@CurrentIndex); 
    INSERT INTO @SplitStringsTable([value]) VALUES(@ReturnText); 
    SELECT @CurrentIndex=@NextIndex+1; 
  END 
  RETURN; 
END 

然后调用它就可以了

select * from jn_user where userid in (SELECT value FROM Split(@idsrt))