2013-12-23 93 views
2

在我用C#編寫的應用程序中,我正在編寫SQL查詢。下面是查詢在C#中的SQL查詢中傳遞字符串數組作爲參數#

SELECT [Resource No_] where [Resource No_] In (@resources) 

@resources是具有一個或多於一個的字符串的用戶輸入的參數。

我的查詢失敗沒有顯示錯誤

據我查詢失敗,因爲在@resources參數以下被傳遞

"'123,'124','125'" 

(有2在開始引號並在末尾,這是失敗我的查詢)。

[Resource No_]是數據庫中的NVARCHAR類型。

谷歌搜索後,我發現關於這個主題的一些幫助,但都是適用的,當[Resource No_]的類型是Integer

+0

向我們展示如何創建此查詢。 –

+0

在不可能的情況下創建動態字符串,因爲我不知道用戶傳遞的參數數量。 – user2739679

+0

@Simon Whitehead :: SqlCommand cmd = new SqlCommand(SELECT [Resource No_] where [Resource No_] In(@resources),conn) – user2739679

回答

4

雖然我不同意所選的答案(或許多棘手的答案)的「重複問題」,here is an answer to it它顯示了一種方法非常類似於我的以下建議。

(我已經投票決定關閉這個問題作爲一個重複,因爲有這樣的答案,即使被埋。)


只有一個SQL值可以綁定到任何給定的佔位符。

雖然有方法將所有數據作爲「單值」發送,但我建議動態創建佔位符:它很簡單,乾淨,並且在大多數情況下可以可靠地工作。

考慮一下:

ICollection<string> resources = GetResources(); 

if (!resources.Any()) { 
    // "[Resource No_] IN()" doesn't make sense 
    throw new Exception("Whoops, have to use different query!"); 
} 

// If there is 1 resource, the result would be "@res0" .. 
// If there were 3 resources, the result would be "@res0,@res1,@res2" .. etc 
var resourceParams = string.Join(",", 
    resources.Select((r, i) => "@res" + i)); 

// This is NOT vulnerable to classic SQL Injection because resourceParams 
// does NOT contain user data; only the parameter names. 
// However, a large number of items in resources could result in degenerate 
// or "too many parameter" queries so limit guards should be used. 
var sql = string.Format("SELECT [Resource No_] where [Resource No_] In ({0})", 
    resourceParams); 

var cmd = conn.CreateCommand(); 
cmd.CommandText = sql; 

// Assign values to placeholders, using the same naming scheme. 
// Parameters prevent SQL Injection (accidental or malicious). 
int i = 0; 
foreach (var r in resources) { 
    cmd.Parameters.AddWithValue("@res" + i, r); 
    i++; 
} 
+0

這不是問題。你的答案是如何創建一個新的SQL語句;當你有幾千個參賽作品時,這並不好。 – fcm

+0

@fcm我不認爲你明白答案,這是關於如何在參數未知的情況下對參數進行參數化。 –

-1

這樣做

resources.Aggregate(r1, r2 => r1 + "', '" + r2 + "'") 

並傳遞一個字符串列表。

2

SQL2005 +:我會使用XML參數。例如:

CREATE PROCEDURE dbo.MyProc (
    @IntArrayAsXML XML 
) 
AS 
BEGIN 
    DECLARE @IntArray TABLE(IntValue INT); 
    INSERT INTO @IntArray (IntValue) 
    SELECT x.XmlCol.value('(@IntValue)[1]', 'INT') 
    FROM @IntArrayAsXML.nodes('/root/row') x(XmlCol) 

    SELECT ... FROM dbo.MyTable t WHERE t.ID IN (SELECT v.IntValue FROM @IntArray v) 
END; 
GO 

EXEC dbo.MyProc @IntArrayAsXML = N'<root> <row IntValue="11" /> <row IntValue="22" /> </root>' 
GO 

SQL2008 +:我會使用表型參數。示例:

CREATE TYPE dbo.IntArray AS TABLE(IntValue INT) ;; 
GO 

    CREATE PROCEDURE dbo.MyProc (
     @IntArrayAsTable dbo.IntArray READONLY 
    ) 
    AS 
    BEGIN  
     SELECT ... FROM dbo.MyTable t WHERE t.ID IN (SELECT v.IntValue FROM @IntArrayAsTable v) 
    END; 
    GO 

    DECLARE @p dbo.IntArray; 
    INSERT @p VALUES (11), (22); 

    EXEC dbo.MyProc @IntArrayAsTable = @p; 
    GO 

另請參閱此MSDN example

相關問題