Как перевести определение таблицы из MS Access в Oracle, используя C # и OleDbConnection? - PullRequest
0 голосов
/ 13 марта 2019

Мне нужно скопировать таблицу из MS Access в Oracle без использования OracleBulkCopy (с использованием управляемого доступа к данным). Первый шаг - создать таблицу.

Как видно из приведенного ниже кода, я теперь преобразовываю поля вручную, запрашивая длину столбца.

Я хотел бы использовать оператор, который преобразует поля для меня, не добавляя правила для всех типов вручную, поскольку существует много типов. Или, лучше, просто извлеките какой-нибудь DDL, который я могу выполнить в Oracle. Возможно ли это?

            private int GetLength(string accessTableName, string columnName, OleDbConnection accessConnection)
            {
                columnName = $"[{columnName}]";
                var accessCommand = new OleDbCommand($"select max(len({columnName})) from {accessTableName}", accessConnection);
                return int.Parse(accessCommand.ExecuteScalar().ToString());
            }

            private void CreateEmptyTable(DataTable schemaTable, string tableName, OracleConnection oracleConnection, string accessTableName, OleDbConnection accessConnection)
            {
                var columnSpecs = new string[schemaTable.Rows.Count];
                for (int i = 0; i < schemaTable.Rows.Count; ++i)
                {
                    var name = schemaTable.Rows[i].ItemArray[0].ToString();
                    var dataType = schemaTable.Rows[i].ItemArray[5];
                    //var length = schemaTable.Rows[i].ItemArray[2];
                    var length = GetLength(accessTableName, name.ToString(), accessConnection);

                    var precision = schemaTable.Rows[i].ItemArray[3];
                    var scale = schemaTable.Rows[i].ItemArray[4];

                    var oracleDt = "";
                    switch (dataType.ToString())
                    {
                        case "System.String":
                            oracleDt = $"nchar({length})";
                            break;
                        case "System.Int32":
                        case "System.Int16":
                            var iLng = int.Parse(length.ToString()) * 2;
                            oracleDt = $"number({iLng},0)";
                            break;
                        case "System.Double":
                        case "System.Decimal":
                            oracleDt = $"number({length},{precision})";
                            break;
                        default:
                            throw new Exception();
                    }

                    name = name.ToString().ToUpper().Replace(' ', '_');

                    columnSpecs[i] = $"{name} {oracleDt}";
                }

                var query = $"create table MDB_{tableName.ToUpper().Replace(' ', '_')} ( {string.Join(",", columnSpecs)} )";

                var oracleCommand = new OracleCommand(query, oracleConnection);
                oracleCommand.ExecuteNonQuery();
            }

Ответы [ 2 ]

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

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

Итак, попробуйте что-то вроде этого:

DoCmd.TransferDatabase acExport, "ODBC Database", strCon,
           acTable, "tblHotels2", "tblHotelEXPORT", True

Теперь выше из Access, но ваш опубликованный ответ находится на правильном пути.

Когда я отправляю выше на сервер SQL, длинные, деньги, заметки, текстовые файлы отправляются и создаются на сервере SQL. Я полагаю, что вы могли бы использовать выше, а затем выполнить серию таблицы изменения, чтобы изменить типы, но это было бы больно.

Так что, прежде чем приступить к боли, я бы попробовал выше. Обратите внимание, что: Я использовал команду передачи для базовой таблицы, а не для запроса. В качестве последнего значения я использовал «True», что означает отсутствие копирования данных, а просто структуру.

Вы также можете попробовать / протестировать другой драйвер ORACLE odbc. У меня нет тестового сервера Oracle, но отправка вышеупомянутого на сервер SQL - он проделал ОЧЕНЬ хорошую работу по созданию типов данных на стороне сервера.

0 голосов
/ 15 марта 2019

Эта опция вместо этого использует Interop, но результат разочаровывает.Числовые поля преобразованы в VARCHAR2, другие типы еще не проверены.Обратите внимание, что для этого также требуется DSN-файл и драйверы Oracle ODBC.

Для тех, кто мог бы использовать это, вот код:

public void CreateTableDefsUsingInterop(string accessFilePath, string accessTable, string oracleUser, string oraclePassword, string oracleTable, string oracleDSNFilePath)
{
    var strConn = $"ODBC;FILEDSN={oracleDSNFilePath};UID={oracleUser};PWD={oraclePassword}";
    var sTypExprt = "ODBC Database";

    var interop = new Application();
    interop.OpenCurrentDatabase(accessFilePath);
    var db = interop.CurrentDb();
    var emptyTable = $"n{accessTable}";
    QueryDef qd;

    qd = db.CreateQueryDef("access2ora1", $"select top 1 * into [{emptyTable}] from [{accessTable}]");
    qd.Execute();

    qd = db.CreateQueryDef("access2ora2", $"delete from [{emptyTable}]");
    qd.Execute();

    interop.DoCmd.TransferDatabase(AcDataTransferType.acExport, sTypExprt, strConn, AcObjectType.acTable, emptyTable, oracleTable);

    interop.Quit(AcQuitOption.acQuitSaveNone);
}
...