Редактирование данных при помощи визуальных компонентов

Редактирование данных при помощи визуальных компонентов

Если вы уже запустили пример, представленный выше, и попробовали исправить хотя бы одну запись в таблице, то наверняка получили сообщение, что сделать это невозможно. Причины этого сообщения очевидны, поскольку компонент IBDataSetl имеет только свойство SelectSQL. Это свойство содержит запрос на выборку записей, его выполнение позволяет получить список тех записей из таблицы EMPLOYEE с сервера, которые удовлетворяют условию в WHERE.

А для того чтобы, к примеру, исправить какую-либо запись, необходимо выполнить команду UPDATE. В общем случае выполнение этой команды может вообще не зависеть от нашего запроса в SelectSQL.

Но поскольку TIBDataSet был спроектирован в первую очередь для того, чтобы использоваться совместно со стандартными визуальными компонентами, то он предоставляет нам средства для автоматического выполнения тех модифицирующих запросов, которые необходимы для изменения данных, полученных при помощи SelectSQL. Чтобы окончательно не запутаться, давайте подробнее рассмотрим этот вопрос.

Итак, мы открыли запрос в SelectSQL. Как видно из рисунка, первая полученная запись содержит имя сотрудника Robert. Предположим, мы хотим исправить это имя на John.

В момент изменения произойдет следующее: в локальном буфере IBDataSetl у текущей записи значение поля FIRST_NAME будет изменено с Robert на John. В базе данных данное изменение пока никак не отражается. Чтобы произвести фактическое изменение данных на сервере, необходимо выполнить соответствующий запрос с UPDATE. Этот запрос необходимо заранее указать у компонента IBDataSetl в свойстве ModifySQL:

UPDATE EMPLOYEE

SET

EMP_NO = :EMP_NO,

FIRST_NAME = :FIRST_NAME,

LAST_NAME = :LAST_NAME,

PHONE_EXT = :PHONE_EXT,

HIRE_DATE = :HIRE_DATE,

DEPT__NO = :DEPT_NO,

JOB_CODE = :JOB_CODE,

JOB_GRADE = :JOB_GRADE,

JOB_COUNTRY = :JOB_COUNTRY,

SALARY = :SALARY WHERE

EMP_NO = :OLD_EMP_NO

Как видно из примера, вместо реальных значений в этом запросе указаны параметры, названия которых совпадают с названием реальных полей. Таким образом, когда пользователь изменит значения полей конкретной записи, ю jtBDataSetl сам задаст значения всех параметров, взяв их из соответствующих |полей. В частности, значение параметра :FIRST_NAME будет равно John. Запрос шз ModifySQL выполнится, и только после этого изменения, сделанные пользователем, окажутся в базе данных.

Аналогичная последовательность действий связана с запросами в свойствах HnsertSQL и DeleteSQL - они выполняются при вставке новой записи и удалении записи пользователем.

Обратите внимание на префикс OLD_ в названии параметра :OLD_EMP_NO. Данный префикс означает, что IBDataSet должен подставить в параметр значение поля до изменения пользователем.

Итак, если мы сформируем все модифицирующие запросы, то наш IBDataSet позволит пользователям редактировать данные, т. е. мы фактически получим запрос, который разработчики на Delphi/C-H-Buildei обычно называют "живым"(live query).

Существует еще одна важная особенность при создании "живых" запросов После выполнения любого модифицирующего действия IBDataSet 1 выполнит запрос, указанный в свойстве RefreshSQL. Этот запрос должен возвращать только одну запись - текущую и нужен для обновления значений полей текущей записи после сделанных исправлений.

SELECT

EMP_NO,

FIRST_NAME,

LAST_NAME,

PHONE_EXT,

HIRE_DATE,

DEPTMTO,

JOB_CODE,

JOB_GRADE,

JOB_COUNTRY,

SALARY,

FULL_NAME

FROM EMPLOYEE

WHERE

EMP_NO = :EMP_NO

Смысл данного запроса становится очевидным, если допустить существование в базе данных триггеров для таблицы EMPLOYEE, которые модифицируют значения полей. Поскольку изменения происходят в самой базе данных сразу после вставки или после изменения записей, то без повторного перечитывания записи (т. е. без Select только что вставленной или измененной записи), мы не узнаем о тех изменениях, которые были сделаны в триггерах. Можно, конечно, вообще переоткрыть весь запрос, заданный в SelectSQL.

Именно такой механизм и реализуется в BDE, когда мы вынуждены целиком переоткрывать все запросы. В IBX без этого легко можно обойтись, используя RefieshSQL, значительно сэкономив при этом сетевой трафик и снизив нагрузку на сервер, поскольку получение всего лишь одной измененной записи гораздо более эффективно, чем переоткрытие запроса целиком.

IBX предоставляет нам возможность быстро сгенерировать необходимые модифицирующие запросы при помощи редактора IBDataSet (рис 2.9.)

Выбрав из списка Table Name нашу таблицу и нажав кнопку Get Table Fields мы сформируем списки Key Fields и Update Fields. В списке Key Fields нужно выделить те поля, которые будут формировать условие WHERE в наших запросах. Очевидно, что это должны быть поля, которые определяют первичный ключ у таблицы. Если такой ключ существует для выбранной таблицы, то вы можете просто нажать на кнопку Select Primary Keys, чтобы автоматически выделить нужные поля.

Рис 2.9. Генератор модифицирующих запросов

В списке Update Fields необходимо выделить те поля, которые потом пользователь сможет редактировать. На рисунке видно, что поле FULL_NAME не включено в список, поскольку это CALCULATED-поле и его значение нельзя менять

К сожалению, надо самому точно знать, какие поля необходимо исключать из модифицирующих запросов поскольку компоненты не дадут ни одной подсказки. Даже при подготовке данного раздела пришлось потратив впустую некоторое время, чтобы понять, почему IBDataSetl никак не "хотел" становиться модифицируемым. Только выяснив, что поле FULL_NAME является вычислимым, стало понятно, почему возникает ошибка IBDataSetl пытался выполнить команду Prepare для каждого из запросов и сервер каждый раз сообщал, что не может изменить read-only-поле! Хочется отметить, что этой проблемы нет в генераторе запросов, реализованном в FIBPlus.

Остается нажать кнопку Generate SQL, чтобы получить все запросы flnsertSQL, ModifySQL, DeleteSQL и RefreshSQL.