使用 ManagedDataAccess 将记录从 MS Access table 导入 Oracle table 的最快方法
Fastest way to import records from MS Access table into Oracle table using ManagedDataAccess
我需要使用 C# 和 Oracle.ManagedDataAccess 将大量记录从 MS Access table 导入 Oracle table。
假设 table 已经存在,将记录从 Access 复制到 Oracle 的最快方法是什么?
我现在正在使用 OleDbConnection,但如果有使用 Interop、VBA 和 sqlloader 的更快方法,我也愿意接受。
到目前为止,这是我的代码。不幸的是,它需要几天才能完成,而本该需要几分钟的时间。
private void CopyRecords(DataTable schemaTable, string tableName, OleDbDataReader accessReader, OracleConnection oracleConnection)
{
if (!accessReader.HasRows)
{
return;
}
var oracleTableName = tableName.ToUpper().Replace(' ', '_');
var statements = new List<string>();
var query = "";
OracleCommand oracleCommand;
while (accessReader.Read())
{
var valueSpecs = new string[schemaTable.Rows.Count];
var fieldSpecs = new string[schemaTable.Rows.Count];
for (int i = 0; i < schemaTable.Rows.Count; ++i)
{
var name = schemaTable.Rows[i].ItemArray[0];
var fieldName = name.ToString().ToUpper().Replace(' ', '_');
var dataType = schemaTable.Rows[i].ItemArray[5];
var value = "";
switch (dataType.ToString())
{
case "System.String":
value = $"'{accessReader[i]}'";
break;
case "System.Int32":
case "System.Int16":
case "System.Double":
case "System.Decimal":
value = accessReader[i].ToString();
if (value.Length < 1)
{
value = "0";
}
break;
default:
throw new Exception();
}
valueSpecs[i] = value;
fieldSpecs[i] = fieldName;
}
var fields = string.Join(",", fieldSpecs);
var values = string.Join(",", valueSpecs);
var statement = $"INSERT INTO MDB_{oracleTableName} ({fields}) VALUES ({values})";
statements.Add(statement);
if (statements.Count >= 10000)
{
query = $"BEGIN\r\n{string.Join(";\r\n", statements)};\r\nEND;";
oracleCommand = new OracleCommand(query, oracleConnection);
oracleCommand.ExecuteNonQuery();
}
}
query = $"BEGIN\r\n{string.Join(";\r\n", statements)};\r\nEND;";
oracleCommand = new OracleCommand(query, oracleConnection);
oracleCommand.ExecuteNonQuery();
}
您为每一行创建一个 INSERT 语句,这基本上是最慢的方法。
看看 "prepared statements",会类似于:
// Prepare the statement
var statement = $"INSERT INTO MDB_{oracleTableName} ({fields}) VALUES (:p0";
for (int i = 1; i < fieldSpecs.Count; ++i) {
statement = statement + ",:p1";
}
statement = statement + ")";
var cmd = new OracleCommand(statement, oracleConnection);
// Add parameters
for (int i = 0; i < fieldSpecs.Count; ++i) {
cmd.Parameters.Add(String.Format("p{0}", i), OracleDbType.Varchar2);
// needs to be more advanced in order to cover also other data types, not just Varchar2
}
// Assign parameter values and execute
while (accessReader.Read()) {
for (int i = 0; i < fieldSpecs.Count; ++i) {
cmd.Parameters[i].Value = accessReader[i];
}
cmd.ExecuteNonQuery();
}
我需要使用 C# 和 Oracle.ManagedDataAccess 将大量记录从 MS Access table 导入 Oracle table。 假设 table 已经存在,将记录从 Access 复制到 Oracle 的最快方法是什么? 我现在正在使用 OleDbConnection,但如果有使用 Interop、VBA 和 sqlloader 的更快方法,我也愿意接受。
到目前为止,这是我的代码。不幸的是,它需要几天才能完成,而本该需要几分钟的时间。
private void CopyRecords(DataTable schemaTable, string tableName, OleDbDataReader accessReader, OracleConnection oracleConnection)
{
if (!accessReader.HasRows)
{
return;
}
var oracleTableName = tableName.ToUpper().Replace(' ', '_');
var statements = new List<string>();
var query = "";
OracleCommand oracleCommand;
while (accessReader.Read())
{
var valueSpecs = new string[schemaTable.Rows.Count];
var fieldSpecs = new string[schemaTable.Rows.Count];
for (int i = 0; i < schemaTable.Rows.Count; ++i)
{
var name = schemaTable.Rows[i].ItemArray[0];
var fieldName = name.ToString().ToUpper().Replace(' ', '_');
var dataType = schemaTable.Rows[i].ItemArray[5];
var value = "";
switch (dataType.ToString())
{
case "System.String":
value = $"'{accessReader[i]}'";
break;
case "System.Int32":
case "System.Int16":
case "System.Double":
case "System.Decimal":
value = accessReader[i].ToString();
if (value.Length < 1)
{
value = "0";
}
break;
default:
throw new Exception();
}
valueSpecs[i] = value;
fieldSpecs[i] = fieldName;
}
var fields = string.Join(",", fieldSpecs);
var values = string.Join(",", valueSpecs);
var statement = $"INSERT INTO MDB_{oracleTableName} ({fields}) VALUES ({values})";
statements.Add(statement);
if (statements.Count >= 10000)
{
query = $"BEGIN\r\n{string.Join(";\r\n", statements)};\r\nEND;";
oracleCommand = new OracleCommand(query, oracleConnection);
oracleCommand.ExecuteNonQuery();
}
}
query = $"BEGIN\r\n{string.Join(";\r\n", statements)};\r\nEND;";
oracleCommand = new OracleCommand(query, oracleConnection);
oracleCommand.ExecuteNonQuery();
}
您为每一行创建一个 INSERT 语句,这基本上是最慢的方法。
看看 "prepared statements",会类似于:
// Prepare the statement
var statement = $"INSERT INTO MDB_{oracleTableName} ({fields}) VALUES (:p0";
for (int i = 1; i < fieldSpecs.Count; ++i) {
statement = statement + ",:p1";
}
statement = statement + ")";
var cmd = new OracleCommand(statement, oracleConnection);
// Add parameters
for (int i = 0; i < fieldSpecs.Count; ++i) {
cmd.Parameters.Add(String.Format("p{0}", i), OracleDbType.Varchar2);
// needs to be more advanced in order to cover also other data types, not just Varchar2
}
// Assign parameter values and execute
while (accessReader.Read()) {
for (int i = 0; i < fieldSpecs.Count; ++i) {
cmd.Parameters[i].Value = accessReader[i];
}
cmd.ExecuteNonQuery();
}