Mah*_*ari 1 .net c# sql t-sql sql-server-2008-r2
可能重复:
使用逗号分隔参数帮助进行SQL搜索查询
我想编写一个存储过程,在表上执行select并需要一个类型的输入变量varchar(max).
我想发送一堆由,输入参数分隔的值,例如
'Jack','Jane','Joe'
Run Code Online (Sandbox Code Playgroud)
然后获取包含其中一个名称的行.
在SQL中,代码将是
Select * from Personnel where Name in ('Jack','Joe','Jane');
Run Code Online (Sandbox Code Playgroud)
现在我想在我的C#应用程序中有一个变量,比如strNames并填充它
string strNames = "'Jack','Joe','Jane'";
Run Code Online (Sandbox Code Playgroud)
并将此变量发送到SP并执行它.就像是
Select * from Personnel where Name in (''Jack','Joe','Jane'') -- this is wrong
Run Code Online (Sandbox Code Playgroud)
但是,如何告诉SQL Server运行此命令?
我需要做到这一点,我知道这是可能的,请给我一些线索.
首先,将名称传递给存储过程时,不需要引用单个名称.
using (SqlCommand cmd = new SqlCommand("MyStoredProc", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@longFilter", "Jack,Jill,Joe");
using (SqlDataReader reader = cmd.ExecuteReader())
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
然后,在存储过程中,您可以使用简单的文本函数和临时表,如下所示,以逗号分隔字符串,并为字符串的每个部分分配临时表的条目:
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
Run Code Online (Sandbox Code Playgroud)
如果不包含任何行(未过滤的结果),请稍后使用以下内容SELECT获取其名称所在的所有人的列表或所有人的列表:@temp@temp
SELECT * FROM Personnel WHERE Name IN (SELECT Name FROM @temp) OR (SELECT COUNT(*) FROM @temp) = 0
Run Code Online (Sandbox Code Playgroud)
您可以使用表值参数.
基本上,您可以在过程中插入一个值列表作为参数,并将它们用作表格,类似于
Select * from Personnel
where Name in (select name from @NamesTable).
Run Code Online (Sandbox Code Playgroud)
现在,具体细节
要使用表值参数,必须在sql server中使用预定义参数的类型
create type NamesTable as table (Name varchar(50))
Run Code Online (Sandbox Code Playgroud)然后,您可以使用已定义的类型作为过程中的参数
create procedure getPersonnelList
@NamesTable NamesTable readonly
as
begin
select * from personnel
where Name in (select Name from @NamesTable)
end
Run Code Online (Sandbox Code Playgroud)
你可以在这个SQL Fiddle中看到它的实际效果
在C#方面你需要创建参数.如果你有一个集合中的名字,并构建字符串,你可以使用它来生成参数,如果它们是逗号分隔的字符串,快速string.Split可以处理它.由于我不知道你的具体情况,我会假设你有一个List<string>叫names.您需要将其转换为要发送到过程的表值参数,使用类似于:
DataTable tvparameter = new DataTable();
tvparameter.Columns.Add("Name", typeof(string));
foreach (string name in names)
{
tvparameter.Rows.Add(name);
}
Run Code Online (Sandbox Code Playgroud)
现在您只需要将该参数发送到该过程,就是这样.这是一个完整的控制台程序,它执行过程并输出结果.
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"]);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)