2013-11-14 29 views
0

如何將名稱列表傳遞給SQL參數,以便我可以執行WHERE IN(@myList)?使用列表輸入構建SQL存儲過程查詢

我正在爲我們的網頁進行「高級搜索」,用戶可以列出它們的列表,用逗號分隔,他們希望找到幾個輸入內容。例如,可能有5個輸入(名字,帳號,姓氏,...),並且對於每個輸入,他們可以列出幾個並用逗號分隔它們。

我到目前爲止的做法是爲每個輸入採用此字符串,並對其進行格式化,以便可以對該字符串使用「IN」子句。這可能嗎?

IE爲「名」用戶輸入「鮑勃,喬,佛瑞德」,我想變換輸入到

"'Bob', 'Joe', 'Fred'" 

,然後發送作爲參數的存儲過程。

Declare @firstNames 

Select * from Users 
where User.FirstName in firstNames 

或者我應該把所有這些名稱放入C#中的DataTable中並將其傳遞給SQL?如果我應該走這條路線,一些例子會有很大幫助!

謝謝!

+1

您沒有提及您正在使用哪個SQL數據庫,但是如果它是MS SQL Server,那麼[SQL Server中的數組和列表] (http://www.sommarskog.se/arrays-in-sql.html)有很多有用的信息。 –

+0

添加標籤。我會閱讀你的鏈接。 – Dave

回答

0

在C#中,您可以向SQLCommand.CommandText添加參數列表。假設客戶名稱是一個字符串「‘鮑勃’,‘喬’,‘弗雷德’」你做這樣的事情:

Dim command As New SqlCommand(commandText, connection) 
     ' Add FirstName parameter for WHERE clause. 
     command.Parameters.Add("@FirstName", SqlDbType.nvarchar) 
     command.Parameters("@FirstName").Value = FirstName 

在查詢分析器你不能在@parameter名單,這是一個滋擾,但你可以從另一個來源通過一個;例如你的C#調用代碼。在你的WHERE子句中,你在WHERE IN(@Name)中執行。在我的測試中,我創建了一個臨時表,並在WHERE(SELECT FirstName FROM #MyCustomerTempTable)中執行WHERE操作,然後在連接它時使用singleton參數替換子查詢。

來源:http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.parameters(v=vs.110).aspx

另一種方法(我最經常使用),以將參數添加到該命令爲:

' Add the input parameter and set its properties. 
Dim parameter As New SqlParameter() 
parameter.ParameterName = "@FirstName" 
parameter.SqlDbType = SqlDbType.NVarChar 
parameter.Value = firstName 

' Add the parameter to the Parameters collection. 
command.Parameters.Add(parameter) 

源(向下滾動到示例): http://msdn.microsoft.com/en-us/library/yy6y35y8(v=vs.110).aspx

您也可以在C#中動態構建您的查詢,或者創建一個字符串。替換@parameter並將其替換爲'我的名稱列表',但這兩種方法都不適用於添加參數對象到SQL Command對象。我建議對SQL Command對象有一個深入的瞭解,以便你可以構建它而不是操縱字符串。

1

每當我的查詢變得有點複雜,這樣,我寧願選擇以下方式之一:

  1. C#創建動態查詢,基於字符串連接可讀性更好,而不是LINQ表達式樹,將它發送到SQL Server,或者
  2. 在SQL Server中創建SP或Table-Valued Function,然後從C#中調用它,將參數傳遞給它。

在C#中創建查詢時,它不可擴展,並且每次您想要更改邏輯時,都應該重新編譯應用程序。

在SP的情況下,因爲這將是一個動態的查詢和where子句應根據輸入參數來創建的,我用exec (@query)

+0

這些路線是否存在安全隱患?我打算在SP中創建查詢並使用exec(@query),但不確定列表問題。我將研究表值函數。 – Dave

+0

@Dave Saeed提出的第一個選項是安全的,因爲您可以生成一個形式爲'SELECT any [FROM] [someTable] WHERE [FirstName] = @ P1 OR [FirstName] = @ P2 OR等格式的SQL語句並以編程方式添加參數。您不應該使用'*'來選擇列,因爲理論上數據庫可以以任意順序自由返回它們。 –

1

假設你正在使用SQL Server,你可以創建這樣一個表格函數拆分逗號分隔值到表

CREATE FUNCTION dbo.Split(@String nvarchar(4000), @Delimiter char(1)) 
RETURNS @Results TABLE (Items nvarchar(4000)) 
AS 
BEGIN 
DECLARE @INDEX INT 
DECLARE @SLICE nvarchar(4000) 
-- HAVE TO SET TO 1 SO IT DOESNT EQUAL Z 
--  ERO FIRST TIME IN LOOP 
SELECT @INDEX = 1 
WHILE @INDEX !=0 
BEGIN 
-- GET THE INDEX OF THE FIRST OCCURENCE OF THE SPLIT CHARACTER 
SELECT @INDEX = CHARINDEX(@Delimiter,@STRING) 
-- NOW PUSH EVERYTHING TO THE LEFT OF IT INTO THE SLICE VARIABLE 
IF @INDEX !=0 
SELECT @SLICE = LEFT(@STRING,@INDEX - 1) 
ELSE 
SELECT @SLICE = @STRING 
-- PUT THE ITEM INTO THE RESULTS SET 
INSERT INTO @Results(Items) VALUES(@SLICE) 
-- CHOP THE ITEM REMOVED OFF THE MAIN STRING 
SELECT @STRING = RIGHT(@STRING,LEN(@STRING) - @INDEX) 
-- BREAK OUT IF WE ARE DONE 
IF LEN(@STRING) = 0 BREAK 
END 
RETURN 
END 

然後你可以從用戶 這樣調用該函數在SP

選擇*,其中User.FirstName在( SELECT items from [dbo]。[Split](@firstNames,','))