Формируемые запросы
Часто один компонент TQuery используют для выполнения различных отстоящих друг от друга во времени запросов. Такой подход уменьшает число используемых компонентов, но может привести к возрастанию программного кода.
Свойство SQL компонента TQuery имеет тип TStrings: property SQL: TStrings; и потому содержимое свойства SQL может формироваться программно методами Add (добавить элемент). Delete (удалить элемент), Clear (очистить список) и прочими.
Пример.
Пусть компонент RashodQuery используется для выполнения динамического запросаSELECT *
FROM RASHOD
WHERE POKUP = :POKUP
то есть запрос "выдать все записи из таблицы расхода товаров RASHOD, у которых имя покупателя POKUP совпадает со значением, указанным в параметре :POKUP". Пусть значение в параметр :POKUP берется из поля POKUP текущей на данный момент записи в таблице POKUPATELI (компонент PokupQuery):
WITH RashodQuery do begin Close;
ParamByName('POKUP').Value :=PokupQuery.FieldByName('POKUP').Value;
Open;
END;//with
Тогда и динамический оператор, и использование параметров можно заменить на следующий код:
WITH RashodQuery do begin
Close; SQL.Add ('SELECT *') ;
SQL.Add('FROM RASHOD')
SQL.Add('WHERE POKUP = ' + PokupQuery.FieldByName('POKUP').AsString) ;
Open;
END;//with
Заметим, что второй вариант лучше использовать в том случае, когда вид выполняемого запроса не повторяется во времени. В противном случае целесообразнее использовать динамический запрос.
Пример.
Пусть для оператора UPDATE, выполняющего корректировку записи в таблице RASHOD, значения полей DAT_RASH, KOLVO, TOVAR, POKUP могут вводиться компонентами TEdit с именами Dat_Rash_Edit, Kolvo_Edit, Tovar_Edit, Pokup_Edit. Требуется сформировать такой SQL-оператор, чтобы в нем указывались в качестве обновляемых только поля, для которых введено значение в соответствующих компонентах. Вид формы показан на рис. 9.8. Для формирования оператора UPDATE используется такой обработчик нажатия экранной кнопки "Изменить":procedure TForm!.UpdateButtonClick(Sender: TObject) ;
var TmpN_Rash : Integer;
Cnt : Integer; //счетчик непустых TEdit
Separator : String[1]; //запятая или пустая строка
begin
{ проверку правильности соответствия значения в Dat Rash Edit.Text формату даты и значения в Koivo_Edit.Text формату целого числа для простоты не производим }
Cnt := 0;
IF Dat_Rash_Edit.Text 0 " THEN INC(Cnt);
IF Kolvo_Edit.Text 0 " THEN INC(Cnt);
IF Tovar_Edit.Text 0 " THEN INC(Cnt);
IF Pokup_Edit.Text 0 " THEN INC(Cnt);
IF Cnt = 0 THEN begin
ShowMessage('He введено ни одно новое значение');
Dat_Rash_Edit.SetFocus;
Exit;
END;//if
//формирование текста оператора UPDATE
WITH ListBoxl.Items do begin
Clear;
Add ('UPDATE RASHOD') ;
Add('SET') ;
IF Dat_Rash_Edit.Text <> " THEN begin
DEC(Cnt) ;
IF Cnt > 0 THEN
Separator := ','
ELSE Separator := " ;
Add(' DAT_RASH = \" + Dat_Rash_Edit.Text + '"' -Separator);
END;//if
IF Kolvo_Edit.Text 0 "THEN begin
DEC(Cnt) ;
IF Cnt > 0 THEN
Separator := ','
ELSE
Separator := " ;
Add(' KOLVO = ' + Kolvo_Edit.Text + Separator);
END;//if
IF Tovar_Edit.Text <> " THEN begin
DEC(Cnt);
IF Cnt > 0 THEN Separator := ','
ELSE Separator := " ;
Add(' TOVAR = "' + Tovar_Edit.Text + '"' + Separator);
END;//if
IF Pokup_Edit.Text <> " THEN
Add(' POKUP = "' + Pokup_Edit.Text + '"');
TmpN_Rash := RashodQuery.FieldByName('N_RASH').As Integer;
Add('WHERE N_RASH = ' + IntToSTr(TmpN_Rash)) ;
END;//with
//выполнение сформированного SQL-оператора
WITH UpdateQuery do begin
SQL.Clear;
SQL := ListBoxl.Items;
TRY
ExecSQL;
EXCEPT
on EDBEngineError do begin
ShowMessage('Ошибка БД. Проверьте уникальность номера ' + 'расхода!');
Exit;
end;//do
ELSE
SHowMessage('Неклассифицированная ошибка при ExecSQL') ;
END;//try
RashodQuery.Close;
RashodQuery.Open;
END;//with