Самый быстрый способ импортировать записи из таблицы MS Access в таблицу Oracle, используя ManagedDataAccess - PullRequest
0 голосов
/ 13 марта 2019

Мне нужно импортировать много записей из таблицы MS Access в таблицу Oracle, используя C # и Oracle.ManagedDataAccess.Предполагая, что таблицы уже существуют, каков самый быстрый способ скопировать записи из 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();
            }

1 Ответ

1 голос
/ 13 марта 2019

Вы создаете оператор INSERT для каждой отдельной строки, это, по сути, самый медленный из возможных способов сделать это.

Посмотрите на «подготовленные операторы», это будет выглядеть так:

// 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();
}
...