2013-01-10 145 views
1

可能重複分離陣列狀字符串:
Help with a sql search query using a comma delimitted parameter執行存儲過程與由逗號

我想要寫執行一個表上的選擇的存儲的過程,並且需要一個輸入變量類型爲varchar(max)

我想發送一串由,分隔的值作爲輸入參數,例如:

'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 

但是如何告訴SQL Server運行此類命令?

我需要做到這一點,我知道這是可能的,請給我線索。

+0

是否可以此字符串'SELECT * FROM Table1'發送例如存儲過程和SP執行它的命令?我不知何故希望sql來執行一個字符串。 –

+0

是的,這是可能的,但我永遠不會那樣做。 –

+0

糟糕,因爲它很脆弱?或其他原因?我很好奇 –

回答

6

首先選擇從表中的數據,單名不需要加引號,當你將它們傳遞到存儲程序。

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 

後來使用以下SELECT讓所有的人它的名稱是@temp或全部的列表,如果@temp不包含任何行(未經過濾的結果):

SELECT * FROM Personnel WHERE Name IN (SELECT Name FROM @temp) OR (SELECT COUNT(*) FROM @temp) = 0 
+0

中找到。這是如何工作的?它看起來並不像longFilter值被存儲在臨時表中。是否有一些SQL代碼丟失?我錯過了明顯的東西嗎? –

+0

其實,你是對的(有趣的是,沒有人注意到它) - 實際插入臨時表中的INSERT缺失。我添加了一條評論。感謝您指出了這一點! –

2

我想你需要Sql Server中的分割函數來將逗號分隔字符串分解爲表。請參閱這些鏈接。

Split Function in Sql Server to break Comma-Separated Strings into Table

SQL User Defined Function to Parse a Delimited String

您可以使用所有的

Select * from 
Personnel where 
    Name in (select items from dbo.Split ('Jack,Joe,Jane',',')) 
+0

我知道爲此目的的「最佳」功能可以在http://www.sqlservercentral.com/articles/Tally+Table/72993/ – MarkD

2

您可以簡單地檢查名稱是否包含在字符串中。注意在年底開始的逗號,以確保您匹配的全名

string strNames = ",Jack,Joe,Jane,"; 

的在SQL成爲

select * from Personnel where PATINDEX('%,' + Name + ',%', @strNames) > 0 

http://www.sqlfiddle.com/#!3/8ee5a/1

5

你可以使用Table Valued Parameters

基本上,你可以插入值的列表作爲過程的參數,並把它們作爲一個表,一些沿

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 
    

    你可以看到,在行動中,this SQL Fiddle

  • 在你需要創建參數事情C#的一面。如果您在集合中有名稱並構建字符串,則可以使用它來生成參數,如果它們是逗號分隔的字符串,則可以使用快速string.Split來處理該問題。由於我不知道你的具體情況,我假設你有一個叫做namesList<string>。你需要將其轉換成一個表值參數發送到程序中,使用類似:

    DataTable tvparameter = new DataTable(); 
    tvparameter.Columns.Add("Name", typeof(string)); 
    foreach (string name in names) 
    { 
        tvparameter.Rows.Add(name); 
    } 
    

    你可以找到如何在SO Question. 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"]); 
         } 
        } 
        } 
    }