我正在编写一个将从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 + '''' + '= '''')'
任何帮助,我都可以弄清楚为什么我的支票无法正常工作,那太好了。
答案 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')