При работе с базами данных в Delphi, особенно с PostgreSQL, разработчики часто сталкиваются с проблемой обработки строк, содержащих апострофы (одинарные кавычки). Рассмотрим типичную ситуацию:
Когда значение поля company содержит апостроф (например, "Jon's Store"), возникает ошибка: Syntax error at or near s. Это происходит потому, что апостроф интерпретируется как конец строкового литерала в SQL.
Почему QuotedStr не всегда помогает
Функция QuotedStr добавляет обрамляющие кавычки и удваивает внутренние апострофы:
function QuotedStr(const S: string): string;
begin
Result := '''' + StringReplace(S, '''', '''''', [rfReplaceAll]) + '''';
end;
Для "Jon's Store" результат будет: 'Jon''s Store'. Теоретически, это должно работать, но в некоторых случаях (особенно при использовании TClientDataSet или других компонентов) могут возникать проблемы.
Решение 1: Использование параметризованных запросов
Наиболее правильное решение - перейти на параметризованные запросы:
var
qry: TFDQuery;
begin
qry := TFDQuery.Create(nil);
try
qry.Connection := YourConnection; // установите соединение с БД
qry.SQL.Text := 'SELECT * FROM orders WHERE customer = :customer';
qry.ParamByName('customer').AsString := DataModule1.tblcustomercompany.Value;
qry.Open;
// Обработка результатов
while not qry.Eof do
begin
// Работа с данными
qry.Next;
end;
finally
qry.Free;
end;
end;
Преимущества:
- Защита от SQL-инъекций
- Корректная обработка специальных символов
- Более высокая производительность при повторных выполнениях
Решение 2: Использование временной связи Master/Detail
Если требуется фильтрация по связанному полю:
// Устанавливаем связь Master/Detail
DataSource1.DataSet := tblcustomer;
tblorders.MasterSource := DataSource1;
tblorders.MasterFields := 'customer_id'; // поле связи в главной таблице
tblorders.IndexFieldNames := 'customer_id'; // поле связи в подчиненной таблице
tblorders.Open;
Решение 3: Использование диапазонов (Ranges)
Для индексированных полей можно использовать SetRange:
procedure TForm1.ApplyFilter;
begin
try
tblorders.Filtered := False;
tblorders.Filter := 'customer = ' + QuotedStr(DBEdit1.Text);
tblorders.Filtered := True;
except
on E: Exception do
ShowMessage('Ошибка фильтрации: ' + E.Message);
end;
end;
Альтернативные подходы
Использование Escape-функций PostgreSQL:
qry.SQL.Text := 'SELECT * FROM orders WHERE customer = ' +
YourConnection.EscapeString(DataModule1.tblcustomercompany.Value);
Замена апострофов при вводе:
function SafeInput(const S: string): string;
begin
Result := StringReplace(S, '''', ''', [rfReplaceAll]);
end;
// При отображении:
function OriginalInput(const S: string): string;
begin
Result := StringReplace(S, ''', '''', [rfReplaceAll]);
end;
Заключение
Для надежной работы с PostgreSQL в Delphi рекомендуется:
1. Использовать параметризованные запросы вместо конкатенации строк
2. Рассмотреть возможность применения связей Master/Detail для фильтрации
3. Обрабатывать исключения при работе с пользовательским вводом
Правильный выбор метода зависит от конкретной задачи, но параметризованные запросы - это наиболее универсальное и безопасное решение.
Статья описывает методы корректной обработки апострофов в SQL-запросах к PostgreSQL при разработке на Delphi, включая использование параметризованных запросов и других подходов.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.