powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Как проверить были изменения внесены или нет?
23 сообщений из 23, страница 1 из 1
Как проверить были изменения внесены или нет?
    #34039304
Surgeon2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вообщем вопрос такой,в универе задание дали=)
Есть база на SQL,к которой подключаются по фоксу и работают с помощью представлений (View).В этой базе хранится куча инфы,и когда проиходят изменения: добавление,удаление,изменение записи,то все это дело региструется в другой таблице(назовем её журнал изменений).Теперь если я не сделал никаких изменений и нажал кнопку запомнить,то журнале изменений, в которой регестрируются все действия, все равно это зафиксируется,хотя по сути я ничего не сделал.
Мне надо найти функцию в фоксе,она по идеи должна быть,которая бы мне вернула ложь или истинну - были изменения или нет,чтобы используя её я вносил данные в журнал изменений или не вносил.
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34039409
Burn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GETFLDSTATE()
CURVAL()
OLDVAL()
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34040097
Surgeon2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если можете немного поясните,что делать будет каждая функция?
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34040161
Burn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Если можете немного поясните,что делать будет каждая функция?
А Хелп почитать не судьба?

Хотя с CURVAL(), OLDVAL() я поторопился - они возвращают сотвествено текущее значение в буферизированой таблице Фокса и старое значение буфера, соотвествено, и для вьюхи или курсорадаптера с SQL-сервера не работают.

А вот GETFLDSTATE() возвращает признак модифицировалось ли каке либо поле таблицы или курсора:


Returns a numeric value indicating if a field in a table or cursor has been modified or had a record appended, or if the deleted status of the current record has been changed.


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



Parameters
cFieldName| nFieldNumber


Specifies the name of the field or the number of the field for which the modification status is returned. The field number nFieldNumber corresponds to the position of the field in the table or cursor structure. DISPLAY STRUCTURE or FIELD( ) can be used to determine a field's number. You can specify –1 for nFieldNumber to return a character string consisting of deletion and modification status values for all fields in the table or cursor. For example, if a table has five fields and only the first field has been changed, GETFLDSTATE( ) returns 121111. The 1 in the first position indicates the deletion status has not been changed. You can also include 0 for nFieldNumber to determine if the deletion status of the current record has changed since the table or cursor was opened.
Note:
Using GETFLDSTATE() only determines if the deletion status of the current record has changed. For example, if you mark a record for deletion and then recall it, GETFLDSTATE() indicates the deletion status has changed even though the record's deletion status has returned to its original state. Use DELETED() to determine the current deletion status of a record.



cTableAlias


Specifies the alias of the table or cursor for which the field modification or record deletion status is returned.
nWorkArea


Specifies the work area of the table or cursor for which the field modification or record deletion status is returned. If you do not specify an alias or work area, GETFLDSTATE( ) returns a value for a field in the currently selected table or cursor.
Return Value
Numeric, Character, or .NULL.

Remarks
The following table lists the character return values and the corresponding modification or deletion status.

Return value Modification or deletion status
1
Field has not been modified or deletion status has not changed.

2
Field has been modified or deletion status has changed.

3
Field in an appended record has not been modified or deletion status has not changed for the appended record.

4
Field in an appended record has been modified or deletion status has changed for the appended record.

.NULL.
At EOF( )


Row or table buffering must first be enabled with CURSORSETPROP( ) for GETFLDSTATE( ) to operate on local tables.

The modification or deletion status is returned for the table or cursor open in the currently selected work area if GETFLDSTATE( ) is issued without the optional cTableAlias or nWorkArea arguments.

Any change in a field will cause GETFLDSTATE() to return a value showing that the field has been modified, whether the change is explicit or implicit. An example of an explicit modification would be including the field in a REPLACE or INSERT INTO command. An implicit modification occurs in a field that has a default value when any command is issued that adds a new record.

