[Delphi, SQLite] Delphi и SQLite. Альтернатива хранимым процедурам
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
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
===========
Похожие новости:
- Выпуск СУБД SQLite 3.36
- [Я пиарюсь] sqlite-gui: еще один редактор SQLite для Windows
- Выпуск rqlite 6.0, распределённой отказоустойчивой СУБД на основе SQLite
- [*nix, DNS, C, SQLite] The Implementation of a Custom Domain Name Server by Using С Sockets
- [Python, Программирование, SQL, Микросервисы, Flask] Чтобы первый блин не вышел комом. Советы начинающему разработчику сервиса
- [Python, SQL, Big Data, Визуализация данных, Data Engineering] Первые шаги в BI-аналитике. Роль Data Engineering
- [Программирование, Delphi, Алгоритмы, HTML, PDF] Даешь свободную литературу! Или как я с политикой вуза боролся
- [Python, Delphi, *nix, DevOps] Ansible-vault decrypt: обходимся без Ansible
- [Python, API, SQLite] Подключаем Sqlite3 к Telegram боту
- [Delphi, Разработка игр, Логические игры] Шахматы на Delphi. Как я изобретал велосипед
Теги для поиска: #_delphi, #_sqlite, #_delphi, #_sqlite, #_sqlite3, #_delphi, #_sqlite
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 06:06
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
SQLite во многих случаях является удобным, незаменимым инструментом. Я уже не могу себе представить - как мы все жили без него. Тем не менее, есть некоторые неудобства при его использовании, связанные с тем, что это легкая встраиваемая СУБД.Самое большое неудобство для меня, как Delphi-разработчика - отсутствие хранимых процедур. Я очень не люблю смешивать Delphi-код и SQL-скрипты. Это делает код намного менее читабильным, и затрудняет его поддержку. Следовательно, нужно как-то разнести код Delphi и тексты 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 GetOrder
SELECT * FROM Orders WHERE ID = :ID GO //SQL DeleteOpenedOrders DELETE FROM Orders WHERE Closed = 0 GO {$R 'SqlList.res' '..\Common\DataBase\SqlList.rc'}
Connection.ExecSQL(SqlList['GetOrder'], ['123']);
=========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 06:06
Часовой пояс: UTC + 5