C# 如何格式化传递给存储过程的数据,以便与IN子句一起使用?

C# 如何格式化传递给存储过程的数据,以便与IN子句一起使用?,c#,sql-server,C#,Sql Server,例如,假设我有以下存储过程: CREATE PROCEDURE [dbo].[get_Members] @IsActive INT, @Gender VARCHAR(MAX) AS SELECT first_name, last_name, gender FROM members WHERE is_active IN (@IsActive) AND gender IN (@Gender)

例如,假设我有以下存储过程:

CREATE PROCEDURE [dbo].[get_Members]
    @IsActive INT,
    @Gender VARCHAR(MAX)
AS
    SELECT
        first_name, last_name, gender
    FROM 
        members
    WHERE 
        is_active IN (@IsActive)
        AND gender IN (@Gender)
GO
ArrayList lst = new ArrayList();

lst.Add(new SqlParameter("@IsActive", IsActive));
lst.Add(new SqlParameter("@Gender", Gender));

try
{
    return this.ExecuteDataTable("get_Members", lst);
}
我有下面的c代码来调用这个存储过程:

CREATE PROCEDURE [dbo].[get_Members]
    @IsActive INT,
    @Gender VARCHAR(MAX)
AS
    SELECT
        first_name, last_name, gender
    FROM 
        members
    WHERE 
        is_active IN (@IsActive)
        AND gender IN (@Gender)
GO
ArrayList lst = new ArrayList();

lst.Add(new SqlParameter("@IsActive", IsActive));
lst.Add(new SqlParameter("@Gender", Gender));

try
{
    return this.ExecuteDataTable("get_Members", lst);
}
在我的表中,
处于活动状态
将是一种
int
类型,可接受值为
1
0

性别是一个
varchar
列,可接受值为
Male
Female
Unknown

我需要使用什么样的变量来传递
IsActive
SQL参数的
1,0
值,以及
in
参数的
Male
Female
Unknown
值,以便它在
in
子句中正常工作

我是一个视觉学习者,所以一个视觉例子会让人惊讶。谢谢。

不用iActive,因为这很容易解释: 将参数声明为
DbType.Boolean
,将其
.Value
设置为c#bool,服务器端的
位0/1
列将正确映射为
0=false
1=true

进入您的查询: 您不能像这样将值传递给IN。如果您想将性别作为VARCHAR传递,您必须执行以下操作:

CREATE PROC [dbo].[get_Members]
    @IsActive int
    ,@Gender varchar(max)

AS

SELECT
    first_name
    ,last_name
    ,gender
FROM members
WHERE is_active IN (@IsActive)
AND @Genders LIKE CONCAT('%.', gender, '.%')

GO

需要注意的重要一点是,您的C#,想要
女性
s和
未知
s,应该构建一个如下所示的字符串:

.female.unknown.
sql变成:

'.female.unknown.' LIKE '%.<gender from column>.%'

你为什么不能像以前那样做呢

因为这不起作用:

WHERE Gender IN ('female, male')
这项工作:

WHERE Gender IN ('female', 'male')
这两件事很不一样

如果您非常想在中使用,则必须有更多变量:

WHERE Gender IN (@g1, @g2, @g3)
你的c可以设置
@g1='male'
@g2='female'
@g3='nonexistent\u或\u null\u或\u even\u male\u,如果你只想要雄性和雌性的话

我会用哪一种? 可能是后一种形式,因为如果您试图通过使用“像%column%这样的值”方法将内容硬塞进一个varchar中,则很有可能不会使用性别索引

最后说明;没有什么可以阻止您使用单个varchar参数并在过程中对其进行切割。最简单的方法是使用sqlserver 2016+和字符串分割函数:

WHERE Gender IN (
  SELECT value FROM STRING_SPLIT(@Genders, '.') WHERE LEN(LTRIM(value)) > 0
)
但是如果你想的话,你可以更多地参与用子字符串等来切碎东西。我没有立即使用此选项,因为它非常具体于数据库,是否可以在服务器端轻松拆分字符串,而无需用户定义函数等(我不想编写一个在所有sql server上普遍适用的字符串,使用左/右/子字符串等)

省去了IsActive,因为这很容易解释: 将参数声明为
DbType.Boolean
,将其
.Value
设置为c#bool,服务器端的
位0/1
列将正确映射为
0=false
1=true

进入您的查询: 您不能像这样将值传递给IN。如果您想将性别作为VARCHAR传递,您必须执行以下操作:

CREATE PROC [dbo].[get_Members]
    @IsActive int
    ,@Gender varchar(max)

AS

SELECT
    first_name
    ,last_name
    ,gender
FROM members
WHERE is_active IN (@IsActive)
AND @Genders LIKE CONCAT('%.', gender, '.%')

GO

需要注意的重要一点是,您的C#,想要
女性
s和
未知
s,应该构建一个如下所示的字符串:

.female.unknown.
sql变成:

'.female.unknown.' LIKE '%.<gender from column>.%'

你为什么不能像以前那样做呢

因为这不起作用:

WHERE Gender IN ('female, male')
这项工作:

WHERE Gender IN ('female', 'male')
这两件事很不一样

如果您非常想在中使用,则必须有更多变量:

WHERE Gender IN (@g1, @g2, @g3)
你的c可以设置
@g1='male'
@g2='female'
@g3='nonexistent\u或\u null\u或\u even\u male\u,如果你只想要雄性和雌性的话

我会用哪一种? 可能是后一种形式,因为如果您试图通过使用“像%column%这样的值”方法将内容硬塞进一个varchar中,则很有可能不会使用性别索引

最后说明;没有什么可以阻止您使用单个varchar参数并在过程中对其进行切割。最简单的方法是使用sqlserver 2016+和字符串分割函数:

WHERE Gender IN (
  SELECT value FROM STRING_SPLIT(@Genders, '.') WHERE LEN(LTRIM(value)) > 0
)

但是如果你想的话,你可以更多地参与用子字符串等来切碎东西。我没有立即使用这个选项,因为在服务器端,没有用户定义的函数等情况下,字符串是否可以很容易地拆分(我不想编写一个在所有sql server上都普遍适用的,使用左/右/子字符串等)

考虑到您只需要解析3个值,另一种方法可能是使用拆分数据。请注意,
PARSENAME
如果分隔字符串中的项目超过4个,或者如果任何项目超过128个字符,则不会有帮助。文档(在编写本文时)是错误的,因为实际返回类型是
sysname
,它是
nvarchar(128)
的同义词


使用
CONCAT
方法,就像在另一个答案中一样,将使您的查询不可搜索;这可能会有很大的性能问题。

考虑到您将只解析3个值,可能会使用另一种方法来拆分数据。请注意,
PARSENAME
如果分隔字符串中的项目超过4个,或者如果任何项目超过128个字符,则不会有帮助。文档(在编写本文时)是错误的,因为实际返回类型是
sysname
,它是
nvarchar(128)
的同义词


使用
CONCAT
方法,就像在另一个答案中一样,将使您的查询不可搜索;这可能会有很大的性能问题。

表值参数最好。查看表值参数将是最好的。尽管PARSENAME有点粗俗,但请看这个巧妙的把戏。。它旨在分离对表等的引用,比如“dbo.Northwind.orders”,我只会在这样一个非常狭窄的上下文中使用它;很多事情都可能以不同的方式破坏它。未来参观t