SQL动态查询检查是否为空或空字符串参数

时间:2019-01-03 23:12:02

标签: sql-server stored-procedures

我正在编写一个将从SSRS报告执行的存储过程。它接收2个参数:SourceID和ConfirmationNumber,但不适用于我正在运行的所有测试

this returns recs:[dbo].[GetParkingPaymentInformation] 'PARC', ''
this does not return recs:[dbo].[GetParkingtPaymentInformation] 'PARC', NULL
this does not return recs:[dbo].[GetParkingPaymentInformation] '', '002077770'
this does not return recs:[dbo].[GetParkingPaymentInformation] NULL, '002077770'
this does return recs:[dbo].[GetParkingPaymentInformation] 'PARC', '002077770'

我希望sp在一个或另一个参数为null或空白时起作用。

这是我到目前为止要编写的代码:

SET @s_SQL = 'SELECT d.ID, d.TransactionNumber, h.SourceType, ' + @s_ColumnName + ', d.FirstName, d.LastName,' +    
                 'LTRIM(RTRIM(d.FirstName)) + '' '' + LTRIM(RTRIM(d.LastName)) [Name], '+ 
                 'd.PaymentAmount,  CONVERT(VARCHAR(10), CAST(d.InitiationDate AS DATE), 101) [InitiationDate]' +
                 ', d.Fee, d.TotalAmount,   d.PaymentStatus, d.PaymentType, d.CreditCardType, ' +
                 'CONVERT(VARCHAR(10), CAST(d.PaymentEffectiveDate AS DATE), 101) [PaymentEffectiveDate]' + 
                 ', CONVERT(VARCHAR(10), CAST(d.ProcessDate AS DATE), 101) [ProcessDate], CONVERT(VARCHAR(10), CAST(d.CreatedDate AS DATE), 101) [CreatedDate],' +
                 'd.CashCode, d.TransConfirmID' +
                 ', d.Phone, d.StreetAddress1, d.StreetAddress2, ' +
                 'LTRIM(RTRIM(d.StreetAddress1)) + '' '' + CASE WHEN LEN(d.StreetAddress2) > 0 THEN LTRIM(RTRIM(d.StreetAddress2)) ELSE '''' END [Address]' +
                 ', d.City, d.[State],  d.ZipFive,  d.ZipFour,  d.Email ' +
                 'FROM '+ @s_TableHeader + ' h WITH (NOLOCK) ' + 
                 'INNER JOIN ' + @s_TableDetail + ' d WITH (NOLOCK) ' +
                 'ON h.ID = d.headerID ' +
                 'WHERE' +
                 '  ((h.sourcetype = ' + '''' + @s_Source_Type + '''' + ') OR ' + '''' + @s_Source_Type + '''' + ' IS NULL OR ' + '''' + @s_Source_Type + '''' + '= '''')' +
                 '  AND ((d.transconfirmid = ' + '''' + @s_Confirmation_Number + '''' + ') OR ' + '''' + @s_Confirmation_Number + '''' + ' IS NULL OR ' + '''' + @s_Confirmation_Number + '''' + '= '''')'

任何帮助,我都可以弄清楚为什么我的支票无法正常工作,那太好了。

2 个答案:

答案 0 :(得分:0)

**请注意,您的示例sql代码不完整,并且您命名的参数与变量名称略有不同,这使得难以理解问题。 *

即使在可以忽略sql注入危险的情况下,也不无理由不鼓励使用动态sql。这样做的主要原因之一是动态sql难以编写,读取和调试。话虽如此,我经常发现自己使用它来解决设计不佳的系统中的问题。

我认为您已经适当研究了替代方案。

为降低动态sql语句的复杂性,我发现以模块化方式构造该语句是一种不错的策略。

在特定情况下,使用'if'语句(或某些变体)可以帮助降低动态where子句的复杂性,并可能有助于解决问题。

示例:

`

set @sql ='select ....... 您的select语句 .....在哪里

如果(@a_Source_Type不为null并且len(@a_Source_Type)> 0) 开始 设置@sql + =''''+ @a_Source_Type +'''= some_field和' 结束 其他 开始 设置@sql + ='len(isnull(some_field,``''))= 0和' 结束

设置@sql + ='1 = 1'

`

以上尝试将比较运算符移出动态sql。

我建议将查询重构为使用类似于此示例的策略,因为您可能会发现识别错误代码更容易。

已证明示例的最后一行在所生成的动态sql语句可能带有或不带有where子句的情况下很有用

答案 1 :(得分:0)

尝试将您的WHERE更改为以下内容:

'where' +  
'  h.sourcetype = ' + isnull(quotename(nullif(@s_Source_Type, ''), ''''), 'h.sourcetype') + 
'  AND d.transconfirmid = ' + isnull(quotename(nullif(@s_Confirmation_Number, ''), ''''), 'd.transconfirmid')