sopy7 Ответов: 2

Базы данных SQLite: копирование данных из таблицы всех данных db1 в DB2 таблицы


Я столкнулся с требованием миграции данных. Если есть изменения в структуре БД, я должен сначала взять копию БД, а затем удалить эту существующую БД, создать новую БД с тем же именем и сбросить все данные из скопированной БД в новую БД.

Для реализации вышеупомянутой задачи я планировал создать консольное приложение или службу Windows с использованием языка C#.

Что я уже пробовал:

Я могу скопировать БД во временное местоположение с помощью
BackupDatabase
способ получения
System.Data.SQLite


Что касается восстановления данных в новую БД...

Используется ниже команда SQLite в браузере SQLite для копирования данных одной таблицы

END TRANSACTION;
ATTACH 'C:\Program Files\DB Browser for SQLite\TestDB.db' AS SourceDB;
ATTACH 'D:\Documents\Demo Applications\Windows\WindowsFormsApplication_SQLite\Database\TestDB.db' AS DestDB;
BEGIN TRANSACTION;
INSERT INTO DestDB.TestEmployee SELECT * FROM SourceDB.TestEmployee;
COMMIT;


Но я не уверен, как выполнить описанную выше операцию со всеми таблицами, существующими в исходной БД, то есть выполнить цикл через все таблицы для копирования и вставки данных.

Другая проблема заключается в изменении структуры таблицы, т. е. если таблица a1 имеет два столбца в резервной БД (из которой я должен скопировать данные) и таблица A1 целевой БД имеет 3 столбца (т. е. один новый столбец) , то запрос, упомянутый в Примере, не дает ошибки: таблица DestDB.TestEmployee имеет 3 колонки, но только 2 значения

Как можно справиться с этим несоответствием столбцов или есть еще один элегантный способ переноса данных из одной БД в другую?

2 Ответов

Рейтинг:
10

sopy7

Я нашел решение..

Чтобы решить проблему различий в структуре таблиц, я веду отдельную таблицу с именем dbShema, которая содержит два столбца "TableName" и "Columns"; в этой таблице я поддерживаю все имена таблиц и все имена столбцов, разделенные запятой в столбце "Columns".

Я извлекаю все таблицы и соответствующие им столбцы в SQLReader и перебираю их, чтобы создать динамический запрос вставки SQLite. Затем я выполнить этот запрос, чтобы скопировать данные из источника в точку ДБ.

Код:

StringBuilder strSql = new StringBuilder();
            strSql.Append("ATTACH 'D:\\Application\\Demo Applications\\Windows\\WindowsFormsApplication_SQLite\\Database\\Source\\TestDB.db' AS SourceDB;");
            strSql.Append("ATTACH 'D:\\Application\\Demo Applications\\Windows\\WindowsFormsApplication_SQLite\\Database\\Destination\\TestDB.db' AS DestDB;");
            
            using (SQLiteConnection con = new SQLiteConnection(SourceconnectionString))
            {
                con.Open();

                using (SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM dbSchema", con))
                {
                    using (SQLiteDataReader rdr = cmd.ExecuteReader())
                    {
                        while (rdr.Read()) // Reading Rows
                        {
                            strSql.Append("INSERT INTO DestDB.");
                            strSql.Append(rdr["TableName"].ToString());
                            strSql.Append(" (");
                            strSql.Append(rdr["Columns"].ToString());
                            strSql.Append(") ");
                            strSql.Append("SELECT ");
                            strSql.Append(rdr["Columns"].ToString());
                            strSql.Append(" FROM SourceDB.");
                            strSql.Append(rdr["TableName"].ToString());
                            strSql.Append(";");
                            var tableName = rdr["TableName"].ToString();
                            var Columns = rdr["Columns"].ToString();
                        }
                    }
                }
            }

            using (SQLiteConnection conn = new SQLiteConnection(DestinationConnectionString))
            {
                conn.Open();
                using (SQLiteCommand cmd = new SQLiteCommand(conn))
                {
                    cmd.CommandText = strSql.ToString();
                    int i = cmd.ExecuteNonQuery();
                    if (i > 0)
                    {
                        MessageBox.Show("Data dumped successfully ...!!!");
                    }
                }
            }


Но я использую SQLReader и stringbuilder для циклирования и конкатенации.

Есть ли более эффективный способ добиться этого ????


Рейтинг:
1

Allen Scott

Ниже приведен пример копирования данных из одной базы данных в другую

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, LiteAccess;

var
  LiteConnection: TLiteConnection;
  LiteQuery: TLiteQuery;
begin
  LiteConnection := TLiteConnection.Create(nil);
  try
    LiteConnection.Options.ForceCreateDatabase := True;
    LiteConnection.Database := 'd:\src.db3';
    LiteConnection.Connect;
    LiteConnection.ExecSQL('create table t_test (f_id integer)');
    LiteConnection.ExecSQL('insert into t_test values(1),(2),(3),(4),(5)');
    LiteConnection.Disconnect;
    LiteConnection.Database := 'd:\dst.db3';
    LiteConnection.Connect;
    LiteConnection.ExecSQL('create table t_test (f_id integer)');
    LiteConnection.ExecSQL('attach "d:\src.db3" as source');
    LiteConnection.ExecSQL('insert into main.t_test select * from source.t_test');
    LiteQuery := TLiteQuery.Create(nil);
    try
      LiteQuery.Connection := LiteConnection;
      LiteQuery.SQL.Text := 'select * from main.t_test';
      LiteQuery.Open;
      while not LiteQuery.Eof do begin
        WriteLn(LiteQuery.FieldByName('f_id').AsString);
        LiteQuery.Next;
      end;
    finally
      LiteQuery.Free;
    end;
  finally
    LiteConnection.Free;
    readln;
  end;
end.


Проверьте это также Эти полезные ссылки

Копирование данных из одной таблицы в другую в SQL Server 2008 R2[^]

sql-SQLite копирование данных из одной таблицы в другую-переполнение стека[^]

Спасибо


sopy7

Оператор insert into main.t_test select * from source.t_test предполагает, что и исходная, и целевая таблицы имеют одинаковые столбцы, но в моей ситуации целевая таблица может иметь дополнительные столбцы (т. е. В этом случае этот оператор ("insert into main.t_test select * from source.t_test" не будет работать).