我有一个SQLite数据库在一个系统中,我需要将存储在SQLite中的数据提取到Oracle数据库中。我该怎么做?
.dump
命令将其转储到文本文件中(有关语法,请参见文档)。SQL Loader是一个实用程序,它可以读取分隔符文本文件并将其导入Oracle数据库。您需要映射每个列从SQLite的扁平文件匹配到Oracle数据库中相应的列。这里有一个很好的FAQ,应该可以帮助您入门。
SELECT name FROM sqlite_master WHERE type='table'
DROP TABLE tablename
在Oracle中重新创建它们(假设SQLite将是权威的),并使用CREATE TABLE
命令。获取每个表的列需要执行以下操作:
SELECT sql FROM sqlite_master WHERE type='table' and name='MyTable'
string columnNames = sql.replace(/^[^\(]+\(([^\)]+)\)/g, '$1').replace(/ [^,]+/g, '').split(',');
string[] columnArray = columnNames.Split(',');
foreach (string s in columnArray)
{
// Add column to table using:
// ALTER TABLE MyTable ADD COLUMN s NVARCHAR(250)
}
StringBuilder
可用于收集表名及其列以创建 INSERT
命令。要添加值,只需在循环遍历从初始查询返回的表名时,对每个表执行 SELECT * FROM MyTable
即可。您将迭代返回的数据表的行的列,并将值添加到 StringBuilder
中:
INSERT INTO MyTable (
+ columnA、columnB 等 + ) VALUES (
datarow[0]、datarow[1] 等 + )
。
不完全像那样,你需要在循环中通过追加列名和数据来填充数据。你可以通过在上面的foreach
循环中追加s
来获取列名。然后使用一个foreach
循环来设置每个列值,该循环会给你drData.ItemArray
中的每个object obj
。如果所有字段都是字符串类型,那么很容易,只需像下面一样将obj.ToString()
添加到查询中每个列值的StringBuilder
中。然后在收集每行的所有列值后运行查询。对于每一行,你需要使用一个新的StringBuilder
- 在每个新行之前,它需要被重置为INSERT INTO MyTable (
+ columnA、columnB等 + ) VALUES (
,以便可以追加新的列值。
DATE
,BLOB
等),则需要在途中确定列类型,将其存储在列表或数组中,然后使用计数器确定该列表/数组插槽的索引并获取类型,以便知道如何将对象转换为Oracle可以使用的内容 - 无论是仅将to_date()
添加到结果中进行格式化日期(因为SQLite将这些存储为具有格式yyyy-MM-dd HH:mm:ss
的日期字符串),还是将其添加到OracleParameter
中用于BLOB
,并将其发送到RunOracleCommand
函数。(下面没有涉及此问题。)string[] columnArray = null;
DataTable dtTableNames = GetSQLiteTable("SELECT name FROM sqlite_master WHERE type='table'");
if (dtTableNames != null && dtTableNames.Rows != null)
{
if (dtTableNames.Rows.Count > 0)
{
// We have tables
foreach (DataRow dr in dtTableNames.Rows)
{
// Do everything about this table here
StringBuilder sb = new StringBuilder();
sb.Append("INSERT INTO " + tableName + " ("); // we will collect column names here
string tableName = dr["NAME"] != null ? dr["NAME"].ToString() : String.Empty;
if (!String.IsNullOrEmpty(tableName))
{
RunOracleCommand("DROP TABLE " + tableName);
RunOracleCommand("CREATE TABLE " + tableName);
}
DataTable dtColumnNames = GetSQLiteTable("SELECT sql FROM sqlite_master WHERE type='table' AND name='"+tableName+"'");
if (dtColumnNames != null && dtColumnNames.Rows != null)
{
if (dtColumnNames.Rows.Count > 0)
{
// We have columns
foreach (DataRow drCol in dtTableNames.Rows)
{
string sql = drCol["SQL"] != null ? drCol["SQL"].ToString() : String.Empty;
if (!String.IsNullOrEmpty(sql))
{
string columnNames = sql.replace(/^[^\(]+\(([^\)]+)\)/g, '$1').replace(/ [^,]+/g, '').split(',');
columnArray = columnNames.Split(',');
foreach (string s in columnArray)
{
// Add column to table using:
RunOracleCommand("ALTER TABLE " + tableName + " ADD COLUMN " + s + " NVARCHAR(250)"); // can hard-code like this or use logic to determine the datatype/column width
sb.Append("'" + s + "',");
}
sb.TrimEnd(",");
sb.Append(") VALUES (");
}
}
}
}
// Get SQLite Table data for insertion to Oracle
DataTable dtTableData = GetSQLiteTable("SELECT * FROM " + tableName);
if (dtTableData != null && dtTableData.Rows != null)
{
if (dtTableData.Rows.Count > 0)
{
// We have data
foreach (DataRow drData in dtTableData.Rows)
{
StringBuilder sbRow = sb; // resets to baseline for each row
foreach (object obj in drData.ItemArray)
{
// This is simplistic and assumes you have string data for an NVARCHAR field
sbRow.Append("'" + obj.ToString() + "',");
}
sbRow.TrimEnd(",");
sbRow.Append(")");
RunOracleCommand(sbRow.ToString());
}
}
}
}
}
}
所有这些都假定您有一个RunOracleCommand()
无返回值函数,可以接受 SQL 命令并将其针对 Oracle DB 运行,以及一个GetSQLiteTable()
函数,通过传递 SQL 命令可以从您的 SQLite DB 返回 DataTable。
请注意,此代码未经测试,因为我直接在此帖子中编写了它,但它基于我编写的用于将 Oracle 同步为 SQLite 的代码,已经过测试并且有效。