使用带逗号分隔值的varchar字符串选择IN

时间:2014-11-19 16:38:32

标签: sql-server sql-server-2008 tsql

我正在尝试在几个表中搜索手机列表。

问题是将单个字符串转换为有效的逗号分隔字符串,以与IN子句一起使用。

我尝试使用替换来解决问题。

DECLARE @PhoneNumber VARCHAR(3000) 
SET @PhoneNumber = '6725556666,2124444444'
SET @PhoneNumber = '''' + @PhoneNumber + ''''

SELECT @PhoneNumber
'6725556666','2124444444'

最后,示例SQL无法按预期识别字符串:

SELECT  Provider
        ,PhoneNumber      
        ,ChangeType
        ,ChangeDate 
FROM dbo.PhoneLog
WHERE PhoneNumber IN (@PhoneNumber)

1 个答案:

答案 0 :(得分:2)

有几种方法可以解决这个问题。一种选择是使用动态sql并将您的电话号码字符串注入包含该语句的变量,然后执行如下操作:

DECLARE @PhoneNumber VARCHAR(3000) 
SET @PhoneNumber = '6725556666,2124444444'
DECLARE @SQL NVARCHAR(max)
SET @SQL = N'
    SELECT Provider, PhoneNumber, ChangeType, ChangeDate 
    FROM dbo.PhoneLog
    WHERE PhoneNumber IN (' + @PhoneNumber + ')'
EXEC sp_executesql @SQL

请注意,此方法可能容易受到SQL注入攻击,例如提供类似

的字符串
SET @PhoneNumber = '1);truncate table phonelog;--'

会有效地清空表格。因此,如果它确定注入的字符串被清理并且安全(或者可能永远不会被使用),那么使用上面这样的动态SQL方法应该只是一个选项。

另一个可能更好的选择是使用用户定义的函数来拆分phonenumber变量并使用如下:

SELECT Provider, PhoneNumber, ChangeType, ChangeDate 
FROM dbo.PhoneLog
WHERE PhoneNumber IN (
    SELECT splitdata FROM dbo.fnSplitString(@PhoneNumber,',')
    -- you could add a check here that the data returned from the function 
    -- is indeed numeric and valid
    -- WHERE ISNUMERIC(splitdata) = 1
    )

以下是示例中使用的函数:

CREATE FUNCTION [dbo].[fnSplitString]   
    (   
        @string NVARCHAR(MAX),   
        @delimiter CHAR(1)   
    )   
    RETURNS @output TABLE(splitdata NVARCHAR(MAX)   
    )   
    BEGIN   
        DECLARE @start INT, @end INT   
        SELECT @start = 1, @end = CHARINDEX(@delimiter, @string)   
        WHILE @start < LEN(@string) + 1 BEGIN   
            IF @end = 0    
                SET @end = LEN(@string) + 1  

            INSERT INTO @output (splitdata)    
            VALUES(SUBSTRING(@string, @start, @end - @start))   
            SET @start = @end + 1   
            SET @end = CHARINDEX(@delimiter, @string, @start)  

        END   
        RETURN   
    END 

我没有写这个功能,我想我是在互联网上找到的......