Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Как сохранить изменения в базе данных: использование Commit в Delphi и Pascal

Delphi , Базы данных , SQL

 

При работе с базами данных в Delphi и Pascal разработчики часто сталкиваются с ошибкой "database is locked" (база данных заблокирована). Эта проблема особенно актуальна при переходе с локальных форматов данных (как TDbf) на SQLite. В этой статье мы разберем причины этой ошибки и покажем правильные способы работы с транзакциями в SQLite.

Проблема: база данных остается заблокированной

Как видно из обсуждения на форуме, пользователь столкнулся с ситуацией, когда после добавления записей и закрытия приложения изменения не сохранялись, а при повторном запуске возникала ошибка "database is locked". Основная причина - неправильное завершение работы с базой данных.

Решение: правильное использование транзакций

1. Основной подход с явным Commit

Перед закрытием приложения необходимо явно завершать транзакции:

procedure TFrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  // Закрываем запросы
  if QryMain.Active then
    QryMain.Close;

  // Завершаем транзакцию
  if SQLTransaction1.Active then
  begin
    try
      SQLTransaction1.Commit;
    except
      on E: Exception do
      begin
        // В случае ошибки выполняем откат
        SQLTransaction1.Rollback;
        ShowMessage('Ошибка при сохранении данных: ' + E.Message);
      end;
    end;
  end;

  // Закрываем соединение
  if SQLite3Connection1.Connected then
    SQLite3Connection1.Connected := False;
end;

2. Автоматический Commit через настройки запроса

Более простой способ - использование автоматического Commit:

procedure TFrmMain.FormCreate(Sender: TObject);
begin
  SQLQuery1.Options := [sqoAutoApplyUpdates, sqoAutoCommit];
  // Другие настройки...
end;

Важные рекомендации

  1. Одно соединение на базу данных:
// Неправильно (для SQLite):
ConnectContacts := TSQLite3Connection.Create(nil);
ConnectCountries := TSQLite3Connection.Create(nil);

// Правильно:
DBConnection := TSQLite3Connection.Create(nil); // Одно соединение для всех запросов
  1. Разделение логики доступа к данным:
    Создайте отдельный модуль данных (DataModule)
    Разместите там соединение и транзакцию
    Все формы должны работать через этот модуль
  2. Пример модуля данных:

unit DataModuleUnit;

interface

uses
  SysUtils, Classes, SQLite3Conn, SQLDB, DB;

type
  TDataModule1 = class(TDataModule)
    SQLite3Connection1: TSQLite3Connection;
    SQLTransaction1: TSQLTransaction;
    procedure DataModuleCreate(Sender: TObject);
    procedure DataModuleDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  DataModule1: TDataModule1;

implementation

{$R *.dfm}

procedure TDataModule1.DataModuleCreate(Sender: TObject);
begin
  SQLite3Connection1.DatabaseName := 'my_database.sqlite';
  SQLite3Connection1.Connected := True;
  SQLTransaction1.Active := True;
end;

procedure TDataModule1.DataModuleDestroy(Sender: TObject);
begin
  if SQLTransaction1.Active then
    SQLTransaction1.Commit;
  SQLite3Connection1.Connected := False;
end;

end.
  1. Работа с несколькими таблицами:
// В модуле данных добавляем запросы
SQLQueryContacts: TSQLQuery;
SQLQueryCountries: TSQLQuery;

// Настройка запросов
procedure TDataModule1.SetupQueries;
begin
  SQLQueryContacts.Database := SQLite3Connection1;
  SQLQueryContacts.Transaction := SQLTransaction1;
  SQLQueryContacts.SQL.Text := 'SELECT * FROM Contacts';

  SQLQueryCountries.Database := SQLite3Connection1;
  SQLQueryCountries.Transaction := SQLTransaction1;
  SQLQueryCountries.SQL.Text := 'SELECT * FROM Countries';
end;

Работа с формами редактирования

Для форм редактирования справочников (стран, категорий и т.д.) используйте следующий подход:

procedure TMainForm.OpenCountriesForm(Sender: TObject);
var
  FrmCountries: TFrmCountries;
begin
  FrmCountries := TFrmCountries.Create(nil);
  try
    // Передаем подключение к данным
    FrmCountries.SetDataModule(DataModule1);
    FrmCountries.ShowModal;
  finally
    FrmCountries.Free;
  end;
end;

Логирование SQL-запросов

Для отладки добавьте логирование:

procedure TDataModule1.SQLite3Connection1Log(Sender: TSQLConnection;
  EventType: TDBEventType; const Msg: String);
var
  LogFile: TextFile;
begin
  AssignFile(LogFile, 'sql_log.txt');
  if FileExists('sql_log.txt') then
    Append(LogFile)
  else
    Rewrite(LogFile);

  try
    WriteLn(LogFile, FormatDateTime('yyyy-mm-dd hh:nn:ss', Now) + ' - ' + Msg);
  finally
    CloseFile(LogFile);
  end;
end;

// Включите логирование при создании модуля
SQLite3Connection1.LogEvents := LogAllEvents;
SQLite3Connection1.OnLog := @SQLite3Connection1Log;

Заключение

Основные правила работы с SQLite в Delphi:
1. Используйте одно соединение на базу данных
2. Всегда завершайте транзакции (Commit/Rollback) перед закрытием
3. Разделяйте логику доступа к данным и пользовательский интерфейс
4. Для простых случаев используйте автоматический Commit
5. Добавляйте логирование для отладки проблем

Следуя этим рекомендациям, вы избежите ошибок "database is locked" и других проблем при работе с SQLite в Delphi и Lazarus.

Создано по материалам из источника по ссылке.

Описание проблемы и методов сохранения изменений в базах данных SQLite в Delphi и Pascal с использованием транзакций Commit.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: SQL ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-07-27 03:04:56/0.0059349536895752/0