Распечатать страницу

Фиксация и отмена изменений в Visual FoxPro

« Назад

Функция

TABLEUPDATE([nRows [, lForce]] [, nWorkArea | cTableAlias] [, cErrorArray])

фиксирует изменения, выполненные в буферизованной записи, таблице, курсоре или курсоре-адаптере, открытом в текущей или заданной рабочей области.

Функция возвращает .T. при успешной фиксации изменений или .F. – в противном случае.

Замечание. VFP по умолчанию устанавливает оптимистическую буферизацию записи для курсоров, ассоциированных с объектом CursorAdapter.

Параметры:

nRows – определяет вариант фиксации изменений в таблице или курсоре. Значения, принимаемые nRows, описаны в табл. 15.13.

Таблица 15.13

Значения параметра nRows

nRows

Описание

0

Фиксирует изменения, выполненные в текущей записи курсора (по умолчанию).
VFP при работе с объектом CursorAdapter выполняет соответствующую команду, хранимую его свойством InsertCmd, UpdateCmd или DeleteCmd

1

Если установлена буферизация таблицы, то фиксирует все изменения, выполненные во всех записях таблицы или курсора.
Если установлена буферизации записи, то фиксирует изменения, выполненные в текущей записи курсора.
VFP при работе с объектом CursorAdapter передает соответствующую команду, хранимую его свойством InsertCmd, UpdateCmd или DeleteCmd, для каждой обновляемой записи

2

То же, что и nRows = 1, однако когда изменения не могут быть зафиксированы, сообщения об ошибке не генерируется и VFP продолжает обработку последующих записей таблицы или курсора.
Если задан параметр cErrorArray и изменения не могут быть зафиксированы, то создается массив cErrorArray

Для совместимости с предыдущими версиями VFP параметр nRows также принимает .F. и .T. соответственно вместо 0 и 1.

При задании 0 или 1 и возникновении ошибки таблица позиционируется на записи, в которой не могут быть выполнены изменения. Для определения причины ошибки можно употребить функцию AERROR( ).

При работе с объектом CursorAdapter и задании для nRows 1 или 2 все изменения в курсоре, осуществленные как события объекта CursorAdapter, должны быть зафиксированы, если только не произошла ошибка при выполнении событий BeforeInsert, AfterInsert, BeforeDelete, AfterDelete, BeforeUpdate или AfterUpdate.

VFP передает значение nRows событию BeforeCursorUpdate объекта CursorAdapter.

lForce – задает, будет ли VFP перезаписывать изменения, выполненные в буфере записи, таблицы или курсора другим сетевым пользователем. Принимает следующие значения:

F. – фиксирует изменения в таблице или курсоре начиная с его первой и завершая последней записью. Если встречается запись, модифицированная другим сетевым пользователем, то VFP генерирует ошибку, которую можно обработать ON ERROR-процедурой. Причем последняя может содержать TABLEUPDATE( ) с lForce = .T. Как альтернатива, если выполняется транзакция, ON ERROR-процедура может содержать команду ROLLBACK, для возврата таблицы или курсора в прежнее состояние;

T. – перезаписывает изменения в таблице или курсоре, выполненные другим пользователем.

Параметр lForce должен быть задан, если имеется параметр nWorkArea | cTableAlias.

cErrorArray – имя массива, создаваемого, когда nRows = 2 и изменения не могут быть зафиксированы. Массив содержит номера записей, в которых не смогли быть зафиксированы изменения. Если параметр задается, то должны также присутствовать параметры lForce и nWorkArea | cTableAlias.

Если произошла ошибка, отличная от ошибки фиксации изменений, то массив будет содержать один элемент, равный –1. Характер ошибки можно пределить, применив функцию AERROR( ).

Если существует объект CursorAdapter, то VFP передает cErrorArray событию AfterCursorUpdate этого объекта.

Функция TABLEUPDATE( ) фиксирует изменения в таблице или курсоре, лишь когда его свойство Buffering отлично от 1, то есть когда имеется буферизация записи или таблицы. Если буферизация отключена и выполнена функция TABLEUPDATE( ), то VFP сгенерирует ошибку. Управление буферизацией осуществляет функция CURSORSETPROP( ).

При обновлении нескольких записей TABLEUPDATE( ) перемещает таблицу на последнюю обновленную запись.

