[英]Batch insert to SQL Server table from DataTable using ODBC Connection
我被要求尋找最有效的方法來獲取DataTable輸入並使用C#將其寫入SQL Server表。 問題在於解決方案必須始終使用ODBC連接,這排除了sqlBulkCopy。 該解決方案還必須適用於SQL Server 2008 R2的所有SQL Server版本。
我認為最好的方法是使用以下SQL語法一次使用1000行的批量插入:
INSERT INTO dbo.Table1(Field1,Field2)SELECT Value1,Value2 UNION SELECT Value1,Value2
我已經編寫了代碼,檢查SQL Server上是否已存在與DataTable輸入相對應的表,如果不存在則創建一個表。
我還編寫了代碼來創建INSERT語句本身。 我正在努力的是如何從數據表中的行動態構建SELECT語句。 如何訪問行中的值以構建我的SELECT語句? 我想我還需要檢查每列的數據類型,以確定值是否需要用單引號(')括起來。
這是我目前的代碼:
public bool CopyDataTable(DataTable sourceTable, OdbcConnection targetConn, string targetTable)
{
OdbcTransaction tran = null;
string[] selectStatement = new string[sourceTable.Rows.Count];
// Check if targetTable exists, create it if it doesn't
if (!TableExists(targetConn, targetTable))
{
bool created = CreateTableFromDataTable(targetConn, sourceTable);
if (!created)
return false;
}
try
{
// Prepare insert statement based on sourceTable
string insertStatement = string.Format("INSERT INTO [dbo].[{0}] (", targetTable);
foreach (DataColumn dataColumn in sourceTable.Columns)
{
insertStatement += dataColumn + ",";
}
insertStatement += insertStatement.TrimEnd(',') + ") ";
// Open connection to target db
using (targetConn)
{
if (targetConn.State != ConnectionState.Open)
targetConn.Open();
tran = targetConn.BeginTransaction();
for (int i = 0; i < sourceTable.Rows.Count; i++)
{
DataRow row = sourceTable.Rows[i];
// Need to iterate through columns in row, getting values and data types and building a SELECT statement
selectStatement[i] = "SELECT ";
}
insertStatement += string.Join(" UNION ", selectStatement);
using (OdbcCommand cmd = new OdbcCommand(insertStatement, targetConn, tran))
{
cmd.ExecuteNonQuery();
}
tran.Commit();
return true;
}
}
catch
{
tran.Rollback();
return false;
}
}
任何建議將不勝感激。 此外,如果有一個比我建議的更簡單的方法,那么任何細節都會很棒。
好的,因為我們不能使用存儲過程或批量復制; 幾年前,當我模擬各種方法時,性能的關鍵決定因素是對服務器的調用次數。 因此,將一組MERGE或INSERT語句批處理為由分號分隔的單個調用被發現是最快的方法。 我最終批處理我的SQL語句。 我認為SQL語句的最大大小是32k所以我把我的批量切成了那個大小的單位。
(注意 - 使用StringBuilder而不是手動連接字符串 - 它對性能有益)
Psuedo-code
string sqlStatement = "INSERT INTO Tab1 VALUES {0},{1},{2}";
StringBuilder sqlBatch = new StringBuilder();
foreach(DataRow row in myDataTable)
{
sqlBatch.AppendLine(string.Format(sqlStatement, row["Field1"], row["Field2"], row["Field3"]));
sqlBatch.Append(";");
}
myOdbcConnection.ExecuteSql(sqlBatch.ToString());
您需要處理批量大小的復雜性,並在字符串替換步驟中格式化正確的字段數據類型,否則這將是最佳性能。
PhillipH的標記解決方案可以解決幾個錯誤和SQL注入問題。
通常,您應該使用參數構建DbCommand
並執行此操作,而不是執行自構建SQL語句。
CommandText必須是"INSERT INTO Tab1 VALUES ?,?,?"
對於ODBC和OLEDB,SqlClient需要命名參數(“@ <Name>”)。
應使用下墊列的尺寸添加參數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.