Если вы разработчик, вы можете разработать приложение для выполнения синхронизации.Вы должны сделать
SELECT name FROM sqlite_master WHERE type='table'
, чтобы получить имена таблиц, затем вы можете воссоздать их в Oracle (сначала вы можете сделать 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)
}
A StringBuilder
можно использовать для сбораимя таблицы с ее столбцами для создания вашей команды INSERT
.Чтобы добавить значения, нужно просто сделать SELECT * FROM MyTable
для каждой из таблиц во время вашего цикла по именам таблиц, которые вы получили в результате первоначального запроса.Вы бы перебрали столбцы строк возвращаемой вами таблицы данных и добавили бы значения в StringBuilder
:
INSERT INTO MyTable (
+ columnA, columnB и т. Д. + ) VALUES (
datarow [0], datarow[1] и т. Д. + )
.
Не совсем так, хотя - вы заполняете данные, добавляя имя столбца и его данные, проходя через циклы.Вы можете получить имена столбцов, добавив s
в этот цикл foreach
выше.Каждое значение столбца затем устанавливается с помощью цикла foreach
, который дает вам каждый object obj in drData.ItemArray
.Если все, что у вас есть, это строковые поля, это просто, вы просто добавляете 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()
void, которая может принятьSQL-команду и запустите ее для базы данных Oracle и функции GetSQLiteTable()
, которая может возвратить DataTable из вашей базы данных SQLite, передав ей команду SQL.
Обратите внимание, что этот код не проверен, поскольку я написал его напрямуюв этом посте, но он в значительной степени основан на коде, который я написал для синхронизации Oracle в SQLite, который был протестирован и работает.