Example 1
The following example demonstrates how you can use GETFLDSTATE( ) to determine if the contents of a field have changed. MULTILOCKS is set to ON, a requirement for table buffering. The customer table in the testdata database is opened, and CURSORSETPROP( ) is then used to set the buffering mode to optimistic table buffering (5).

GETFLDSTATE( ) is issued to display a value (1) corresponding to the unmodified state of the cust_id field before it is modified. The cust_id field is modified with REPLACE, and GETFLDSTATE( ) is issued again to display a value (2) corresponding to the modified state of the cust_id field. TABLEREVERT( ) is used to return the table to its original state, and GETFLDSTATE( ) is issued again to display a value (1) corresponding to the original state of the cust_id field.

Copy Code
CLOSE DATABASES
CLEAR

SET MULTILOCKS ON && Allow table buffering
OPEN DATABASE (HOME(2) + 'data\testdata')
USE Customer && Open customer table
=CURSORSETPROP("Buffering",5,"customer") && Enable table buffering

* Get field state on original cust_id field and display state
nState=GETFLDSTATE("cust_id")
DO DisplayState WITH nState("Original")

* Change field contents and display state
REPLACE cust_id WITH "***"
nState=GETFLDSTATE("cust_id")
DO DisplayState WITH nState("After Replace")

* Discard table changes and display state
= TABLEREVERT(.T.) && Discard all table changes
nState=GETFLDSTATE("cust_id")
DO DisplayState WITH nState("After Revert")

PROCEDURE DisplayState
PARAMETER nState,cOperation
DO CASE
CASE nState=1
=MESSAGEBOX("Field has not been modified",0,cOperation)
OTHERWISE
=MESSAGEBOX("Field has been modified",0,cOperation)
ENDCASE



Example 2
The following example shows the difference in behavior between fields with and without default values.

Copy Code
SET MULTILOCKS ON
CREATE DATABASE example
CREATE TABLE customer (cust_id C(6),state C(2) DEFAULT "FL")
CLOSE TABLES
USE customer
=CURSORSETPROP("Buffering",5,"customer")

APPEND BLANK
?GETFLDSTATE("cust_id") && Returns 3, field in an appended record has
&& not been modified.

?GETFLDSTATE("state") && Returns 4, field in an appended record has
&& been modified.
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34040216
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Surgeon2000Если можете немного поясните,что делать будет каждая функция?
А Вы не могли бы пояснить Вашу логику работы?

Итак, есть таблица на MS SQL сервере. Есть таблица-лог, в которой храняться все изменения сделанные в этой таблице.

ГДЕ хранится эта таблица-лог? Там же на MS SQL или у клиента в файлах DBF?

Если таблица-лог хранится на MS SQL, то совершенно не важно чем именно (каким способом) происходит модификация таблицы-источника. Это все решается через триггеры типа Update "навешанные" таблицу-источник.

При любой модификации таблицы-источника сработает триггер Update. Далее уже в этом триггере делаешь анализ: а изменилось ли в действительности контролируемые значения или нет.

Это решается через служебную таблицу inserted. Эта таблица существует только внутри тела триггеров. Ее структура совпадает со структурой таблицы на которую и наложен триггер. Содержимое - это только измененные (добавленные) записи.

Есть еще служебная таблица deleted, которая содержит удаленные записи.

