Русский
Русский
English
Статистика
Реклама

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

SQLite во многих случаях является удобным, незаменимым инструментом. Я уже не могу себе представить - как мы все жили без него. Тем не менее, есть некоторые неудобства при его использовании, связанные с тем, что это легкая встраиваемая СУБД.

Самое большое неудобство для меня, как Delphi-разработчика - отсутствие хранимых процедур. Я очень не люблю смешивать Delphi-код и SQL-скрипты. Это делает код намного менее читабильным, и затрудняет его поддержку. Следовательно, нужно как-то разнести код Delphi и тексты SQL-скриптов.

Предлагаю свой вариант решения проблемы

  • Выносим весь SQL-код в отдельный тестовый файл ресурсов, подключенный к проекту.

  • Запросы в SQL-файле разделяем маркерами начала с идентификаторами и маркерами конца. В моём случае синтаксис маркера начала - //SQL ИмяПроцедуры. Маркер конца - GO.

  • Создаем класс - менеджер SQL-запросов. При загрузке приложения он читает SQL-файл из ресурсов и составляет из него список хранимых процедур с уникальными именами-идентификаторами.

  • В процессе работы приложения мендежер извлекает текст SQL-запроса по его идентификатору для последующей его передачи на выполнение.

Главная идея - простота и легкость использования, подобная вызову хранимых процедур и удобство при создании и модификации SQL-запросов

Код юнита менеджера запросов:

unit uSqlList;interfaceuses 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;implementationfunction 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;initializationSqlList := TSqlList.Create;finalizationFreeAndNil(SqlList);end.

Пример содержимого файла SQL-скриптов:

//SQL GetOrderSELECT * FROM Orders WHERE ID = :IDGO//SQL DeleteOpenedOrdersDELETE FROM Orders WHERE Closed = 0GO

Подключение файла скриптов к проекту:

{$R 'SqlList.res' '..\Common\DataBase\SqlList.rc'}

Использование с компонентом TFDConnection:

  Connection.ExecSQL(SqlList['GetOrder'], ['123']);

Собственно, это всё. Использую данное решение уже в нескольких проектах и мне оно кажется очень удобным. Буду благодарен за советы и замечания. Рад, если мой посто кому-то будет полезен!

Источник: habr.com
К списку статей
Опубликовано: 20.06.2021 14:08:21
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Delphi

Sqlite

Sqlite3

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru