Какой формат подстановочных знаков для функции поиска TEdit в FireDA C Delphi - PullRequest
0 голосов
/ 06 мая 2020

Это мой код для поиска данных с использованием компонента TEdit, который запускает TFDQuery с параметром:

qryItems.ParamByName('searches').AsString := Format('%%%s%%',[edtSearch.Text]);

Если я удалю подстановочные знаки (Формат ('%%% s %%')), он работает. Подстановочные знаки помогут мне отфильтровать запрос.

Мне нравится код, он чистый, простой и понятный. Но я все еще не уверен, что это правильно - он ничего не возвращает!

Мой вопрос: работает ли приведенный выше код для фильтрации запросов из события TEdit.OnChangeTracking? В противном случае, как это правильно сделать?

ОБНОВЛЕНИЕ 1: Вот код из редактора TFDQuery:

SELECT category.name AS category, item.name, item.description
FROM item
JOIN category ON item.category_id = category.list_id
WHERE item.description LIKE :searches
ORDER BY item.sellable
LIMIT 100

Теперь я пытаюсь получить доступ к нему из этого кода во время выполнения, но он не работает:

qryItems.ParamByName('searches').AsString := Format('%%%s%%',[edtSearch.Text]);

Я думаю, что виноват этот формат кода ('%%% s %%', [edtSearch.Text]), я не понимаю.

1 Ответ

1 голос
/ 06 мая 2020

Короткий ответ заключается в том, что вы хотите получить назначение параметров, подобное этому:

  FDQuery1.Params[0].AsString := '%a%';
  FDQuery1.Open();

при условии, что значение, которое вы хотите сопоставить в своем выражении LIKE, - это просто буква a. Или, если вы хотите использовать Format, вы можете сделать что-то вроде этого:

  FDQuery1.Params[0].AsString := Format('%%%s%%', [edFilter.Text]);

Причина появления трех знаков ha sh в строке заключается в том, что первый собственный «ускользает» от второй в выражении, вычисляемом форматом, а третий, непосредственно перед 's' объединяется с ним, чтобы действовать как заполнитель для строки, поскольку Format создает ее результат.

Однако, учитывая, что вы не полностью знаком с работой с наборами данных и фильтрацией, я думаю, что вы делаете это излишне сложным для себя по крайней мере в двух отношениях:

  • FMX + LiveBindings не полностью свободен от ошибок и имеет некоторые причуды, которые могут хорошо встаньте у вас на пути.

  • Синтаксис для использования оператора LIKE, в котором используются символы ha sh (#), противоречит использованию знаков ha sh для разрешения параметров в функции Format. Это, в частности, может сбивать с толку чрезвычайно , особенно когда вы пытаетесь получить синтаксически правильное выражение LIKE, будь то для включения в Sql ваш запрос или в «локальный фильтр», т. Е. тот, который использует свойства Filter + Filtered FDQuery.

Итак, я собираюсь сделать предложение, которое, возможно, изначально может быть нежелательным, а именно провести ваше исследование таких вещей, как фильтрация в приложении VCL , как показано ниже. Настройка займет всего несколько минут, но, вероятно, сэкономит вам время и нервную систему, по сравнению с попытками сделать это правильно в приложении FMX + LiveBinding, которое находится в стадии разработки. Вот как это сделать:

  1. Создайте новое приложение VCL и добавьте в него эти компоненты.
    FDConnection1: TFDConnection;
    FDGUIxWaitCursor1: TFDGUIxWaitCursor;
    FDQuery1: TFDQuery;
    DBGrid1: TDBGrid;
    DBNavigator1: TDBNavigator;
    DataSource1: TDataSource;
    edFilter: TEdit;
    btnLocalFilter: TButton;
    btnSqlFilter: TButton;

Добавьте приведенный ниже код в файл формы.

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

case FilterMode of

и исследуйте поведение приложения, изменяя содержимое элемента управления edFilter и нажимая две кнопки, как только вы адаптировали код к имеющимся у вас данным. Моя использует таблицу авторов, я не могу вспомнить, откуда я ее взял, но, возможно, она была из образца базы данных Pubs для Sql -Server.

Приложение показывает - я уверен, что вы собранные - что вы можете фильтровать данные, отображаемые вашим приложением, либо на стороне сервера, изменив Sql, используемое для получения данных, либо на стороне клиента, используя свойство Filter FDQuery. Чтобы вы могли легко увидеть, что происходит, Sql для фильтрации на стороне сервера создается путем объединения содержимого edFilter.Text с остальной частью Sql, но в реальной жизни вы не должны никогда делает это из-за уязвимости Sql Injection .

Код

type
  TFilterMode = (fmLocal, fmSql);

type
  TForm1 = class(TForm)
  [...]
  public
    { Public declarations }
    FilterMode : TFilterMode;
  end;
[...]
const
      sOrderBy = ' order by lastname, forename';
      sSql = 'select * from authors';
      sFilteredSql = sSql + ' where lastname like  :lastname%';
      sLocalFilter = 'lastname like ''%%s%%''';

procedure TForm1.OpenFDQuery;
var
  S : String;
begin
  if FDQuery1.Active then FDQuery1.Close;
  FDQuery1.Params.Clear;
  FDQuery1.Filter := '';
  FDQuery1.Filtered := True;
  case FilterMode of
    fmSql : begin
      FDQuery1.Sql.Text := '';
      //  WARNING - don't do this for real - risk of Sql Injection exploit
      //  use a parameterised query instead - see http://docwiki.embarcadero.com/RADStudio/Rio/en/Using_Parameters_in_Queries
      S := 'select * from authors where lastname like ''%' + edFilter.Text + '%''';
      FDQuery1.Sql.Text := S;
    end;
    fmLocal : begin
      FDQuery1.Sql.Text := sSql + sOrderBy;
      S := 'lastname like ''%' + edFilter.Text + '%''';
      FDQuery1.Filter := S;
      FDQuery1.Filtered := True;
    end;
  end;

  FDQuery1.Open;
end;

procedure TForm1.ApplySqlFilter;
begin
  FilterMode := fmLocal;
  OpenFDQuery;
end;

procedure TForm1.ApplyLocalFilter;
begin
  FilterMode := fmLocal;
  OpenFDQuery;
end;

procedure TForm1.btnLocalFilterClick(Sender: TObject);
begin
  ApplyLocalFilter;
end;

procedure TForm1.btnSqlFilterClick(Sender: TObject);
begin
  ApplySqlFilter;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  edFilter.Text := 'a';
end;
...