powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / странность в while+update+skip
14 сообщений из 14, страница 1 из 1
странность в while+update+skip
    #33038511
lesha_spb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
заметил интересный эффект, такой код:
GO TOP IN tmptab
DO WHILE !EOF("tmptab")
UPDATE tmptab SET id_meter=y WHERE id_meter = x
ENDDO
эффект такой если _tally от update > 1, то текущая запись в tmptab сдвигается как надо, но если _tally=1, то текущая запись остается той же самой!
сделал так:
GO TOP IN tmptab
DO WHILE !EOF("tmptab")
UPDATE tmptab SET id_meter=y WHERE id_meter = x
IF _tally<=1
SKIP IN tmptab
ENDIF
ENDDO
все работает, но вообще странно то ли это баг, то ли фича(но если фича то скорее вредная чем полезная)
...
Рейтинг: 0 / 0
странность в while+update+skip
    #33038530
leaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
эффект действительно интересный а если не мудрить и оставить в покое системную переменную которую лучше не трогать и вместо

GO TOP IN tmptab
DO WHILE !EOF("tmptab")
UPDATE tmptab SET id_meter=y WHERE id_meter = x
IF _tally<=1
SKIP IN tmptab
ENDIF
ENDDO


записать
replace id_meter with y for id_meter = x in tmptab

то что будет?
кстати команда апдейт кажеться блочит таблицу а реплас этого не делает
...
Рейтинг: 0 / 0
странность в while+update+skip
    #33038570
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
leafкстати команда апдейт кажеться блочит таблицу а реплас этого не делает
Вообще-то наоборот. REPLACE FOR блокирует всю таблицу, а UPDATE-SQL только изменяемые записи.

Хотя сам пример действительно надуманный. Поскольку нигде в HELP не говорится как поведет себя указатель записи при выполнении команды UPDATE-SQL, то это надо контролировать самостоятельно.

Ну, а в приведенном случае вообще полный бред получиться в том смысле, что невозможно предсказать результат модификации . Но это уже на совести автора примера.
...
Рейтинг: 0 / 0
странность в while+update+skip
    #33038575
lesha_spb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
replace for вообще не подходит для использования в while,
GO TOP IN tmptab
DO WHILE !EOF("tmptab")
replace id_meter with y for id_meter = x in tmptab
enddo

после первого же реплэйса выходим из while.
...
Рейтинг: 0 / 0
странность в while+update+skip
    #33038603
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lesha_spbreplace for вообще не подходит для использования в while
Подходит, но при определенных условиях. Просто кроме опции FOR в команде REPLACE есть и опция WHILE. При наличии соответсвующего индекса все можно сделать. Но надо знать конкретную задачу, а не "то, не знаю что", что написано в примере.
...
Рейтинг: 0 / 0
странность в while+update+skip
    #33038607
leaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
тяжело с гуру спорить но всё же в споре рождаеться истина
как говориться Платон мне друг
Возможно у меня старая версия хелпа но всё же вот выдержка из хелпа к пятерке :
В отличии от команды replace команда update использует блокировку записей при обновлении множества записей в таблице открытой с разделяемым доступом . Это сокращает разрешение конфликтов записей в многопользовательской среде, но также может понизить производительность.
Для максимальной производительности открывайте таблицу для монопольного использования или используйте FLOCK( ), что бы блокировать таблицу.


На мой взляд весьма красноречиво или я чего не понимаю ?
...
Рейтинг: 0 / 0
странность в while+update+skip
    #33038623
leaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
специально для автора
там есть такая маленькая опция for отсюда вопрос нужен ли Вам вообще цикл? Ну если уж так не можете без него жить то нате:

select tmptab
scan for id_meter = x
replace id_meter with y
endscan
...
Рейтинг: 0 / 0
странность в while+update+skip
    #33038669
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
leafВозможно у меня старая версия хелпа но всё же вот выдержка из хелпа к пятерке :
В отличии от команды replace команда update использует блокировку записей при обновлении множества записей в таблице открытой с разделяемым доступом . Это сокращает разрешение конфликтов записей в многопользовательской среде, но также может понизить производительность.
Для максимальной производительности открывайте таблицу для монопольного использования или используйте FLOCK( ), что бы блокировать таблицу.

А где противоречие с тем что я написал?

ВладимирМREPLACE FOR блокирует всю таблицу, а UPDATE-SQL только изменяемые записи
...
Рейтинг: 0 / 0
странность в while+update+skip
    #33038720
leaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну в принципе противоречия нет
хотя явного указания на блокировку таблицы я не нашел по крайней мере в своем А проверять руками нет желания остается принять к сведению на веру хотя при случае обязательно проверю
возможно блокировка заголовка просто необходима хотя и в этом случае не понятно что лучше блокировка записей по одной записи или единичная блокировка заголовка?
...
Рейтинг: 0 / 0
странность в while+update+skip
    #33038738
