将分隔值传递给IN运算符的SQL Server存储过程。怎么样?

时间:2013-07-14 06:45:22

标签: sql-server stored-procedures

我需要将参数(@name)作为字符串'Alex','david','crowner'传递给存储过程中的查询。

存储过程中的查询如下所示:

select * 
from employees 
where name in (@name)

将传递的@name参数的值类似于

'Alex','david','crowner'

我如何在存储过程中处理此问题,以便在IN运算符的表中查找名称?

3 个答案:

答案 0 :(得分:1)

在SQL Server 2008及更高版本中,您可以使用表值参数。在数据库中,您必须创建表类型。例如:

-- Drop old example definitions
if exists (select * from sys.procedures where name = 'TestProcedure')
    drop procedure TestProcedure
if exists (select * from sys.types where name = 'TestTableType')
    drop type TestTableType
if exists (select * from sys.tables where name = 'TestTable')
    drop table TestTable
go    
-- Create example table, type and procedure
create table TestTable (id int identity, name varchar(50))
create type TestTableType as table (name varchar(50))
go
insert TestTable values ('Bill'), ('George'), ('Barrack')
go
create procedure dbo.TestProcedure
    @List TestTableType readonly
as
select  *
from    TestTable
where   name in 
        (
        select  name
        from    @List
        )
go

在C#中,您可以传递DataTable作为表值参数:

var listTable = new DataTable();
listTable.Columns.Add("Name", typeof(string));
listTable.Rows.Add("Bill");
listTable.Rows.Add("George");

var listParameter = new SqlParameter();
listParameter.ParameterName = "@List";
listParameter.Value = listTable;

using (var con = new SqlConnection("Server=localhost;Database=test;" + 
                                   "User Id=testuser;Password=testpassword;"))
{
    var com = con.CreateCommand();
    com.CommandText = "dbo.TestProcedure";
    com.CommandType = CommandType.StoredProcedure;
    com.Parameters.Add(listParameter);
    con.Open();
    using (var read = com.ExecuteReader())
    {
        while (read.Read())
            Console.WriteLine(read["name"]);
    }
}

即使是单个表值参数所需的代码量和复杂性也不是SQL Server设计者的补充。

答案 1 :(得分:0)

你可以将一个字符串传递给参数和存储过程中使用函数体内的函数,如charindex和substring,并替换为你想做的事情

答案 2 :(得分:0)

经过一番研究后,我偶然发现a Code Project thread,这是解决问题的关键。在上面的线程的帮助下,我编写了以下存储过程:

CREATE PROCEDURE [dbo].[myWorkingProcedure]    
 @inputList nvarchar(MAX)    
AS       
DECLARE @SetPoint INT    
DECLARE @VALUE nvarchar(50)    
CREATE TABLE #tempTab (id nvarchar(50) not null)
BEGIN    
 SET NOCOUNT ON;
 WHILE PATINDEX('%,%',@inputList) > 0 <-- Drive loop while commata exist in the input string
 BEGIN
  SELECT  @SetPoint = PATINDEX('%,%',@inputList) <-- Determine position of next comma
  SELECT  @VALUE = LEFT(@inputList , @SetPoint - 1) <-- copy everything from the left into buffer
  SELECT  @idList = STUFF(@inputList, 1, @SetPoint, '') <-- throw away the stuff you copied
  INSERT INTO #tempTab (id) VALUES (@VALUE) <-- put value in buffer table
 END
 INSERT INTO #tempTab (id) VALUES (@inputList) <-- insert last value in the input list to buffer
 BEGIN
  SELECT * FROM myTable
  WHERE myColumn IN (SELECT id FROM #tempTab) <-- Do the select
   DROP TABLE #tempTab <-- throw buffer table away
 END    
END    
GO