2015-11-02 68 views
0

我有以下我要運行SQL語句:使用價值

string sql = @"DECLARE @a udt;" + 
       "INSERT INTO @a (id) VALUES @params;"; 

我有以下的整數數組:

int[] array1 = {10,20,30,40,50,60}; 

這是重要的不是上述數組大小在我的程序中是動態的。

我想,這樣的SQL在SqlCommand正在執行的SQL語句從陣列添加值到@params看起來是這樣的:

sql = @"DECLARE @a udt;" + 
     "INSERT INTO @a (id) VALUES (10),(20),(30),(40),(50),(60);" + 
     "EXEC sp @a;"; 

我曾嘗試以下除其他外,並保持獲得例外:

SqlConnection con = new SqlConnection("connectionString"); 
SqlCommand cmnd = new SqlCommand(sql, con); 

for (int i = 0; i < array1.Count; i++) 
{ 
    cmnd.Parameters.AddWithValue("@params" , array1[i]); 
} 

con.open(). 
cmnd.ExecuteNonQuery(); 

請有人請解釋我做錯了什麼。我還需要確保防止SQL注入。

+0

你不能這樣做,基本上是這樣。您將不得不動態生成SQL,或者使用不同的參數值多次執行相同的(單個)插入操作。 – Blorgbeard

+0

@Blorgbeard我可以做些什麼,比如'... VALUES @ param1,@ param2 ...'而不是'... VALUES(10),(20)...'? –

+0

有沒有理由不能只運行插入X次? –

回答

1

加入int數組格式化根據@params參數:

int[] intArr = { 10, 20, 30 }; 
string intStr = string.Join(",", intArr.Select(i => "(" + i.ToString() + ")")); 

intStr是其中傳遞給SQL形式(10),(20),(30)。創建動態語句並執行它。

-- declared here for sample 
declare @params varchar(50) = '(10),(20),(30)' 

declare @sql varchar(max) = 
    'declare @a table (id int)' + ';' + 
    'insert into @a (id) values ' + @params + ';' + 
    'exec sp @a' 

exec (@sql) 
+0

這將防止SQL注入? –

1

您可以使用爲您的值子句生成動態SQL。這會導致一些性能開銷,取決於由於糟糕的計劃緩存重用而導致此代碼運行的頻率。

我會將數組作爲分隔字符串傳遞給過程,並使用SQL字符串分隔符將字符串轉換爲表。這允許您將一個參數傳遞給過程,並可能繞過UDT。

有許多可用於網頁搜索的字符串分隔符。任何你發現使用循環會很慢,但會起作用。我個人更喜歡Jeff Moden的內聯表值函數[DelimitedSplit8K](需要免費註冊,但我認爲它非常值得),這可能是最快的TSQL字符串分離器。

使用任何分離器將與此類似:

DECLARE @a udt; 
INSERT INTO @a([id]) 
SELECT [Item] 
FROM [dbo].[DelimitedSplit8K](@params) 

這將轉換{} 10,20,30,40,50,60一個表,每行一個值。

另一個用途是用於連接:

SELECT 
    [col1], 
    [col2], 
    [ItemNumber] -- position in array 
FROM [dbo].[MyTable] A 
INNER JOIN [dbo].[DelimitedSplit8K](@params) B 
ON  A.[col3] = B.[Item] -- join on array value 
+0

另一個拆分功能 - http://dotnetprof.blogspot.in/2012/08/split-function-sql.html – niksofteng

1

你接近你的解決方案,但你需要明確地引用每個數組索引參數的SQL字符串。例如:

List<int> tests = new List<int>() { 10, 11, 12}; 
    var command = new MySqlCommand(); 
    List<string> parameterNames = new List<string>(); 
    for (int i = 0; i < tests.Count; i++) 
    { 
      string parameterName = String.Format("@test{0}", i); 
      command.Parameters.AddWithValue(parameterName, tests[i]); 
      parameterNames.Add("(" + parameterName + ")"); 
    } 
    string insertSql = @"insert into test(id) values {0}"; 
    command.CommandText = String.Format(insertSql, String.Join(", ", parameterNames)); 
    command.Connection = connection; 

    int result = command.ExecuteNonQuery(); 

生成的SQL命令文本將是:

"insert into test(id) values (@test0), (@test1), (@test2)" 
+0

爲什麼要在單個語句中完成循環。看到我的答案。 – niksofteng

+0

這種方法的問題是,您不能有超過2100個參數。 –