【问题标题】:SQL stored procedure sent data for "IN" conditionSQL 存储过程为“IN”条件发送数据
【发布时间】:2013-02-26 06:27:19
【问题描述】:

我有一个存储过程,它具有使用“IN”关键字的 where 条件。所以我想向存储过程发送多个值。

这是我的存储过程:

ALTER PROCEDURE [dbo].[xxx]
   @COM_KEY varchar(max) = NULL
AS
BEGIN
    SELECT     
       UserName, UserId
    FROM 
       company        
    WHERE      
       (COM_KEY IN (@COM_KEY))
END

所以我在这里传递值

string companyID = "";

for (int i = 0; i < lbCompanies.Items.Count; i++)
{
    if (i == 0)
    {
        companyID += Convert.ToInt32(lbCompanies.Items[i].Value);
    }
    else
    {
        companyID += "," + Convert.ToInt32(lbCompanies.Items[i].Value);
    }
}

DataSet ApproveList = DataRepository.TUsersProvider.xxx(companyID);

但是有错误

将 varchar 值 '3087,4058' 转换为数据类型 int 时转换失败

我该如何解决?

【问题讨论】:

  • 您使用的是哪个 DBMS?乍一看,问题似乎是您将 varchar 传递给查询需要 int 列表的 in 子句。
  • 为了确认,IN 语句时出现该错误?
  • IN 的格式是 IN ('something', 'something else') 而不是 IN ('something, something else') 更不是这样,请参阅我的答案。
  • 检查我的答案,它会为你工作。

标签: asp.net sql


【解决方案1】:

您不能将逗号分隔的字符串传递给@COM_KEY。你应该传递一个数组。

完成此任务的一种方法是使用Table-Valued Parameters

看看这篇文章,Solution #3:TSQL: Passing array/list/set to stored procedure (MS SQL Server)

本质上,您将ints 系列视为您应用JOIN 的表,而不是通过WHERE ... IN () 短语查询它。

【讨论】:

  • 不喜欢。如果您查看我引用的文章,他们会提到您的解决方案,然后继续使用更有效的方法。
  • 他们列出了许多解决方案,并且他们还引用了简单的案例,这个解决方案就足够了。对于这个特殊的情况,这将按预期工作。感谢您指出任何方式:)
【解决方案2】:

您可以创建一个UserDefinedFunction 来解析字符串并将提取的每个整数放入一个表中以解决此问题

CREATE Function fnSplitter (@IDs Varchar(100) )  
Returns @Tbl_IDs Table  (ID Int)  As  

Begin 
 -- Append comma
 Set @IDs =  @IDs + ',' 
 -- Indexes to keep the position of searching
 Declare @Pos1 Int
 Declare @pos2 Int

 -- Start from first character 
 Set @Pos1=1
 Set @Pos2=1

 While @Pos1<Len(@IDs)
 Begin
  Set @Pos1 = CharIndex(',',@IDs,@Pos1)
  Insert @Tbl_IDs Select  Cast(Substring(@IDs,@Pos2,@Pos1-@Pos2) As Int)
  -- Go to next non comma character
  Set @Pos2=@Pos1+1
  -- Search from the next charcater
  Set @Pos1 = @Pos1+1
 End 
 Return
End

现在像这样改变你的存储过程

ALTER PROCEDURE [dbo].[xxx]
@COM_KEY varchar(max) = NULL
AS
BEGIN
 SELECT UserName, UserId
 From company        
 WHERE COM_KEY IN (Select ID From dbo.fnSplitter(@COM_KEY))
END

查看link 了解详细实现

【讨论】:

  • 这行得通,我们在大型生产环境中使用它,但并非出于欲望。如果您可以使用,Ofer 发布的答案中提到的表值函数是更好的选择。如果他们不在桌子上,请使用此解决方案。请不要使用动态 SQL。
【解决方案3】:

解决您的问题最简单的方法是 vale SQL 字符串(用于动态查询),然后执行语句

ALTER PROCEDURE [dbo].[xxx]
   @COM_KEY varchar(max) = NULL
AS
BEGIN
DECLARE @SQL nvarchar(MAX)

SET @SQL=N'    SELECT     
       UserName, UserId
    FROM 
       company        
    WHERE      
       (COM_KEY IN ('+@COM_KEY+'))'
EXCE @SQL
END

@ssilas777 提到的解决方案是相同的复杂版本。

另请注意,使用IN 并不总是可取的。我遇到了

查询超时错误

IN 有很多 ID 时

【讨论】:

  • 请不要使用此解决方案。动态 SQL 几乎从来都不是正确的解决方案。
  • @ChrisPorter 我知道,我在回复中也提到它是最简单的解决方案,基于 SQL Server 的版本。否则你也可以参考这篇文章 [stackoverflow.com/questions/10511029/…
【解决方案4】:

从以下位置更改您的代码:

if (i == 0)
{
  companyID += Convert.ToInt32(lbCompanies.Items[i].Value);
}
else
{
  companyID += "," + Convert.ToInt32(lbCompanies.Items[i].Value);
}

到:

if (i == 0)
{
  companyID +="'" + Convert.ToInt32(lbCompanies.Items[i].Value) + "'";
}
else
{
  companyID += ",'" + Convert.ToInt32(lbCompanies.Items[i].Value) + "'";
}

【讨论】:

  • 将值用单引号括起来并不能解决他遇到的数据类型问题。无论值是否被单引号转义,都不能针对 varchar 参数执行 IN 子句。
猜你喜欢
  • 1970-01-01
  • 2013-07-29
  • 1970-01-01
  • 2015-08-01
  • 1970-01-01
  • 2012-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多