在SQL(动态查询)中过滤数据的最佳方法是什么?

时间:2013-11-30 07:24:53

标签: sql sql-server tsql stored-procedures

我有一个存储过程,它应该从根据提供的参数过滤的表中返回结果集。

更新

alter procedure  Proc_CheckExchange     
@Flag varchar(3),      
@symbol varchar(13)=null,        
@exchange char(3)=null,        
@limit money=null,        
@chargerate numeric(18,4)=null,        
@ChgType char(2)=null,        
@IsActive int=null,        
@Mkrid varchar(11)=null,        
@statecode varchar(4) =null    


as         
 declare @sql nvarchar(max)  

set @sql = N'select * from Tbl_StampDutyException1 where 1 = 1'  
if(@Flag='CHK')      
begin   


if len(isnull(@exchange, '')) > 0  
  set  @sql = @sql + N'and exchange=@exchange'+ cast(@exchange as nvarchar(100))  

if len(isnull(@symbol, '')) > 0  
 set   @sql = @sql + N'and symbol=@symbol'+ cast(@symbol as nvarchar(100))  

if len(isnull(@limit, '')) > 0  
 set   @sql = @sql + N'and limit=@limit'+ cast(@limit as nvarchar(100))  

if len(isnull(@chargerate, '')) > 0  
  set  @sql = @sql + N'and chargerate=@chargerate'+ cast(@chargerate as nvarchar(100))  

if len(isnull(@ChgType, '')) > 0  
 set   @sql = @sql + N'and ChgType=@ChgType'+ cast(@ChgType as nvarchar(100))  

if len(isnull(@IsActive, '')) > 0  
  set  @sql = @sql + N'and IsActive=@IsActive'+ cast(@IsActive as nvarchar(100))  

    if len(isnull(@statecode, '')) > 0  
 set   @sql = @sql + N'and statecode=@statecode'+ cast(@statecode as nvarchar(100))  



exec (@sql)  
end  

if (@Flag='ALL')      
begin    
 select * from Tbl_StampDutyException1   
end

更新1

    alter procedure  Proc_CheckExchange     
@Flag varchar(3),      
@symbol varchar(13)=null,        
@exchange char(3)=null,        
@limit money=null,        
@chargerate numeric(18,4)=null,        
@ChgType char(2)=null,        
@IsActive int=null,        
@Mkrid varchar(11)=null,        
@statecode int =null    


as         
 declare @sql nvarchar(max)  

set @sql = N'select * from Tbl_StampDutyException1 where 1 = 1'  
if(@Flag='CHK')      
begin   

  if len(isnull(@exchange, '')) > 0
    set @sql = @sql + N' and exchange = @exchange'

   if len(isnull(@limit, '')) > 0
    set @sql = @sql + N' and limit = @limit'

    if len(isnull(@chargerate, '')) > 0
    set @sql = @sql + N' and chargerate = @chargerate'

    if len(isnull(@ChgType, '')) > 0
    set @sql = @sql + N' and ChgType = @ChgType'

    if len(isnull(@IsActive, '')) > 0
    set @sql = @sql + N' and IsActive = @IsActive'

    if len(isnull(@statecode, '')) > 0
    set @sql = @sql + N' and statecode = @statecode'

    if len(isnull(@symbol, '')) > 0
    set @sql = @sql + N' and symbol = @symbol'

 declare @params as nvarchar(max) = N'@Flag varchar(3), 
@symbol varchar(13),        
@exchange char(3),        
@limit money,        
@chargerate numeric(18,4),        
@ChgType char(2),        
@IsActive int,        
@Mkrid varchar(11),        
@statecode varchar(4)'
print @sql
--EXECUTE sp_executesql @sql, @params, @Flag, @symbol, @exchange, @limit, @chargerate, @ChgType,    @IsActive, @Mkrid, @statecode

    end

我正在尝试创建一个存储过程,其中WHERE子句中的条件将与传递给存储过程的条件一样多。我希望我清楚自己要实现的目标。我收到错误Error converting data type varchar to numeric.

3 个答案:

答案 0 :(得分:1)

您可以做的是使用动态SQL重写存储过程,并且只有在定义了参数时才包含部分where子句,例如:用

代替身体
declare @sql nvarchar(max)
set @sql = N'select * from Tbl_StampDutyException1 where 1 = 1'

if len(isnull(@exchange, '')) > 0
    set @sql = @sql + N' and exchange = ' + cast(@exchange as nvarchar(100))

-- add all parameters; you need to cast them to nvarchar if they have other type

exec (@sql)

作为改进,您可以使用sp_executesql来执行动态SQL。有关如何使用它,请参阅here。在这种情况下,代码将是:

declare @sql nvarchar(max)
set @sql = N'select * from Tbl_StampDutyException1 where 1 = 1'

if len(isnull(@exchange, '')) > 0
    set @sql = @sql + N' and exchange = @exchange'

-- add all parameters;

declare @params as nvarchar(max) = N'@Flag varchar(3), 
@symbol varchar(13),        
@exchange char(3),        
@limit money,        
@chargerate numeric(18,4),        
@ChgType char(2),        
@IsActive int,        
@Mkrid varchar(11),        
@statecode varchar(4)'

EXECUTE sp_executesql @sql, @params, @Flag, @symbol, @exchange, @limit, @chargerate, @ChgType,    @IsActive, @Mkrid, @statecode

顺便说一句,不要在存储过程中使用select *,这不是一个好习惯。列出要返回的所有列。否则,如果表定义发生更改,您将获得与之前相同的结果。

答案 1 :(得分:0)

我猜您需要的是一个条件WHERE CLAUSE方法,提供了下面的示例脚本,您需要将所有IF条件转换为CASE然后您可以将所有条件组合到一个SELECT语句中:

SELECT * FROM Tbl_StampDutyException1   
WHERE 
exchange = CASE WHEN @exchange='' or @exchange is  null THEN exchange ELSE @exchange END
AND symbol = Case when @symbol='' or @symbol is  null  THEN symbol ELSE symbol   
AND *so on.....*

答案 2 :(得分:0)

我认为这是一个很好的解决方案

SELECT * from dbo.Clients
WHERE 
    (@param1 IS NULL OR field1 = @param1)
AND (@param2 IS NULL OR field2 = @param2)

使用这种方法,每次执行查询时,服务器都不会重新处理语句(执行计划)。