Т.е. FoxPro тут вообще не при чем. Никаким боком. Не его это задача.
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34040429
Surgeon2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да вся база и все таблицы на SQL. Там и сейчас работают тригеры,они то как раз и добавляют в таблицу логов то что были изменения,так они же SQL-ные триггеры срабатывают даже когда ничего по сути не было изменено.Я так понимаю это происходит т.к. фоксу когда говорят запомнить(такая кнопочка есть в моем меню когда работаешь с таблицей ),то они берет это Remote View,т.е. то что в буфере,записывает в таблицу,хотя по сути данные те же и остались.К примеру я поковыряю таблицу,ну пусть я нажму кнопку редактировать и веду значение 5 вместо 10,потом передумаю и опять веду 10,а потом нажму запомнить.Данные не изменились, но фокс подумает что я поменял их и запишет,а так как он их запишет то и тригер сработает.Получается в таблицу логов записало что такой-то пользователь сделал в такое-то время изменения с записью номер такая-то.А на самом деле,данные остались теже!Вот и надо решить такую проблему,что данные если не меняются то и записывать не к чему...
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34040439
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так я же и объясняю. Анализируй результат в триггере MS SQL. Т.е. сравнивай содержимое исходной таблицы и содержимое служебной таблицы inserted. Если для одной и той же записи (одного значения ключевого поля) нет изменений в остальных полях, то и нечего записывать эту запись в лог.

С точки зрения FoxPro эту проблему тоже можно решить, но, по сути, тем же самым способом. Т.е. "в тупую" перебирая поля таблицы и сравнивая с их исходным значением (исходное значение берешь по OldVal()). Если все совпало, то делается откат буфера по TableRevert() для данной записи.

Но на стороне FoxPro - это совершенно бессмысленное занятие. Более того, это занятие бессмысленно с любой точки зрения. Прикинь, какова вероятность такого события? Ну будет у тебя немного мусора. Ну и что? Стоит ли чистка незначительного количества записей таких героических усилий?

Впрочем, в качестве учебного задания такое еще сойдет. Как решить, направление тебе указали.
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34042415
Surgeon2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Не... тут ты не совсем прав!Смысл определеный есть,это не учебная база,а реальное приложение,пусть не великое,но оно на приличной фирме работает.И дали потому как мусор появлеятся,это не единичный случай.
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34042421
Surgeon2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А сделать на уровне SQL я подумаю
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34048769
Surgeon2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я подумываю насчет использования функции
GETNEXTMODIFIED
что вы думаете?
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34051730
гость_я
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
GetNextModified() не решит твоей проблемы. Она просто укажет тебе, что в буфере есть изменения этой записи. А вот изменились ли действительно значения полей либо в них повторно записали те же значения на этот вопрос можно получить ответ только сравнивая измененные поля через CURVAL() и OLDVAL() как указывал ВладимирМ
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34051805
alex11100
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
GETFLDSTATE(-1)
первая цифра в строке - что делали с записью

последующие - если там '2' значит соответствующее поле трогали,
если '1', то не трогали

111112111111 - запись существовала и потрогали 6 поле
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34071578
Surgeon2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
КОгда я получу такой результат 111112111111
мне с считывать цифру для каждого поля при помощи функций деления нацело и взятия остатка?
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34072022
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Surgeon2000КОгда я получу такой результат 111112111111
мне с считывать цифру для каждого поля при помощи функций деления нацело и взятия остатка?
Я понимаю, что читать HELP для "настоящих программистов" - глубоко противно. Но хоть эксперимент провести самостоятельно можно? Посмотреть какого типа получится результат и что означают все эти циферки. Кстати, они меняются в диапазоне от 1 до 4

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
CREATE CURSOR test (f1 C( 10 ), f2 N( 10 ))
SET MULTILOCK ON
=CursorSetProp("buffering", 5 )
?"Нет записей",GetFldState(- 1 )

INSERT INTO test (f1) VALUES ("Пример")
?"Добавили новую запись и изменили поле 1",GetFldState(- 1 )

=TableUpdate(.T.,.T.)
?"Сбросили буфер",GetFldState(- 1 )

REPLACE f2 WITH f2
?"Заменили содержимое поля 2 на то же самое значение",GetFldState(- 1 )

=TableRevert(.T.)
?"Откатили буфер",GetFldState(- 1 )

DELETE
?"Удалили запись",GetFldState(- 1 )

=TableRevert(.T.)
?"Откатили буфер",GetFldState(- 1 )