Замечание. Вызов TABLEUPDATE( ) для локальной таблицы или вида, не имеющего первичных полей (см. свойство KeyFieldList), генерирует для поиска обновляемой записи длинную опцию WHERE. По умолчанию в опции WHERE может быть до 40 полей. Если возникает ошибка SQL: Statement too long (Ошибка 1812), то следует либо использовать первичное поле, либо увеличить допустимую сложность опции WHERE, употребив SYS(3055). В качестве второго параметра функции следует взять величину, использующую 8 * FCOUNT( ):

Sys(3055, Max(320, Min(2040, 8 * Fcount( ))))

При употреблении объекта CursorAdapter выполняются следующие действия:

TABLEUPDATE( ) оперирует только курсором, ассоциированным с объектом CursorAdapter;

TABLEUPDATE( ) выполняет команды в соответствии с типом источника данных и командами, хранимыми свойствами InsertCmd, UpdateCmd и DeleteCmd;

TABLEUPDATE( ) передает значение GETFLDSTATE(1) для каждой изменяемой записи следующим событиям объекта CursorAdapter: BeforeInsert, BeforeDelete, BeforeUpdate.

С текущей записи объекта CursorAdapter можно переместиться в обработчиках следующих его событий: BeforeInsert, AfterInsert, BeforeDelete, AfterDelete, BeforeUpdate и AfterUpdate.

Пример. Выполняются изменения в буферизованной таблице.

close databases

&&

&& Создаем свободную таблицу Employee

create table d:\Employee (LastName C(20))

&&

&& При использовании буферизации
&& SET MULTILOCKS нужно установить в ON

set multilocks on

&&

&& Активизируем буферизацию таблицы

CursorSetProp('Buffering', 5, 'Employee')

&& Добавляем в таблицу запись

insert into Employee (LastName) values ('Сема')

&&

&& Фиксируем изменения

TableUpdate(1)

&& Просмотр результата

browse last

&&

&& Меняем значение поля LastName

replace LastName with 'Женя'

&&

&& Фиксируем изменения

TableUpdate(1)

browse last

&&

&& Закрываем и удаляем таблицу Employee

use

delete file d:\Employee.dbf

Функция

TABLEREVERT([lAllRows [, nWorkArea | cTableAlias]])

отменяет изменения, выполненные в буферизованной записи, таблице, курсоре или курсоре-адаптере, открытом в текущей или заданной рабочей области, и восстанавливает oldval-значения для удаленных таблиц и текущие, хранимые на диске значения для локальной таблицы или курсора.

Функция возвращает число записей, изменения в которых отменены.

Если TABLEREVERT( ) применяется с таблицей или курсором, используемым без буферизации, то VFP генерирует ошибку.

Отмена изменений осуществляется до их фиксации, например функцией TABLEUPDATE( ).

Фактически TABLEREVERT( ) восстанавливает содержимое буфера, которое пользователь может наблюдать, например, при выполнении BROWSE.

Функция TABLEREVERT( ) не меняет положения файлового указателя.

Параметр:

lAllRows – определяет, все ли изменения таблицы или курсора будут отменены. Параметр имеет действие при буферизации таблицы. Тогда, если lAllRows = .F., то отменяются изменения сделанные в текущей записи; если lAllRows = .T., то отменяются все изменения.

Если применяется буферизация записи, то параметр lAllRows игнорируется, все изменения текущей записи отменяются.

Пример:

close databases

create table d:\Employee (LastName C(20))

&& SET MULTILOCKS нужно установить в ON

set multilocks on

CursorSetProp('Buffering', 5, 'Employee')

insert into Employee (LastName) values ('Сема')

TableUpdate(1)

browse last && Покажет имя Сема

&&

&& Меняем значение поля LastName

replace LastName with 'Женя'

browse last && Покажет имя Женя

&&

&& Отменяем изменение записи

TableRevert(.T.)

browse last && Покажет имя Сема

use

delete file d:\Employee.dbf

Функция

CURVAL(cExpression [, nWorkArea | cTableAlias])

возвращает значение поля (выражения), хранимое на диске, для текущей или заданной таблицы или удаленного источника.

Тип возвращаемого значения определяется типом выражения, заданного cExpression.

Параметр:

cExpression – выражение, значение на диске которого возвращает CURVAL( ). Обычно cExpression – это имя поля или выражение, содержащее поля таблицы или удаленного источника данных.

