C# 使用逗号分隔的类似数组的字符串执行存储过程
可能重复: 我想编写一个存储过程,在表上执行select,并且需要一个varcharmax类型的输入变量 我想发送一组以分隔的值作为输入参数,例如C# 使用逗号分隔的类似数组的字符串执行存储过程,c#,.net,sql,tsql,sql-server-2008-r2,C#,.net,Sql,Tsql,Sql Server 2008 R2,可能重复: 我想编写一个存储过程,在表上执行select,并且需要一个varcharmax类型的输入变量 我想发送一组以分隔的值作为输入参数,例如 'Jack','Jane','Joe' 然后获取包含其中一个名称的行 在SQL中,代码是 Select * from Personnel where Name in ('Jack','Joe','Jane'); 现在我想在我的C应用程序中有一个变量,比如strNames,然后像这样填充它 string strNames = "'Jack',
'Jack','Jane','Joe'
然后获取包含其中一个名称的行
在SQL中,代码是
Select * from Personnel where Name in ('Jack','Joe','Jane');
现在我想在我的C应用程序中有一个变量,比如strNames,然后像这样填充它
string strNames = "'Jack','Joe','Jane'";
并将此变量发送到SP并执行它。差不多
Select * from Personnel where Name in (''Jack','Joe','Jane'') -- this is wrong
但是我如何告诉SQLServer运行这样的命令呢
我需要实现这一点,我知道这是可能的,请给我线索。我想您需要Sql Server中的Split函数将逗号分隔的字符串拆分为表。请参考这些链接 您可以使用从表中选择数据
Select * from
Personnel where
Name in (select items from dbo.Split ('Jack,Joe,Jane',','))
首先,将单个名称传递给存储过程时,不需要引用它们
using (SqlCommand cmd = new SqlCommand("MyStoredProc", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@longFilter", "Jack,Jill,Joe");
using (SqlDataReader reader = cmd.ExecuteReader())
{
...
}
}
然后,在存储过程中,您可以使用简单的文本函数和一个临时表,如下所示,在逗号处拆分字符串,并为字符串的每个部分创建一个临时表条目:
DECLARE @temp AS TABLE (Name NVARCHAR(255))
IF ISNULL(@longFilter, '') <> ''
BEGIN
DECLARE @s NVARCHAR(max)
WHILE LEN(@longFilter) > 0
BEGIN
IF CHARINDEX(',', @longFilter) > 0
BEGIN
SET @s = LTRIM(RTRIM(SUBSTRING(@longFilter, 1, CHARINDEX(',', @longFilter) - 1)))
SET @longFilter = SUBSTRING(@longFilter, CHARINDEX(',', @longFilter) + 1, LEN(@longFilter))
END ELSE
BEGIN
SET @s = LTRIM(RTRIM(@longFilter))
SET @longFilter= ''
END
-- This was missing until 20140522
INSERT INTO @temp (Name) VALUES (@s)
END
END
您只需检查字符串中是否包含名称。请注意结尾开头的逗号,以确保与全名匹配
string strNames = ",Jack,Joe,Jane,";
SQL成为
select * from Personnel where PATINDEX('%,' + Name + ',%', @strNames) > 0
请参阅您可以使用的
基本上,您可以在过程中插入一个值列表作为参数,并将其用作表,类似于
Select * from Personnel
where Name in (select name from @NamesTable).
现在,具体情况如何
若要使用表值参数,必须在sql server中使用预定义参数的类型
create type NamesTable as table (Name varchar(50))
然后,可以将定义的类型用作过程中的参数
create procedure getPersonnelList
@NamesTable NamesTable readonly
as
begin
select * from personnel
where Name in (select Name from @NamesTable)
end
你可以在行动中看到这一点
在C端,您需要创建参数。如果集合中有名称并生成字符串,则可以使用该名称生成参数,如果它们是逗号分隔的字符串,则可以使用快速字符串。拆分可以解决这一问题。因为我不知道你的具体情况,我假设你有一个名字列表。您需要将其转换为一个表值参数,然后发送到过程中,方法如下:
DataTable tvparameter = new DataTable();
tvparameter.Columns.Add("Name", typeof(string));
foreach (string name in names)
{
tvparameter.Rows.Add(name);
}
您可以在中找到有关如何在C代码中生成TVP的更多信息
现在只需要将该参数发送到过程,就这样。这是一个完整的控制台程序,它执行该过程并输出结果
List<string> names = new List<string> { "Joe", "Jane", "Jack" };
using (SqlConnection cnn = new SqlConnection("..."))
{
cnn.Open();
using (SqlCommand cmd = new SqlCommand("getPersonnelList", cnn))
{
cmd.CommandType = CommandType.StoredProcedure;
DataTable tvparameter = new DataTable();
tvparameter.Columns.Add("Name", typeof(string));
foreach (string name in names)
{
tvparameter.Rows.Add(name);
}
cmd.Parameters.AddWithValue("@NamesTable", tvparameter);
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
Console.WriteLine("{0} - {1}", dr["ID"], dr["Name"]);
}
}
}
}
例如,是否可以将此字符串Select*从表1发送到存储过程,然后sp将其作为命令执行?我想让sql执行一个字符串。是的,这是可能的,但我从来没有这样做过。哎呀,因为它易受攻击?还是其他原因?我很好奇脆弱是一回事。您还失去了.NET framework提供的所有舒适感,例如,参数总是以正确的格式传递给查询,等等。想想i18关于日期或浮点值的问题。另外,如果要将语句发送到存储过程,也可以立即在应用程序中执行它—有什么区别?Mahdi。您可以使用sp_executesql命令实现这一点:它确实有自己的位置。但是你需要非常谨慎地使用它。我主要关心的是确保您没有使用用户输入来构建sql命令,因此也没有使用sql-injection。我所知道的用于此目的的最佳功能是如何工作?看起来longFilter值从未存储在temp表中。是否缺少一些SQL代码?我遗漏了一些明显的东西吗?事实上,你是对的,有趣的是,以前没有人注意到这一点——临时表中的实际插入丢失了。我加了一句评论。谢谢你指出这一点!
List<string> names = new List<string> { "Joe", "Jane", "Jack" };
using (SqlConnection cnn = new SqlConnection("..."))
{
cnn.Open();
using (SqlCommand cmd = new SqlCommand("getPersonnelList", cnn))
{
cmd.CommandType = CommandType.StoredProcedure;
DataTable tvparameter = new DataTable();
tvparameter.Columns.Add("Name", typeof(string));
foreach (string name in names)
{
tvparameter.Rows.Add(name);
}
cmd.Parameters.AddWithValue("@NamesTable", tvparameter);
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
Console.WriteLine("{0} - {1}", dr["ID"], dr["Name"]);
}
}
}
}