2013-03-08 71 views
2

我想提出的參數化查詢的SQLQuery可以是這樣的:如何使用ADO.NET/C#進行涉及多個表的參數化查詢?

SELECT * FROM Table1 WHERE Col1 IN (SELECT Col2 FROM Table2 WHERE Col3 IN (1, 2, 3)); 

的數據來自WS接口,雖然我可以信任的消費者我想發揮它的安全和使用參數化查詢涉及DbParameters防止SQL注入。怎麼做?

謝謝!

+0

你可以使用存儲過程嗎? – Ankit 2013-03-08 13:40:08

+0

@Ankit:不,我不能。我必須使現有的代碼來處理依賴於另一個表的條件,並且使用存儲過程將會發生太大的變化。 – 2013-03-08 13:43:03

+0

你有這樣的代碼嗎? – 2013-03-08 13:45:46

回答

3

正如您所注意的,關鍵點是使用參數。令人討厭的是,IN子句出了名的問題。現在,如果你知道值均爲整數(例如你正在服用的int[]參數到C#方法),那麼你可以只是與之類的東西脫身:

cmd.CommandText = "SELECT * FROM Table1 WHERE Col1 IN (SELECT Col2 FROM Table2 WHERE Col3 IN (" 
+ string.Join(",", values) + "))"; // please don't!!! 

這是可怕的,表明一個非常糟糕的做法(如果有人將其複製爲字符串,則處於痛苦的世界),並且不能使用查詢計劃緩存。您可以做這樣的事情:

var sb = new StringBuilder("SELECT * FROM Table1 WHERE Col1 IN (SELECT Col2 FROM Table2 WHERE Col3 IN ("); 
int idx = 0; 
foreach(var val in values) { 
    if(idx != 0) sb.Append(','); 
    sb.Append("@p").Append(idx); 
    cmd.Parameters.AddWithValue("@p" + idx, val); 
    idx++ 
} 
sb.Append("))"); 
cmd.CommandText = sb.ToString(); 

這是首選的,但尷尬。

或者簡單:與像dapper的工具,讓擔心:

var data = conn.Query<YourType>(
    "SELECT * FROM Table1 WHERE Col1 IN (SELECT Col2 FROM Table2 WHERE Col3 IN @values)", 
    new { values }); 

這裏短小精悍點的使用和「做正確的事」。它也爲您處理「0值」的情況。

+0

謝謝Marc!我很熟悉如何進行參數化查詢。正如我告訴過你的,我只是在想不同的(錯誤的)方式。因此,底線是參數化「第二個查詢」,就像單個表一樣。所以這和我多次做的事情沒有什麼不同。 – 2013-03-08 14:16:18

+0

@matti絕對沒有什麼不同; ADO.NET不關心*命令文本是什麼。您所顯示的具體查詢中唯一有趣的技術點是'IN'子句 - 這是一個真正的PITA來正確參數化。 – 2013-03-08 14:17:24

+0

要檢查出這個小巧玲瓏。看起來不錯! – 2013-03-08 14:24:14

1

下面是一個例子:

SqlCommand cmd = new SqlCommand("SELECT * FROM Table1 WHERE Col1 IN (SELECT Col2 FROM Table2 WHERE Col3 = @myparam", conn); 

//define parameters used in command object 
SqlParameter param = new SqlParameter(); 
param.ParameterName = "@myparam"; 
param.Value   = "myvalue"; 

//add new parameter to command object 
cmd.Parameters.Add(param); 

// get data stream 
reader = cmd.ExecuteReader(); 

看看這個鏈接查看更多細節: http://csharp-station.com/Tutorial/AdoDotNet/Lesson06

+0

謝謝!我在想,我必須爲每個值創建一個DbParameter,例如:SELECT * FROM TABLE1 WHERE Col1 IN(@Params),它反過來將具有Status-es的參數。 – 2013-03-08 14:05:29

1

的困難在這裏被參數化每個單獨IN子句,這樣就可以通過ID的變量數。

看一看這個有用的物品作爲一種方法來解決這個問題:http://www.mikesdotnetting.com/Article/116/Parameterized-IN-clauses-with-ADO.NET-and-LINQ

基本上,它涉及字符串操作的一點點建立IN子句的參數列表,這樣就結束了一個對於具有3個ID的特定示例,SQL語句如下所示:

select * from TABLE1 where COL1 in (select COL2 from TABLE2 where COL3 IN (@p1, @p2, @p3)); 
+0

謝謝。我製作了自動處理IN的代碼。然而,我在想,是否有可能參數化SELECT * FROM TABLE1 WHERE Col1 IN(@Params),這反過來會以某種方式爲Status-es提供參數。也許這只是愚蠢的。 – 2013-03-08 14:11:56

相關問題