TUpdateSQL предназначен для модификации данных на сервере с помощью заранее подготовленных SQL-предложений. Он позволяет определить различные операторы SQL для удаления, вставки и модификации записи, в том числе отличные от простых операторов DELETE, INSERT, APPEND. Эти операторы SQL содержатся в свойствах DeleteSQL, InsertSQL, ModifySQL соответственно.
Имя компонента TUpdateSQL может быть значением свойства UpdateObject какого-либо компонента TDataSet (например, TTable или TQuery). Если в этом случае используется кэширование данных, то в процессе выполнения транзакции, инициированной применением метода ApplyUpdates компонента TDataSet при попытке вставки, удаления или изменения записи генерируется SQL-запрос, содержащийся в свойстве InsertSQL, DeleteSQL или ModifySQL соответственно. Эти свойства можно редактировать, выбрав пункт UpdateSQL editor из контекстного меню компонента TUpdateSQL. Если же кэширование не используется, соответствующие SQL-запросы генерируются при выполнении метода Post компонента TDataSet.
Отметим, что эти три свойства поддерживают специальное расширение SQL, обеспечивающее возможность использования в запросах значений полей, существовавших до начала выполнения транзакции, переносящей на сервер данные из кэша (обычно это требуется при создании предложения WHERE в SQL-запросах). Такие значения полей обозначаются следующим образом: префикс "OLD_" + <имя поля>.
На этапе выполнения в процессе сохранения какой-либо записи на сервере компонент TUpdateSQL выбирает один из трех описанных в его свойствах запросов в соответствии со значением свойства UpdateKind компонента TDataSet, пересылает параметры запроса на сервер и выполняет запрос с целью фиксации на сервере данного обновления.
Для управления каждым отдельным обновлением внутри транзакции, переносящей данные из кэша на сервер, можно использовать событие OnApplyUpdate соответствующего компонента TDataSet, а также параметры UpdateKind (тип обновления) и UpdateAction, которому должно быть присвоено значение uaApplied, если обновление было успешным. Если установить значение этого параметра равным uaSkip, данная запись в кэше будет проигнорирована и не перенесена на сервер.
Для изучения поведения TUpdateSQL внесем изменения в уже созданное приложение, заменив компонент Table1 на компонент TQuery и добавив на форму один компонент TUpdateSQL и компонент TCheckBox. Свойства этих компонентов изменим следующим образом (табл.2):
Таблица 2
Компонент | Свойство | Значение |
---|---|---|
Query1 | Active | true |
CachedUpdates | true | |
UpdateObject | UpdateSQL1 | |
SQL | Select * from clients | |
DataSource1 | DataSet | Query1 |
CheckBox1 | Caption | Использовать кэширование |
UpdateSQL1 | ModifySQL | update CLIENTS set LAST_NAME = :LAST_NAME, FIRST_NAME = :FIRST_NAME, ACCT_NBR = :ACCT_NBR where LAST_NAME = :OLD_LAST_NAME and FIRST_NAME = :OLD_FIRST_NAME and ACCT_NBR = :OLD_ACCT_NBR |
DeleteSQL | delete from CLIENTS where LAST_NAME = :OLD_LAST_NAME and FIRST_NAME = :OLD_FIRST_NAME and ACCT_NBR = :OLD_ACCT_NBR | |
InsertSQL | insert into CLIENTS (LAST_NAME, FIRST_NAME, ACCT_NBR) values (:LAST_NAME, :FIRST_NAME, :ACCT_NBR) |
Cтандартные SQL-запросы для добавления, удаления и изменения записи наиболее удобно создавать с помощью UpdateSQL editor, выбранного из контекстного меню компонента UpdateSQL1 (рис. 10)
Рис.10. UpdateSQL editor
Добавим в запрос вычисляемое поле STATUS для отображения состояния записи в кэше, уберем часть полей из списка отображаемых колонок DBGrid1, внесем изменения в существующие обработчики событий и добавим несколько новых (для события OnCalcField компонента Query1 и для события OnClick компонента CheckBox1):
//--------------------------------------------------------------------------- #include <vcl\vcl.h> #pragma hdrstop #include "appl1.h" //--------------------------------------------------------------------------- #pragma link "Grids" #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { Query1->ApplyUpdates(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button3Click(TObject *Sender) { Close(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { Query1->CancelUpdates(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Query1CalcFields(TDataSet *DataSet) { AnsiString UpdStr[] = {"Не изменялась", "Изменена", "Добавлена", "Удалена"}; if (Query1->CachedUpdates) Query1STATUS->Value=UpdStr[Query1->UpdateStatus()]; } //--------------------------------------------------------------------------- void __fastcall TForm1::CheckBox1Click(TObject *Sender) { Query1->CachedUpdates=CheckBox1->Checked; } //---------------------------------------------------------------------------
Если перед запуском приложения запустить утилиту SQL Monitor, то можно пронаблюдать, как генерируются запросы, содержащиеся в свойствах компонента UpdateSQL1, при использовании кэширования и без него, а также как отображается состояние конкретной записи при использовании кэширования (рис.11):
Рис.11. Приложение с использованием UpdateSQL
Отметим, что свойства DeleteSQL, InsertSQL, ModifySQL компонента TUpdateSQL могут содержать более сложные запросы, нежели сгенерированные автоматически в его редакторе свойств, в соответствии с логикой содержащего его приложения.