C# 如何使用C和OLEDB连接将表定义从MS Access转换到Oracle?
我需要将表从MS Access复制到Oracle,而不使用OracleBulkCopy和托管数据访问。 第一步是创建表 从下面的代码中可以看出,我现在在查询列长度时手动转换字段 我想使用一个语句来转换字段,而不必手动为所有类型添加规则,因为类型很多。 或者更好,只提取某种DDL,我可以在Oracle中执行。 这可能吗C# 如何使用C和OLEDB连接将表定义从MS Access转换到Oracle?,c#,oracle,ms-access,etl,oracle.manageddataaccess,C#,Oracle,Ms Access,Etl,Oracle.manageddataaccess,我需要将表从MS Access复制到Oracle,而不使用OracleBulkCopy和托管数据访问。 第一步是创建表 从下面的代码中可以看出,我现在在查询列长度时手动转换字段 我想使用一个语句来转换字段,而不必手动为所有类型添加规则,因为类型很多。 或者更好,只提取某种DDL,我可以在Oracle中执行。 这可能吗 private int GetLength(string accessTableName, string columnName, OleDbConnecti
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();
}
此选项使用互操作,但结果令人失望。数值字段已转换为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);
}
也许您可以尝试在基表上执行命令来代替查询 因此,请尝试以下方法:
DoCmd.TransferDatabase acExport, "ODBC Database", strCon,
acTable, "tblHotels2", "tblHotelEXPORT", True
以上是Access提供的,但您发布的答案是正确的
当我将上面的内容发送到SQL server时,long、money、memo和文本文件都会发送出去并在SQL server上创建。我想您可以使用上面的代码,然后执行一系列ALTERTABLE来更改类型,但这会很痛苦
所以在疼痛来临之前,我会尝试上面的方法。请注意:
我在基表上使用了transfer命令,而不是查询。
我使用True作为最后一个值-这意味着没有数据拷贝,只有结构
您还可以尝试/测试其他ORACLE odbc驱动程序。我周围没有测试oracle服务器,但将上述内容发送到SQL server—它在服务器端创建数据类型方面做得非常好。Access没有任何内置工具生成DDL,特别是与oracle兼容的方言。简短回答:不是。数据类型nchar似乎不是一个好的选择。当您使用CHARx时,字符串将填充空格字符,我怀疑这是您想要的。现在NCHAR和NVARCHAR通常是无用的,因为数据库中的默认字符集是AL32UTF8,即UTF-8。改用简单的VARCHAR2。@Wernfrieddomschait谢谢,我不知道这会导致填充。将使用varchar2数据类型。谢谢!这就是我需要的。我将看看是否可以用C和Oracle复制这个。在我上一次尝试中,所有字段都是varchar2,但可能有一些参数我没有查看。