lesha_spb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
согласен пример я привел не самый лучший:)
на самом деле было так:
select * from tab where IsTaken=0 order by id_meter into cursor tmptab readwrite
GO TOP IN tmptab
DO WHILE !EOF("tmptab")
ищем новое значение для tmptab.id_meter;
if нашли
replace id_meter WITH tMId.idob IN tmptab
endif
SKIP IN tmptab
ENDDO
попробовал делать через update, чтобы избавится от лишних итераций в while.
(записей с одинаковым id_meter в tmptab обычно несколько)
Но с update я был не прав. сделал так:
local curid
select * from tab where IsTaken=0 order by id_meter into cursor tmptab readwrite
GO TOP IN tmptab
DO WHILE !EOF("tmptab")
curid=tmptab.id_meter
ищем новое значение для tmptab.id_meter;
if нашли
replace id_meter WITH tMId.idob WHILE id_meter=curid IN tmptab
else
SKIP IN tmptab
endif
ENDDO
В таком варианте все отрабатывает правильно и как понимаю replace while все таки быстрее чем заменять по одной записи.
...
Рейтинг: 0 / 0
странность в while+update+skip
    #33038865
leaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
хотите совет - приведите весь текст полностью
...
Рейтинг: 0 / 0
странность в while+update+skip
    #33040804
lesha_spb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
щас все работает как надо.но давайте все же приведу мою ситуацию подробней. может я что нибудь делаю не лучшим образом))
суть в следующем: нужно из некоторых таблиц одной базы перенести все новые данные в аналогичные таблицы другой базы. то что данные новые определяет столбец istaken. таблицы реально находятся на sql server работаем с ними через remote view.
формат таблиц в общем случае можно описать так:
idob id_meter nomer istaken ну и набор других полей

при переносе данных из одной базы в другую нужно изменить ссылку id_meter. т.к. она может не совпадать.
в итоге имеем:
local curid
*выбираем все данные из исходной таблицы:
myquery = select * from tab where IsTaken=0 order by id_meter
SqlExec(source_handle, MyQuery, "tmptab")

GO TOP IN tmptab
DO WHILE !EOF("tmptab")
curid=tmptab.id_meter
*ищем в источнике в таблице meters номер объекта по его idob'у
USE IN SELECT("tMNum")
MyQuery = "select meter_numb from meters where idob = "+tmptab.id_meter
SqlExec(source_handle, MyQuery, "tMNum")
*ищем в получателе в таблице meters по номеру объекта его idob. это и *будет нужный нам id_meter
USE IN SELECT("tMId")
MyQuery = "select idob from meters where meter_numb = "+tMNum.meter_numb
sqlFlag = RunSqlExec(target_handle, MyQuery, "tMId")
IF RECCOUNT("tMId") > 0 &&если нашли
replace id_meter WITH tMId.idob WHILE id_meter=curid IN tmptab
else
SKIP IN tmptab
endif
ENDDO

получили в tmptab новые данные в нужном нам виде, после чего они через remote view помещаются в получатель.
например так:
SELECT TMPPOW
APPEND FROM DBF("tmptab")
SELECT TMPPOW
TABLEUPDATE()
вот и все далее работает некая процедура на sql server но это к делу не относится
...
Рейтинг: 0 / 0
странность в while+update+skip
    #33041905
Igor Korolyov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hi leaf!

Там не совсем хороший текст, вот ты и не понял :)

REPLACE ... FOR и REPLACE ... WHILE производят блокировку ВСЕГО файла для своей работы - т.е. они выполняют неявный FLOCK() - что конечно способно привести к конфликту - если в таблице уже есть какая-то блокировка (причём совершенно не имеет значения - попадает заблокированная запись под условие в FOR или WHILE или нет!!!) А вот при SQL UPDATE производится только RLOCK() блокировка, и только для тех записей, которые попадают под условие - т.е. если заблокированы "другие" записи - это ничему не мешает.
А проблема с производительностью в том, что действительно быстрее наложить одну FLOCK() и потом спокойно поменять кучу записей, чем возится с блокировкой каждой отдельной изменяемой записи. Однако надо ещё провести тест - я не удивлюсь если разница в скорости будет минимальна...

P.S. REPLACE БЕЗ "множественных" диапазонов (т.е. тот который только текущую запись меняет) делает RLOCK() - и это хорошо :)

Posted via ActualForum NNTP Server 1.1
...
Рейтинг: 0 / 0
странность в while+update+skip
    #33042513
leaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
спасибо игорь примерно так я и понял
особых проблем не возникнет как в первом так и во втором случае при грамотном использовании фокспро так что оба способа на мой взляд равноценны но всё же сумничал я не зря этот момент для меня стал более ясен спасибо всем так что всем спасибо
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / странность в while+update+skip
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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