Если сравнить значения, возвращаемые CURVAL( ) и OLDVAL( ), то можно определить, изменил ли значение поля (с момента начала редактирования) другой сетевой пользователь или нет.

Функции  CURVAL( ) и OLDVAL( ) могут возвращать различные значения, только при оптимистической буферизации записи или таблицы.

Замечание. При работе с видом в многопользовательском окружении значения, возвращаемые CURVAL( ), могут не отражать последние изменения, если прежде не использована функция REFRESH( ). Данные, возвращаемые видом, буферизуются и функция CURVAL( ) читает их из буфера. Для переноса в буфер изменений, произведенных другим пользователем, употребляется REFRESH( ).

Пример. Вызываются функции CURVAL( ) и OLDVAL( ).

close databases

create table d:\Employee (LastName C(20))

set multilocks on

CursorSetProp('Buffering', 5, 'Employee')

insert into Employee (LastName) values ('Сема')

? CurVal('LastName')   && Напечатает: .NULL.

? OldVal('LastName')   && Напечатает: .NULL.

TableUpdate(1)

? CurVal('LastName')   && Напечатает: "Сема"

? OldVal('LastName')   && Напечатает: "Сема"

&& Меняем значение поля LastName и выводим его оригинальное значение

replace LastName with 'Женя'

? CurVal('LastName')   && Напечатает: "Сема"

? OldVal('LastName')   && Напечатает: "Сема"

&& Фиксируем изменения

TableUpdate(1)

? CurVal('LastName')   && Напечатает: "Женя"

? OldVal('LastName')   && Напечатает: "Женя"

use

delete file d:\Employee.dbf

Функция

OLDVAL(cExpression [, nWorkArea | cTableAlias])

возвращает оригинальное значение поля (выражения) для текущей или указанной таблицы. То есть возвращается значение, которое поле имело до изменения, причем это изменение не было зафиксировано. Результат возвращается для текущей записи.

Тип возвращаемого значения определяется типом выражения, заданного cExpression.

Параметр:

cExpression – выражение, оригинальное значение которого возвращает OLDVAL( ). Обычно cExpression – это имя поля или выражение, содержащее поля таблицы или удаленного источника данных.

Если таблица базы данных или курсор имеет правило проверки или триггер, то OLDVAL( ) не требует, чтобы была установлена буферизация записи или таблицы. В противном случае при отсутствии буферизации генерируется ошибка.

Если установлена буферизация записи и файловый указатель смещен с изменой записи на другую или если выполнена функция TABLEUPDATE( ), или фиксация изменений вызвана другими действиями, например такими, как завершение транзакции, то поля будут обновлены и их оригинальные, существовавшие до обновления значения станут недоступны.

Пример см. в описании функции CURVAL( ).

Функция

GETFLDSTATE(cFieldName | nFieldNumber [, nWorkArea | cTableAlias])

возвращает число или .NULL., означающее статус изменения значения поля текущей записи или статус ее удаления. Результат возвращается для текущей или заданной параметром nWorkArea | cTableAlias таблицы.

Функция GETFLDSTATE( ) употребляется, когда активизирована буферизация записи или таблицы.

Смысл результатов функции описан в табл. 15.14.

Таблица 15.14

Результаты функции GETFLDSTATE( ) и параметр nFieldState функции SETFLDSTATE( )

Результат
или nFieldState

Статус изменения или удаления

1

Значение поля и статус удаления записи не изменены

2

Изменено значение поля или статус удаления записи

3

Значение поле и статус удаления добавленной записи не изменены

4

Изменено значение поля или статус удаления добавленной записи

.NULL.

Файловый указатель в конце файла

Параметры:

cFieldName | nFieldNumber – имя или номер поля, для которого возвращается результат. Номер поля можно определить, воспользовавшись командой DISPLAY STRUCTURE или функцией FIELD( ).

Если параметр nFieldNumber = –1, функция вернет строку, содержащую статусы изменения или удаления всех полей записи таблицы или курсора. Например, если таблица имеет 4 поля и изменено значение первого поля, то

? GetFLDState(–1)

напечатает

12111

Первая единица результата говорит о том, что статус удаления записи сохранен, последующие 4 символа строки характеризуют статусы изменения полей текущей записи таблицы.

Если nFieldNumber = 0, то функция вернет статус удаления текущей записи таблицы или курсора.

Замечание. Простановка и последующее снятие пометки удаления переведут запись в ее первоначальное состояние, однако GETFLDSTATE( ) вернет результат, означающий, что статус удаления записи изменен.

