【发布时间】:2016-12-25 02:40:30
【问题描述】:
我被要求寻找最有效的方法来获取 DataTable 输入并使用 C# 将其写入 SQL Server 表。问题是解决方案必须始终使用 ODBC 连接,这排除了 sqlBulkCopy。该解决方案还必须适用于 SQL Server 2008 R2 之前的所有 SQL Server 版本。
我认为最好的方法是使用以下 SQL 语法一次使用 1000 行的批量插入:
插入到 dbo.Table1(字段 1,字段 2) 选择值 1,值 2 联盟 选择值1,值2
我已经编写了代码来检查与 DataTable 输入对应的表是否已经存在于 SQL Server 上,如果不存在则创建一个。
我还编写了代码来创建 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;
}
}
任何建议将不胜感激。此外,如果有比我建议的更简单的方法,那么任何细节都会很棒。
【问题讨论】:
-
您是否也排除了 ADO.net 表参数?这是一个奇怪的限制,因为将 Table 参数传递给存储过程并在传入的表上使用 MERGE 命令是迄今为止实现这一点的最有效方法。
-
问题是我们将在我们正在写入的 SQL Server 上拥有非常有限的权限。我们在桌子上有 CRUD,仅此而已。恐怕任何涉及存储过程和/或 TVP 的解决方案都不在范围内。
标签: c# sql-server odbc batching