作为参数参数值的串联字符串不提供存储过程

时间:2015-06-15 08:03:46

标签: sql-server sql-server-2008

我正在使用SQL SERVER 2008管理工作室 我有一个存储过程,它接受几个参数 一个参数名称为@recvemail,默认值为'B' 如果@recvemail的值为'Y',那么选择电子邮件新闻信的所有用户都应显示在输出中。
如果@recvemail'N',则不希望收到电子邮件信函的用户应包含在输出中。
如果值为'B',则应在输出中显示所有用户, 他们是否选择了新闻信或者没有选择新闻信。

现在对于默认值'B',我尝试将参数参数值设置为'Y''N',但我没有得到任何输出。

我的存储过程是

Create procedure [dbo].[proc_getMembershipEmailbackup] 
-- exec proc_getMembershipEmail @From=N'1991-06-11',@To=N'2017-06-14',@DevoteeName=N'',@MembershipName=N'Membership Life',@log_cond=N'',@recvemail=N'N'

@From varchar(10),                                      
@To varchar(10),                                      
@DevoteeName varchar(60)='',   
@MembershipName varchar(100)='ALL',           
@Email varchar(50)= '',                             
@Phoneno varchar(50)= '',  
@MinAmount decimal =Null,    
@MaxAmount decimal =NULL,  
@log_cond Varchar(5), 
@recvemail char(61)='B' 

As   
Begin     
    if @recvemail = 'B'  
    Begin  
      Set @recvemail='Y' + ',' + 'N'  
    End  
end                  
Begin     
    if @MembershipName = 'ALL'  
    Begin  
        Set @MembershipName=''  
    End  
end
begin

select 
            ROW_NUMBER() over (order by mu.f_name) as [No],
            mu.f_name  +' '+mu.l_name  as DevoteeName ,  
            mu.pers_email as Email,  
            mu.home_phone as PhoneNo,
            mp.name as MembershipName, 
            mu.recv_email as optedforemail,
            d1.memb_id ,  
            d1.amt_due as amount_due,  
            CONVERT(varchar(10),d1.nextduedate,101) as duedate,  
            d1.pay_term


from d_user_memb d1   
            left join m_user mu on d1.user_id = mu.user_id  
            left join m_memb_pledge mp on d1.memb_id = mp.memb_id   
where  
            d1.status in ('A','D','C')
            AND(Isnull(@From,'') = '' or CONVERT(date,d1.nextduedate ) >=  CONVERT(date,@From) )              
            and  (Isnull(@To,'') = '' or CONVERT(date,d1.nextduedate ) <= CONVERT(date,@To ))             
            and  (Isnull(@DevoteeName,'') = '' or (f_name +' '+l_name) like '%' + @DevoteeName + '%')
            and (recv_email in (@recvemail ) )
            and (Isnull(@MembershipName,'') = '' or (mp.name) = @MembershipName)     
            and (ISNULL (@Email, '') = '' or mu.pers_email = @Email)    
            and (ISNULL (@Phoneno, '') = '' or mu.home_phone = @Phoneno) 

            --and (ISNULL (@MinAmount,0) = 0 or cast(d1.amt_due as decimal(10,2)) >=@MinAmount)  
            --and (ISNULL (@MaxAmount, 0) =0 or cast(d1.amt_due as decimal(10,2)) <= @MaxAmount)  
            and d1.amt_due<>0  
            and mu.status='A'  
            and (    
    (    
     @log_cond = 'b'     
     AND d1.amt_due BETWEEN @MinAmount AND @MaxAmount    
    )        
    OR     
    (    
     @log_cond <> 'b'     
     AND @log_cond <> '0'            
     AND      
     (    
      isnull(@log_cond,'')=''         
      OR (@log_cond = '>' AND d1.amt_due > @MinAmount)        
      OR (@log_cond = '<' AND d1.amt_due < @MinAmount)   
      OR (@log_cond = '>=' AND d1.amt_due >= @MinAmount)        
      OR (@log_cond = '<=' AND d1.amt_due <= @MinAmount)          
      OR (@log_cond='=' AND d1.amt_due =@MinAmount)    
     )        
    )        
    OR        
    (    
     ISNULL(@log_cond,'')='0'         
    )        
   )

End  

我尝试使用这样的值执行该过程,但我没有得到任何输出

use CHTLIVE
GO
exec proc_getMembershipEmailbackup  @From=N'1800-06-11',@To=N'2099-06-14',@DevoteeName=N'',@log_cond='', @recvemail='B'

如果将参数值@recvemail'B'更改为'Y',我将正确输出,并且所有选择了电子邮件的用户都会在输出中正确显示。
同样,我将值从'B'更改为'N'我正确获取输出,并且所有未选择电子邮件的用户都会显示在输出中。
仅用于值'B'我没有获得输出。我应该得到输出,以便所有选择或不选择电子邮件的用户都应该出现在输出中。

2 个答案:

答案 0 :(得分:2)

正如Mark Sinkinsonhis comment中写的那样,IN()运算符需要逗号分隔的参数列表,但是您为它提供了一个包含逗号分隔值列表的参数。

更改存储过程的这一部分:

and (recv_email in (@recvemail ) )

到此:

and (recv_email = @recvemail OR @recvemail = 'B')

答案 1 :(得分:2)

该行

and (recv_email in (@recvemail ) )

相当于

and recv_email = @recvemail 

IN适用于只传递单个参数的参数列表。它不解析参数的内容,以查看它们中的任何一个是否可以解释为以逗号分隔的列表。

如果要检查选项列表,请创建一个表值参数并在IN子句中使用它:

declare @emailoptions table (Option varchar(2))

IF (@recvemail = 'B'  OR @recvemail = 'Y')
begin
    insert into @emailoptions VALUES('Y')
end if
IF (@recvemail = 'B'  OR @recvemail = 'N')
begin
    insert into @emailoptions VALUES('N')
end if

这将允许您使用@emailOptions

联合您的表
from d_user_memb d1   
    left join m_user mu on d1.user_id = mu.user_id  
    left join m_memb_pledge mp on d1.memb_id = mp.memb_id   
    inner join @emailOptions on Option=@recvc_email    

这允许您使用两个以上的选项,优化器将能够使用包含recv_email的任何索引来创建更快的执行计划。