SQL Server 2008动态SQL中能否给单个参数传入多个字符串?
问题解答:SQL Server 2008中传入多字符串参数结合LIKE使用
当然可行,但你当前的写法存在问题——直接把逗号分隔的@Portfolio参数塞进LIKE子句里,只会匹配完全等于这个长字符串的Portfolio字段值,而不是匹配其中任意一个子项。比如你写的Tgt_DO.Portfolio like 'Treasury Investment,CASH,Derivatives,Wholesale Funding',只会找出Portfolio字段恰好是这个完整逗号串的记录,显然不符合你的预期。
下面给你两种适配SQL Server 2008的解决方案(因为2008没有内置的STRING_SPLIT函数):
方法1:自定义表值拆分函数
先创建一个拆分逗号分隔字符串的函数,之后在动态SQL里调用它来匹配多个子项:
-- 创建拆分函数 CREATE FUNCTION dbo.SplitString ( @InputString NVARCHAR(MAX), @Delimiter NVARCHAR(5) ) RETURNS @OutputTable TABLE (Value NVARCHAR(100)) AS BEGIN DECLARE @StartIndex INT, @EndIndex INT SET @StartIndex = 1 -- 确保字符串末尾有分隔符,避免漏拆最后一项 IF SUBSTRING(@InputString, LEN(@InputString), 1) <> @Delimiter BEGIN SET @InputString = @InputString + @Delimiter END WHILE CHARINDEX(@Delimiter, @InputString) > 0 BEGIN SET @EndIndex = CHARINDEX(@Delimiter, @InputString) INSERT INTO @OutputTable(Value) SELECT SUBSTRING(@InputString, @StartIndex, @EndIndex - @StartIndex) SET @InputString = SUBSTRING(@InputString, @EndIndex + 1, LEN(@InputString)) END RETURN END GO
然后修改你的动态SQL代码,用EXISTS结合拆分后的子项做匹配(如果是精确匹配就把LIKE '%...%'改成= s.Value):
Declare @AsOfDate varchar(10) Declare @PID varchar(5) Declare @Portfolio varchar(200) -- 建议放大长度,避免截断 Declare @sqlCommand varchar(max) Set @AsOfDate = '04/30/2018' Set @Portfolio = 'Treasury Investment,CASH,Derivatives,Wholesale Funding' Set @PID = 'I.A.6' -- 构建动态SQL,注意转义单引号避免语法错误 SET @sqlCommand = ' SELECT * -- 替换成你实际需要查询的字段 FROM Tgt_DO WHERE Tgt_DO.PID = ''' + @PID + ''' AND Tgt_DO.AsOfDate = ''' + @AsOfDate + ''' AND EXISTS ( SELECT 1 FROM dbo.SplitString(''' + REPLACE(@Portfolio, '''', '''''') + ''', '','') s WHERE Tgt_DO.Portfolio LIKE ''%'' + s.Value + ''%'' -- 模糊匹配,精确匹配用= s.Value )' -- 执行动态SQL EXEC(@sqlCommand)
方法2:用XML拆分(无需自定义函数)
如果不想创建函数,可以直接在动态SQL里用XML来拆分字符串,省去创建函数的步骤:
Declare @AsOfDate varchar(10) Declare @PID varchar(5) Declare @Portfolio varchar(200) Declare @sqlCommand nvarchar(max) -- 用nvarchar适配sp_executesql Set @AsOfDate = '04/30/2018' Set @Portfolio = 'Treasury Investment,CASH,Derivatives,Wholesale Funding' Set @PID = 'I.A.6' -- 用参数化动态SQL更安全,避免SQL注入 SET @sqlCommand = N' SELECT * FROM Tgt_DO WHERE Tgt_DO.PID = @PID AND Tgt_DO.AsOfDate = @AsOfDate AND EXISTS ( SELECT 1 FROM ( SELECT LTRIM(RTRIM(Split.a.value(''.'', ''VARCHAR(100)''))) AS Value FROM ( SELECT CAST(''<M>'' + REPLACE(@Portfolio, '','', ''</M><M>'') + ''</M>'' AS XML) AS Data ) AS A CROSS APPLY Data.nodes(''/M'') AS Split(a) ) s WHERE Tgt_DO.Portfolio LIKE ''%'' + s.Value + ''%'' )' -- 执行参数化动态SQL EXEC sp_executesql @sqlCommand, N'@PID varchar(5), @AsOfDate varchar(10), @Portfolio varchar(200)', @PID = @PID, @AsOfDate = @AsOfDate, @Portfolio = @Portfolio
重要提示
- 优先用参数化动态SQL(比如
sp_executesql),不要直接拼接字符串,能有效避免SQL注入风险,同时提升查询性能。 - 如果
Portfolio字段是精确匹配,把LIKE '%' + s.Value + '%'改成= s.Value即可,效率更高。
内容的提问来源于stack exchange,提问作者ASH
相关产品推荐
相关产品推荐

