Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 使用带有逗号分隔值的varchar字符串在中选择_Sql Server_Sql Server 2008_Tsql - Fatal编程技术网

Sql server 使用带有逗号分隔值的varchar字符串在中选择

Sql server 使用带有逗号分隔值的varchar字符串在中选择,sql-server,sql-server-2008,tsql,Sql Server,Sql Server 2008,Tsql,我正试图在几个表格中搜索电话列表 问题是将单个字符串转换为有效的逗号分隔字符串,以便与in子句结合使用 我尝试使用replace来解决问题。 DECLARE @PhoneNumber VARCHAR(3000) SET @PhoneNumber = '6725556666,2124444444' SET @PhoneNumber = '''' + @PhoneNumber + '''' SELECT @PhoneNumber '6725556666','2124444444' 最后,示例S

我正试图在几个表格中搜索电话列表

问题是将单个字符串转换为有效的逗号分隔字符串,以便与in子句结合使用

我尝试使用replace来解决问题。

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)

有几种方法可以解决这个问题。一个选项是使用动态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
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
    )
请注意,这种方法可能容易受到SQL注入攻击,例如,向

SET @PhoneNumber = '1);truncate table phonelog;--'
实际上会清空桌子。因此,只有在确定注入的字符串经过消毒且安全(或者可能永远不应该使用)的情况下,才可以选择使用上述动态SQL方法

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

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
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 
创建函数[dbo].[fnSplitString]
(   
@字符串NVARCHAR(最大值),
@分隔符字符(1)
)   
返回@output TABLE(splitdata-NVARCHAR)(最大值)
)   
开始
声明@start INT、@end INT
选择@start=1、@end=CHARINDEX(@delimiter、@string)
而@start

我没有写这个函数,我想我是在互联网上的某个地方得到的…

可能是互联网工程师的副本?搜索“可能更好”?我想你还没见过鲍比·泰尔斯吧?请不要提倡邀请SQL注入漏洞的动态SQL方法。哎呀!神圣的SQL注入邀请@AaronBertrand,但我见过亲爱的Bobby Tables,我意识到了这种危险,但我们是否应该始终假设使用动态sql会招致注入攻击?为什么不假设输入在输入到查询中之前已被正确清理?或者OP也意识到了风险,或者至少可以对其进行评估。@AaronBertrand哦,我假设批评是针对第一个选项的,但是第二个选项中的函数也有这种问题吗?我不这么认为,但你的评论让我不确定。“假设”应该是你需要阅读的全部内容。这与继续让许多公司陷入困境的假设是一样的。不,你不能假设输入是经过消毒的,或者OP意识到了风险。这可能是OP在工作的第一天编写的第一个SQL查询。您是否希望与可能产生的新闻故事相关联?