Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/87.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逗号分隔值查询_Sql_Dynamic Sql_Delimiter_Delimited - Fatal编程技术网

动态SQL逗号分隔值查询

动态SQL逗号分隔值查询,sql,dynamic-sql,delimiter,delimited,Sql,Dynamic Sql,Delimiter,Delimited,[更新:使用SQL Server 2005] 您好,我要做的是使用逗号分隔的值列表(ID)查询存储过程以检索数据行 我收到的问题是转换错误: Conversion failed when converting the varchar value ' + @PassedInIDs + ' to data type int. my where子句和错误中的语句是: ... AND (database.ID IN (' + @PassedInIDs + ')) 注意:database.ID为int

[更新:使用SQL Server 2005]

您好,我要做的是使用逗号分隔的值列表(ID)查询存储过程以检索数据行

我收到的问题是转换错误:

Conversion failed when converting the varchar value ' +
@PassedInIDs + ' to data type int.
my where子句和错误中的语句是:

...
AND (database.ID IN (' + @PassedInIDs + '))
注意:database.ID为int类型

我在以下网站上看到了这篇文章:

但由于错误而没有完成

在我的执行脚本中,我有:

...
@PassedInIDs= '1,5'
我做错什么了吗?
谢谢您的帮助。

您需要像对待桌子一样对待ufn\u CSV旋转设备。因此,您可以加入该功能:

JOIN ufn_CSVToTable(@PassedInIDs) uf ON database.ID = uf.[String]

我建议在SQL2005中为此使用XML。有点笨重,但它可以更容易。它允许您将XML选择到表中,然后可以连接或插入表等

如果还没有,请查看Sql Server的OPENXML()

例如,您可以传入以下内容: “12…”

然后使用:

exec sp_xml_preparedocument @doc OUTPUT, @xmlParam

SELECT element 
FROM OPENXML (@doc, 'Array/Value', 2) WITH (element varchar(max) 'text()')

这应该是一个开始

我强烈建议您使用该链接中的第二种方法。创建一个用户定义的函数,将逗号分隔的字符串转换为一个表,然后可以轻松地从中选择


如果你在Erland上使用Google和“Dynamic SQL”,他会很好地记录它所带来的陷阱。

首先,你在SQL中向IN函数传递一个字符串。如果您回顾一下原始文章,您将看到它不是直接发出SQL语句,而是构建一个
字符串,这是要执行的SQL语句

SQL中没有字符串求值。这:

database.ID IN (' + @PassedInIDs + ')
不会转到:

database.ID IN (1,2,3)
仅仅因为
@passedInds
参数恰好包含
'1,2,3'
。该参数甚至没有被查看,因为您所拥有的只是一个包含
“++@passedinds+”
的字符串。从语法上讲,这相当于:

database.ID IN ('Bob')
简而言之,您无法在SQL中执行此处尝试的操作。但还有四种可能性:

  • 您可以用调用语言构造SQL字符串,并完全放弃存储过程
  • 您可以在in子句中使用一个动态准备语句,该语句的参数与您希望使用的参数相同
  • 您可以使用一个固定的预处理语句,例如,包含10个参数:
    IN(?,,,,,,,,,,,,,?)
    ,只填充所需数量,将其他参数设置为NULL
  • 您可以创建一个包含10个参数的存储过程,并传入所需的参数,将其他参数设置为NULL:
    in(@p1,@p2,…,@p10)

  • 我将创建一个CLR表值函数:

    JOIN ufn_CSVToTable(@PassedInIDs) uf ON database.ID = uf.[String]
    


    在它中,您将分离字符串并执行到一组行的转换。然后,您可以加入该表的结果,或者使用IN查看列表中是否有id。

    这可以通过Narayana文章中提到的6种方法解决

    我最棘手的问题是如何实施

    声明@声明nvarchar(256)
    set@statement='select*from Persons where Persons.id in(+@PassedInIDs+')”
    execsp_executesql@语句

      -
        以下是我发现和测试的内容:

        SET QUOTED_IDENTIFIER ON
        SET ANSI_NULLS ON
        GO
        CREATE  FUNCTION [dbo].[SplitStrings] ( @IDsList VARCHAR(MAX) )
        RETURNS @IDsTable TABLE ( [ID] VARCHAR(MAX) )
        AS 
        BEGIN
            DECLARE @ID VARCHAR(MAX)
            DECLARE @Pos VARCHAR(MAX)
        
            SET @IDsList = LTRIM(RTRIM(@IDsList)) + ','
            SET @Pos = CHARINDEX(',', @IDsList, 1)
        
            IF REPLACE(@IDsList, ',', '') <> '' 
                BEGIN
                    WHILE @Pos > 0 
                        BEGIN
                            SET @ID = LTRIM(RTRIM(LEFT(@IDsList, @Pos - 1)))
                            IF @ID <> '' 
                                BEGIN
                                    INSERT  INTO @IDsTable
                                            ( [ID] )
                                    VALUES  ( CAST(@ID AS VARCHAR) )
                                END
                            SET @IDsList = RIGHT(@IDsList, LEN(@IDsList) - @Pos)
                            SET @Pos = CHARINDEX(',', @IDsList, 1)
                        END
                END 
            RETURN
        END
        
        GO
        


        您使用的是什么SQL?它不应该试图将该值转换为int。您可以显示更多代码吗?SQL Server 2005?顺便说一句,这应该行得通。该错误看起来像是将“++@passedinds+”视为字符串。。。你缺少报价吗?缺少完整的查询,我不能告诉你。当您使用动态SQL时,所有内容都被引用,直到您对引用的字符串运行exec。它在任何时候都不应该将“++@passedids+”视为文本字符串。在我看来,这就像一个错误出现在错误代码段的案例。请显示整个查询-看起来您没有正确构建动态sql字符串…casper。。。您所做的编辑可能正在更改一段按字面意思粘贴的代码。这对于上面使用动态SQL的查询是完全不必要的。evals的最后一个字符串将只是“IN(1,5)”,这是有效的SQL。@freelookenstein:不幸的是,在解析和生成列表的XML时,您会因较大的值列表而产生巨大的开销。为什么不像他尝试的那样使用动态SQL?casperOne,您指的是哪种显著的开销?如果您能将我链接到一些文档,我将不胜感激。XML解析是“巨大的开销”。至少,从解析一个字符串到一种语言(SQL)再到两种语言(SQL和XML),生成XML本身没有任何开销。您当然可以将“1,2,3”作为字符串传递,将其连接到动态SQL中,然后就可以使用它了。我总是这样做。你错了,那么你对我的答案读得不够好。他显然认为他可以在存储过程中执行动态SQL。你不能。至少不是这样。你当然可以。将要使用的子查询保存为字符串,然后执行。我个人不喜欢注射的潜力,但他并没有要求完全安全的东西。这就是我说的:“至少不是这样。”。我知道您可以使用EXECUTE在服务器上执行动态SQL。但这不是问题所在,我绝对不建议在“从野外”传入参数的存储过程中这样做。他给出的链接是动态SQL。他只是在语法上有个拼写错误。我们需要完整的代码来了解情况。他发布的错误是如果您不使用动态SQL会发生的错误。因为我们没有完整的代码,所有的赌注都没有了。或者像他想做的那样使用动态SQL?@cmartin:但他没有,因为这是在一个存储过程中,他想将逗号分隔的值列表放入SP。可以在SP中使用动态SQL,但那只是一种浪费。如果你看看他使用的链接,他当然在尝试使用动态SQL。我也不觉得这样做是浪费。