假设我有下表(TestTable):
ID,SystemID,UserID (所有列的类型均为int)
我想编写一个应该接受字符串参数的存储过程;它的值如((5和6)或7)可返回应用以下查询的所有用户:
Select * From TestTable Where SystemID = 5
Intersect
Select * From TestTable Where SystemID = 6
以上结果是 union 与
Select * From TestTable Where SystemID = 7
SP必须接受任何组合,例如(((4或5)和6)或8),(((5或9)或8)和10) ..等等
我该如何实现?
更新:我的问题不是如何拆分字符串..但是如何让动态sql实现它的逻辑意义
答案 0 :(得分:1)
DECLARE @param NVARCHAR(MAX) = N'4 or 5 and 6 or 8 and 10';
DECLARE
@sql NVARCHAR(MAX) = N'',
@q NVARCHAR(MAX) = N'SELECT UserID FROM dbo.TestTable WHERE SystemID = ';
SELECT @sql = @q + REPLACE(REPLACE(@param, ' or ', '
UNION ALL ' + @q),
' and ', '
INTERSECT ' + @q);
PRINT @sql;
-- EXEC sp_executesql @sql;
结果:
SELECT UserID FROM dbo.TestTable WHERE SystemID = 4
UNION ALL SELECT UserID FROM dbo.TestTable WHERE SystemID = 5
INTERSECT SELECT UserID FROM dbo.TestTable WHERE SystemID = 6
UNION ALL SELECT UserID FROM dbo.TestTable WHERE SystemID = 8
INTERSECT SELECT UserID FROM dbo.TestTable WHERE SystemID = 10
现在,无论这个查询是否产生您实际效果的结果,我都不知道,但我相信它符合上述要求。
答案 1 :(得分:-1)
试试这个......我几乎没有改变Aaron Bertrand的询问。
DECLARE @param NVARCHAR(MAX) = N'(((4 or 5) and 6) or 8)';
DECLARE @sql NVARCHAR(MAX) = N'',
@q NVARCHAR(MAX) = N'SELECT * FROM dbo.TestTable WHERE SystemID = ',
@paranth NVARCHAR(100) = substring(@param,0,PATINDEX('%[0-9]%',@param));
set @param =substring(@param,PATINDEX('%[0-9]%',@param),len(@param)-PATINDEX('%[0-9]%',@param))
SELECT @sql = @q + REPLACE(REPLACE(@param, ' or ', '
UNION ALL ' + @q),
' and ', '
INTERSECT ' + @q);
set @sql=@paranth+@sql
if (isnull(@paranth,'')<>'')
set @sql=@sql+')'
PRINT @sql;
答案 2 :(得分:-2)
您可以在SP中使用CSV到整数表值函数。首先,您必须首先创建CsvToInt函数。然后,您可以在存储过程中使用它将参数转换为整数列表。正如所指出的,这仅适用于动态搜索条件的“或”组件。
您可以将其与EXEC
或sp_executesql
结合使用。这将允许您添加sql作为参数。
SET @myBaseQuery = 'SELECT * FROM TestTable WHERE SystemId = ' + @myParam
EXECUTE(@myBaseQuery)
或
SELECT * FROM TestTable WHERE SystemID IN (SELECT IntValue FROM dbo.CsvToInt('2,3,4,5,6'))
-- use your parameters
CREATE FUNCTION [dbo].[CsvToInt] ( @Array VARCHAR(1000))
RETURNS @IntTable TABLE
(IntValue INT)
AS
BEGIN
DECLARE @separator CHAR(1)
SET @separator = ','
DECLARE @separator_position INT
DECLARE @array_value VARCHAR(1000)
SET @array = @array + ','
While patindex('%,%' , @array) <> 0
BEGIN
SELECT @separator_position = patindex('%,%' , @array)
SELECT @array_value = LEFT(@array, @separator_position - 1)
INSERT @IntTable
VALUES (CAST(@array_value AS INT))
SELECT @array = stuff(@array, 1, @separator_position, '')
END
RETURN
END
CsvToInt函数取自http://www.summit-pro.com/blog/2010/05/18/csv-list-to-int-sql-function/