?"Тип значения, возвращаемого по GetFldState(-1)=", TYPE("GetFldState(-1)")

Физический порядок следования полей можно получить через функцию AFIELDS(). Номер строки полученного массива - это и есть порядковый номер поля.

Также можно использовать функции FIELD() для получения имени поля по его порядковому номеру.
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34072153
Surgeon2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да хелп не самое приятное занятие читать,но я его почитал.На англицком.Из того че понял то понял...
Теперь буду знать что массив.
А вообще спасибо большое за помощь!
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34072357
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"массив" относился к функции AFILEDS(), а то, что возвращает GetFldState(-1) - это символьная строка.

Однако можно использовать и прямое обращение

?GetFldState("MyField","MyTable")

В этом случае будет возвращено число, определяющее статус изменений для данного поля.

Русский HELP по VFP3 есть в сети. Можно скачать, например, отсюда

http://vfp.narod.ru/Briefcase/Briefcase.htm

Там есть про GetFldState()

Кроме того, уже близок к завершению проект перевода на русский язык HELP по VFP9. Скорее всего, его закончат где-то к новому году.
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34072516
Surgeon2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А вот русский хелп по 9-му меня спасет!
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34072528
Surgeon2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я все-такие одно не понял.
Я беру сначала функцию GETNEXTMODIFIED(0,имя таблицы)
так я проверяю были ли вообще изменения.Если были,то GETNEXTMODIFIED
вернет номер первой измененной записи в таблице.

Затем я в строковую переменную считываю значения,функцией
GETFLDSTATE("имя таблицы",номер записи полученный от GETNEXTMODIFIED)
А если у меня изменено несколько записей то так мне функция выдаст состояние строки номер которой я задал или всех последующих строк которые идут начиная с этой?Это все-таки char массив будет или что?
Если можно привидите пример работы с результатом,например вернуло мне
111112111111 как я с цифирками обращаться могу?<--Это для меня самое главное.

Просто моя идея такая,я беру при помощи GETNEXTMODIFIED номер каждой последующей измененной записи.Потом я расчитываю, что зная номер записи,
GETFLDSTATE мне вернет её состояние.Если там появляются кроме 1 например 2,то мне надо проверить были ли реальные изменения или нет.Я это делаю при помощи CURVAL OLDVAL.Если изменения были то все я это дело останавливаю и произвожу запись из вьшек в таблицы,иначе пока до конца не дойду.
Не хочется в тупую сравнивать штук 30 полей записи.А сравнить только те которые являются "подозрительными" на изменения.
Я уточню,там скорее всего в этом месте я работаю с одной записью в таблице.Т.е. изменения могут быть в 1 записи и проверить надо одну.
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34072569
Surgeon2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Напряг мозги и состряпал,тока не очень то и работает=)
Если пользователь зашел и поменял значение на одно потом руками опять назад,то не срабатывает.

SET MULTILOCKS ON
=CURSORSETPROP("Buffering", 5, "rv_uz")
IF (GETNEXTMODIFIED(0,"rv_uz") <> 0)

LOCAL i as Integer
LOCAL flag1 as Boolean
flag1 = 0

FOR i=1 TO 100

IF FIELD(i,"rv_uz")=''
EXIT
ENDIF

IF GetFldState(i,"rv_uz") <> 1

IF CURVAL(FIELD(i,"rv_uz"),"rv_uz") <> OLDVAL(FIELD(i,"rv_uz"),"rv_uz")
flag1 = 1
EXIT
ENDIF

ENDIF

ENDFOR

IF flag1 = 0

если я оставлю
SET MULTILOCKS ON
=CURSORSETPROP("Buffering", 5, "rv_uz")
IF (GETNEXTMODIFIED(0,"rv_uz") <> 0)

