[Delphi, SQLite] Delphi и SQLite. Альтернатива хранимым процедурам

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
20-Июн-2021 16:33

SQLite во многих случаях является удобным, незаменимым инструментом. Я уже не могу себе представить - как мы все жили без него. Тем не менее, есть некоторые неудобства при его использовании, связанные с тем, что это легкая встраиваемая СУБД.Самое большое неудобство для меня, как Delphi-разработчика - отсутствие хранимых процедур. Я очень не люблю смешивать Delphi-код и SQL-скрипты. Это делает код намного менее читабильным, и затрудняет его поддержку. Следовательно, нужно как-то разнести код Delphi и тексты SQL-скриптов.Предлагаю свой вариант решения проблемы
  • Выносим весь SQL-код в отдельный тестовый файл ресурсов, подключенный к проекту.
  • Запросы в SQL-файле разделяем маркерами начала с идентификаторами и маркерами конца. В моём случае синтаксис маркера начала - //SQL ИмяПроцедуры. Маркер конца - GO.
  • Создаем класс - менеджер SQL-запросов. При загрузке приложения он читает SQL-файл из ресурсов и составляет из него список хранимых процедур с уникальными именами-идентификаторами.
  • В процессе работы приложения мендежер извлекает текст SQL-запроса по его идентификатору для последующей его передачи на выполнение.
Главная идея - простота и легкость использования, подобная вызову хранимых процедур и удобство при создании и модификации SQL-запросовКод юнита менеджера запросов:
unit uSqlList;
interface
uses System.Classes, Winapi.Windows, System.SysUtils,
  System.Generics.Collections;
type
  TSqlList = class(TObjectDictionary<string, TStrings>)
  const
    SCRIPTS_RCNAME = 'SqlList';
  private
    function GetScripts(const AName: string): TStrings;
    procedure FillList;
    function GetItem(const AKey: string): string;
  public
    constructor Create;
  public
    property Sql[const Key: string]: string read GetItem; default;
  end;
var
  SqlList: TSqlList;
implementation
function GetStringResource(const AName: string): string;
var
  LResource: TResourceStream;
begin
  LResource := TResourceStream.Create(hInstance, AName, RT_RCDATA);
  with TStringList.Create do
    try
      LoadFromStream(LResource);
      Result := Text;
    finally
      Free;
      LResource.Free;
    end;
end;
{ TScriptList }
constructor TSqlList.Create;
begin
  inherited Create([doOwnsValues]);
  FillList;
end;
procedure TSqlList.FillList;
var
  LScripts: TStrings;
  I: Integer;
  S, LKey: string;
  LStarted: Boolean;
  LSql: TStrings;
begin
  LScripts := GetScripts(SCRIPTS_RCNAME);
  try
    LStarted := False;
    LSql := nil;
    for I := 0 to LScripts.Count - 1 do
    begin
      S := LScripts[I];
      if LStarted then
      begin
        if S = 'GO' then
        begin
          LStarted := False;
          Continue;
        end
        else if not S.StartsWith('//') then
          LSql.Add(S);
      end
      else
      begin
        LStarted := S.StartsWith('//SQL ');
        if LStarted then
        begin
          LKey := S.Substring(6);
          LSql := TStringList.Create;
          Add(LKey, LSql);
        end;
        Continue;
      end;
    end;
  finally
    LScripts.Free;
  end;
end;
function TSqlList.GetItem(const AKey: string): string;
begin
  Result := Items[AKey].Text;
end;
function TSqlList.GetScripts(const AName: string): TStrings;
begin
  Result := TStringList.Create;
  try
    Result.Text := GetStringResource(AName);
  except
    FreeAndNil(Result);
    raise;
  end;
end;
initialization
SqlList := TSqlList.Create;
finalization
FreeAndNil(SqlList);
end.
Пример содержимого файла SQL-скриптов:
//SQL GetOrder
SELECT * FROM Orders WHERE ID = :ID
GO
//SQL DeleteOpenedOrders
DELETE FROM Orders WHERE Closed = 0
GO
Подключение файла скриптов к проекту:
{$R 'SqlList.res' '..\Common\DataBase\SqlList.rc'}
Использование с компонентом TFDConnection:
Connection.ExecSQL(SqlList['GetOrder'], ['123']);
Собственно, это всё. Использую данное решение уже в нескольких проектах и мне оно кажется очень удобным. Буду благодарен за советы и замечания. Рад, если мой посто кому-то будет полезен!
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_delphi, #_sqlite, #_delphi, #_sqlite, #_sqlite3, #_delphi, #_sqlite
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 12:44
Часовой пояс: UTC + 5