【问题标题】:How to use a variable inside IN operator [duplicate]如何在IN运算符中使用变量[重复]
【发布时间】:2017-12-08 19:33:27
【问题描述】:

我正在尝试用 C# 编写一个应用程序,它将一个包含多个用逗号分隔的值的变量传递给存储过程

string state = "AZ, CA, VA"

我希望我的存储过程返回变量中每个状态的所有数据

CREATE PROCEDURE usp_GetStateInfo
@state varchar(2)

SELECT * FROM StateTable WHERE state IN (@state)

但是当我执行上面的代码时,我收到一条错误消息,提示“语法不正确” 我做错了什么,我该如何解决?

谢谢

【问题讨论】:

  • 使用单引号:"'AZ', 'CA', 'VA'"
  • 我假设您说的是 SQL-server (T-SQL)?您当前调用该过程的代码是什么?
  • 网上也有关于如何在sql中使用保留字IN的例子你试过google搜索吗?
  • 我现在遇到的问题是在创建存储过程时。每当我尝试执行存储过程时,它都会给我错误
  • @DylanNicholson 的可能副本是您想要的。 IN 在列表中查找值。字符串不是列表。您可以发送一个表值参数 - 值列表 - 然后加入它。

标签: c# sql stored-procedures in-operator


【解决方案1】:

您不能使用多个输入作为 IN 语句的参数。您必须在 SQL 中拆分这些逗号分隔值以创建表变量并与该表变量连接。

你可以创建一个分割输入字符串的函数:-

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[udf_PutStringtoTableUnique]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[udf_PutStringtoTableUnique]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE function [dbo].[udf_PutStringtoTableUnique]  
(         
      @inputStr as varchar(max),  
      @delim nchar(1) = N','    
)    
returns @tbl table(ID int primary key)    
as    
BEGIN    

if @inputStr = '' or @inputStr is null
return 

declare @tags nchar(2)
set @tags = @delim + @delim;

with tbl_for_csv as    
(    
select left(@inputStr + @tags,charindex(@delim,@inputStr + @tags) -1)as Col,     
right(@inputStr + @tags,len(@inputStr + @tags) - charindex(@delim,@inputStr + @tags)) as Str    
union all    
select left(Str,charindex(@delim,Str) - 1)as Col,     
right(Str,len(Str) - charindex(@delim,Str)) from tbl_for_csv    
where len(right(Str,len(Str) - charindex(@delim,Str))) > 0    
)    
insert into @tbl    
select distinct Col from tbl_for_csv    
option (maxrecursion 0)    

return 
END

GO

SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER ON
GO

然后在程序中写这样的东西:-

DECLARE @TempStates Table (StateName Varchar(2))

INSERT INTO @TempStates
Select id from [dbo].[udf_PutStringtoTableUnique](@state, ',')

    SELECT * FROM StateTable 
    INNER JOIN @TempStates temp ON state = temp.StateName 

【讨论】:

  • 不错,但很麻烦的解决方案。我确信这会起作用,但 UDF 非常慢
  • 这是一个简单的 udf,不会花费太多时间......我也尝试过处理大量数据。
  • 是的,我知道你的意思,如果它们不被内联使用,那么它们是可以接受的......当内联(在选择中)使用时,它们真的会降低速度。
  • 是的...同意格兰特..最好有一个表变量来存储函数的结果n使用它。正在编辑该查询...
  • 这是个好主意 :) 我会尽量记住这一点
【解决方案2】:

IN 运算符接受内联值列表或select 语句。 SQL 中没有原生的list 变量类型。当然varchar(2) 不会像你一样工作。

当您使用 C# 时,循环遍历状态列表并为每个元素调用存储过程是有意义的。该过程将使用= 而不是IN 来过滤状态。

如果您坚持该过程接受逗号分隔值的字符串,那么您将不得不使用 SQL 命令来拆分字符串并将每个值插入到临时表或表变量中,然后有一个 select 语句供IN消费。

在 T-SQL 中,您可以使用 STRING_SPLIT() 为 SQL Server 2016 执行此操作 https://docs.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql

SELECT *
FROM StateTable
WHERE state IN(
    SELECT value
    FROM STRING_SPLIT(@states, ',') )

【讨论】:

  • 太棒了,什么版本的SQL支持STRING_SPLIT?顺便说一句,这是对我们所有人在某个时候遇到的问题的一个非常有效的答案......
  • LOL 2016....我仍在使用 2008...如果支持,我将使用 '95
  • 不幸的是,String_Split 已在 2016 年推出,仅在兼容级别 130 下可用。:(
  • 很遗憾,我还在用2005
猜你喜欢
  • 1970-01-01
  • 2017-01-29
  • 2018-08-29
  • 2014-01-29
  • 2022-01-25
  • 2019-05-29
  • 2014-05-05
  • 2018-09-16
  • 2022-01-01
相关资源
最近更新 更多