Статус изменения будет зафиксирован GETFLDSTATE( ) как при явном, так и неявном изменении значения поля. Явное изменение вызывается, например, командой REPLACE или INSERT INTO, неявное происходит в результате подстановки в добавленной записи значения по умолчанию (если таковое имеется).

Пример 1:

close databases

open database d:\HomeLibrary\HomeLibrary.dbc

use Authors

select Authors

set multilocks on

&&

&& Активизируем буферизацию таблицы

CursorSetProp('Buffering', 5, 'Authors')

&&

? GetFLDState("Author")      && Напечатает: 1

&&

&& Изменяем значения поля Author первой записи таблицы

replace Author with Proper(Author)

? GetFLDState("Author")      && Напечатает: 2

Пример 2. Функция GETFLDSTATE( ) вызывается после добавления записи для поля State, имеющего значение по умолчанию, и поля Cust_id, его не имеющего.

close databases

set multilocks on

create database d:\Example

create table Customer (Cust_id C(6), State C(2) default "FL")

&& Активизируем буферизацию таблицы

CursorSetProp('Buffering', 5, 'Customer')

append blank

? GetFLDState ("State")         && Напечатает: 4

? GetFLDState("Cust_id")     && Напечатает: 3

browse last

close databases

delete databases d:\Example

Функция

SETFLDSTATE(cFieldName | nFieldNumber, nFieldState
                  
[, nWorkArea | cTableAlias])

устанавливает для текущей или заданной таблицы статус изменения поля или статус удаления текущей записи. Статус удаления устанавливается, если nFieldNumber = 0.

Функция возвращает .T., если действие выполнено, или .F. – в противном случае.

Употребляется только для буферизованных таблиц.

Параметр:

nFieldState – число в диапазоне 1 – 4. Описание значений параметра см. в табл. 15.14.

Смысл остальных параметров см. в описании функции GETFLDSTATE( ).

Функция

GETNEXTMODIFIED(nRecordNumber [, nWorkArea | cTableAlias] [, lNoFire])

возвращает номер первой измененной записи, расположенной после записи nRecordNumber. Функция употребляется для буферизованной таблицы или курсора. Результат возвращается для текущей или заданной таблицы или курсора.

Функция вернет 0, если после записи nRecordNumber нет измененных записей.

Запись считается измененной, если выполнялось редактирование ее полей или проставлялась и/или снималась пометка удаления.

Параметры:

nRecordNumber – номер записи, после которой GETNEXTMODIFIED( ) ищет измененную запись. Если задать nRecordNumber = 0, то функция будет искать первую измененную запись таблицы или курсора.

lNoFire – игнорируются, если параметр равен .T., ошибки, обнаруживаемые заданными для полей и записи правилами, а также ошибка "Uniqueness of index <имя индекса> is violated". В противном случае при обнаружении ошибки функцией GETNEXTMODIFIED( ) генерируется соответствующее сообщение.

Пример 1. Выводятся номера всех модифицированных записей.

close databases

open database d:\HomeLibrary\HomeLibrary.dbc

use Authors

select Authors

set multilocks on

&&

&& Активизируем буферизацию таблицы

CursorSetProp('Buffering', 5, 'Authors')

&&

&& Изменяем значения поля Author в 3-х записях

for nRec = 3 to 9 step 3

         go nRec

         replace Author with Proper(Author)

next

nRec = 0

do while .T.

         nRec = GetNextModified(nRec)

         if nRec = 0 then

                   exit

         endif

         ?? nREc      && Напечатает: 3   6   9

enddo

&& Восстанавливаем представление данных в буфере

TableRevert(.T.)

Пример 2. Нарушается уникальность первичного индекса AuthorId таблицы Authors.

close databases

open database d:\HomeLibrary\HomeLibrary.dbc

use Authors

select Authors

set multilocks on

CursorSetProp('Buffering', 5, 'Authors')

AuthorIdForRecNumber1 = Authors.AuthorId

&& Перемещаемся на следующую запись

skip

&& При замене нарушается уникальность первичного индекса AuthorId

replace AuthorId with AuthorIdForRecNumber1

? GetNextModified(1, "Authors", .T.)       && Напечатает: 0

TableRevert(.T.)

При вызове GetNextModified(1) в примере 2 будет сгенерирована ошибка "Uniqueness of index AUTHORID is violated".