а за ним пойдет метод который сохраняет,то когда пользователь зашел в режим редактирования,но ничего не трогал,все срабатывает.
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34072636
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Странный Вы какой-то, Вам же предложили: скачайте русский HELP и наконец-то прочитайте как именно работают указанные функции. Там все по русски написано. Логика работы этих функций со времен VFP3 не изменилась. Могли добавиться новые параметры, но старая логика осталась неизменной.

То, что Вы написали - вообще бессмысленно.

При работе с курсором, полученным через SQLExec() или Remote View значения OldVal() и CurVal() всегда одинаковые

OldVal() - это то значение, которое было в записи непосредственно перед началом изменения буфера

CurVal() - это то значение, которое есть сейчас в dbf-таблице - источнике (но не в буфере!). Не на самом сервере, а в курсоре . Имеет смысл только для файл-сервера и прямой работы с DBF-таблицами. По сути, проверяет не изменилось ли значение другим пользователем, пока данный пользователь что-то там редактировал.

Общие ошибки:

1) Глобальные настройки надо делать в главной (стартовой) процедуре или при инициализации формы. Делать настройку режима буферизации в момент сохранения просто бессмысленно. Все и так уже сохранено.

2) GetNextModified() - не перемещает указатель записи. Это значит, что если Вы модифицируете несколько записей одновременно, а потом перешли на НЕ измененную запись, то, хотя GetNextModified() и вернет номер изменной записи, но физического перемещения на эту измененную запись не произойдет. Останетесь там, где были.

3) Если на текущей форме пользователь изменяет только одну (текущую) запись, то зачем Вы вообще использовали GetNextModified()?

Для одной (текущей) записи все гораздо проще

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
LOCAL llModified
llModified = .F.
DO CASE
CASE LEN(ChrTran(GetFldState(- 1 ),"1",""))= 0 
	* Данную запись вообще не меняли. Нет смысла в проверках

CASE LEFT(GetFldState(- 1 ), 1 )="4" AND Deleted() = .T.
	* Данная запись - это новая запись, которую тут же и удалили
	* Такие записи вообще не отправляются на сервер
	* Нет смысла в проверках

CASE LEFT(GetFldState(- 1 ), 1 )="3"
	* Данная запись - это новая запись 
	* это модификация, которую надо сохранить
	llModified = .T.

CASE Deleted() = .T.
	* Данная запись - это запись, которая была удалена
	* это модификация, которую надо сохранить
	llModified = .T.

OTHERWISE
	* Было изменение в каком-то поле или нескольких полях. 
	* Проверяем, это реальное изменение или же вошли, поигрались и 
	* вышли, заменив значение на то же самое
	LOCAL lnI, lcFieldName
	FOR lnI =  2  TO LEN(GetFldState(- 1 ))
		IF SubStr(GetFldState(- 1 ),m.lnI, 1 )>"1"
			* В этом поле была модификация
			lcFieldName = FIELD(m.lnI- 1 )
			IF OldVal(m.lcFieldName,"rv_uz")<>EVALUATE("rv_uz."+m.lcFieldName)
				* Значение этого поля реально изменилось
				llModified = .T.
				EXIT
			ENDIF
		ENDIF
	ENDFOR

ENDCASE

IF llModified = .T.
* Была реальная модификация, создание новой записи 
* или удаление существующей записи
ENDIF

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

В случае использования GetNextModified() нужен цикл, для организации перемещения по записям.
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34072780
Surgeon2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Круто заработало,разобрал все,

вопрос такой m.lnI,для чего m.? в программе тоже есть места с такого вида это что означает?

Спасибо большое!
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34072785
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Surgeon2000вопрос такой m.lnI,для чего m.? в программе тоже есть места с такого вида это что означает?

Что означает префикс (буква) "m." перед именем
...
Рейтинг: 0 / 0
Как проверить были изменения внесены или нет?
    #34072795
Surgeon2000
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ещё раз спасибо,теперь точно все ясно!
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Как проверить были изменения внесены или нет?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]