powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / удаление записей
15 сообщений из 15, страница 1 из 1
удаление записей
    #33085716
k_sv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Очень нужна помощь новичку.
Я для отображения данных использую представление. Устанавливаю
Код: plaintext
1.
set multilock on
CURSORSETPROP('Buffering',  5 , 'v_tar_job')
Таблица имеет индекс типа Candidate с For !deleted().
В гриде (где отображается мое представление), добавляю 2 одинаковые записи (которые противоречат индексу Candidate).
Если нажать на кнопку "сохранить", в которой содержится следующий код
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
IF TableUpdate(.T.,.T.,"v_tar_job")=.F.
	LOCAL laError( 1 )
	=AERROR(laError)
	if laerror( 1 )= 1884 
	  =MessageBox('Недопустимо несколько тарифов;
                с одинаковой датой!',  64 , 'Сообщение')
	  return
	endif
ENDIF
после выдачи сообщения и возврата в мой грид я делаю пометку на удаление одной записи. После нажатия кнопки "сохранить", опять выдается сообщение. Хотя, на мой взгяд, уже индекс уже не должен иметь ничего против.

А если сперва ввести 2 одинаковые записи, одну пометить на удаление, а потом "сохранить", то все нормально.

Что я делаю не так.
Раскажите, пожалуйста, как это надо делать.
...
Рейтинг: 0 / 0
удаление записей
    #33085869
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проблема с индексом заключается в том, что контроль уникальности происходит сразу в момент ввода данных в самом буфере . Т.е. еще ДО сброса буфера.

В данном случае, ты не сможешь сдвинуть указатель записи со второй записи с дублирующим значением. Именно на нее и идет ругань. При этом не имеет никакого значение буферизирована таблица или нет.

Т.е. здесь нужен перхват сообщения об ошибке, а не контроль записи по TableUpdate() (хотя он и не помешает, но это "вторичная", необязательная, проверка).

Это одна из причин, почему я вместо контроля уникальности по индексу Candidat использую триггеры.

В твоем случае простейшее решение, это сделать на базе таблицы Local View. Все остальное останется без изменений, но здесь контроль уникальности будет происходить именно в момент сброса буфера, а не ДО него.
...
Рейтинг: 0 / 0
удаление записей
    #33085964
k_sv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ В твоем случае простейшее решение, это сделать на базе таблицы Local View. Все остальное останется без изменений, но здесь контроль уникальности будет происходить именно в момент сброса буфера, а не ДО него.
Я и использую Local View.

ВладимирМ В данном случае, ты не сможешь сдвинуть указатель записи со второй записи с дублирующим значением. Именно на нее и идет ругань
А вот по записям я почему-то спокойно хожу (несмотря на то, что я ввела несколько дублирующих). Это в моей форме. А если просто открыть представление, тогда действительно не дает сдвинуть указатель.
У меня 2 вопроса:
1. Почему у меня в форме не выдается сообщение об ошибке, а позволяет делать, все что мне вздумается?
2. На каком событии я должна перехватывать ошибку? И какой ее код?

Заранее благодарна за ответы.
...
Рейтинг: 0 / 0
удаление записей
    #33086050
k_sv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Видимо, на глупые вопросы никто не отвечает.
...
Рейтинг: 0 / 0
удаление записей
    #33086254
k_sv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хоть никто и не отвечает, осмелюсь задать еще один вопрос по аналогичной теме.
Есть таблица "zakaz" , у которого индекс id_zak типа Primary. На базе него есть Local View "look_zak".
При пометке записи на удалении в представлении - помечается запись и в таблице. Тут все нормально. Но при recall записи в представлении - ошибка: Uniqueness of index id_zak is violated. (1884)

Объясните, пожалуйста, почему так происходит.
...
Рейтинг: 0 / 0
удаление записей
    #33086353
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так. С самого начала.

Есть таблица с индексом типа CANDIDAT ... FOR !Deleted()

На ее базе создано обновляемое Local View

Редактирование этого Local View осуществляется в режиме табличной буферизации

Сброс изменений осуществляется только по команде TableUpdate() БЕЗ транзакции

Начну с конца.

Хотя кажется, что при табличной буферизации сброс изменений во всех строках по команде TableUpdate() происходит сразу. Одним пакетом. Но на самом деле это не так. Сброс изменений происходит по одной записи за раз.

Сбросили одну запись, если ошибок нет перешли к следующей. Сбросили и эту запись, если возникла ошибка, то не произошел сброс только этой самой записи на которой возникла ошибка и всех последующих. До которых еще не добрались.

НО! Те записи, которые были сброшены до возникновения ошибки успешно сохранились в исходной таблице.

Т.е. в твоем случае завели в Local View 2 одинаковые записи. Команда TableUpdate() вернула .F., но ошибка произошла при попытке сброса второй записи. А первая была успешно сброшена в исходную таблицу!

Ты возвращаешся в GRID. НО! Тут очередная "подлянка". Ведь Local View ты не обновила, хотя частичный сброс данных произошел. И тут весь вопрос в том, какую именно запись ты пометишь как удаленную. Если ту, которая уже была сброшена, то это без толку. Вместо возможных 2 дублей получишь 3 дубля (одна уже в таблице и 2 в Local View). А вот если вторую, то проблем быть не должно, но только в том случае, если первую не редактировали.

Вобщем - это надо отдельно на примерах показывать. Но проблема именно в том, что TableUpdate() частично успел сбросить записи в исходную таблицу.

Как это предотвратить? Очень просто. Надо окружить сброс буфера транзакцией. Примерно так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
BEGIN TRANSACTION
IF TableUpdate(.T.,.T.,"v_tar_job") = .T.
	END TRANSACTION
ELSE
	ROOLBACK
	LOCAL laError( 1 )
	=AERROR(laError)
	if laerror( 1 )= 1884 
		=MessageBox('Недопустимо несколько тарифов'+;
                		' с одинаковой датой!',  64 , 'Сообщение')
	endif
ENDIF

Транзакция и обеспечит факт сброса всех изменений из буфера "одним пакетом". Т.е. либо все, либо ничего.

Однако в данном случае хорошо бы еще и самостоятельно проверить на предмет наличия дублей ДО попытки сброса. Дело в том, что такая "откаченная" буферизация не очень хорошо себя ведет при повторной попытке сброса. Возможны глюки.

Еще один момент.

Тебе кажется, что если внесены изменения в Local View, а потом эти изменения были успешно сброшены в исходную таблицу, то содержимое Local View и исходной таблицы стало одинаково. На самом деле это не так! Причин множество. Для "синхронизации" содержимого необходимо сделать обновление Local View после сброса буфера. Т.е. где-то так:

Код: plaintext
1.
2.
IF TableUpdate(.T.,.T."v_tar_job")
	REQUERY("v_tar_job")
ENDIF

Отсутствие обновления (синхронизации) Local View и может стать причиной нарушения уникальности Primary Key. Т.е. вместо снятия метки с записи, ранее помеченной как удленная юудет предпринята попытка создания новой записи . А это и вызовет подобное сообщение об ошибке.
...
Рейтинг: 0 / 0
удаление записей
    #33087542
k_sv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за разъяснения. Пробую.
Но у меня еще один вопрос возник.
Я на базе таблицы делаю прелставление. Если в таблице есть помеченные на удаление записи, представление их отображает все равно не помеченными.
Как это понимать???

Еще немного, и я сойду с ума...
...
Рейтинг: 0 / 0
удаление записей
    #33087710
k_sv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Так, предыдущий вопрос снимается. Простите. Ведь представление делается запросом SQL.
При установке set deleted on помеченные записи не отображаются.
Тогда вопрос такой:
если пользователь удалил запись (сделал пометку), а потом опомнился и решил ее вернуть (по идее надо просто отрекалить), то как это сделать?
Или пусть заново вводит?
...
Рейтинг: 0 / 0
удаление записей
    #33087752
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
k_svТогда вопрос такой:
если пользователь удалил запись (сделал пометку), а потом опомнился и решил ее вернуть (по идее надо просто отрекалить), то как это сделать?
Или пусть заново вводит?
Пусть заново вводит!

Дело в том, что восстановить запись помеченную как удаленная - это не такой простой процесс как кажется. Точнее, в простых случаях такое допустимо. Но представьте себе, что было выполнено каскадное удаление ряда записей.

Например, при удалении шапки накладной надо удалить и все записи из накладной. Если пользователь передумал, то что, организовывать каскадное восстановление? А как быть с пересчетом сумм остатка? А если удаление затронуло больше таблиц?

Да, в конце-концов, а как организовать поиск той записи, которую удалили? Ведь "шттатный" режим - это SET DELETED ON. Т.е. такие записи вообще не отображаются!

И еще. Это ты знаешь, что процесс удаления разбит на 2 этапа: сначала установка метки на удаление, потом собственно физическое удаление. Но пользователь-то этого не знает! И не должен знать! Умерла, так умерла!
...
Рейтинг: 0 / 0
удаление записей
    #33095159
k_sv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за помощь.
Но у меня очередная проблема и не могу понять в чем дело.
Делаю все как и положено:

ВладимирМ
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
BEGIN TRANSACTION
IF TableUpdate(.T.,.T.,"v_tar_job") = .T.
	END TRANSACTION
ELSE
	ROLLBACK
	LOCAL laError( 1 )
	=AERROR(laError)
	if laerror( 1 )= 1884 
		=MessageBox('Недопустимо несколько тарифов'+;
                		' с одинаковой датой!',  64 , 'Сообщение')
	endif
ENDIF

Но первой же строчке выдается сообщение ошибка:
Table v_tar_job has one or more non-structural indexes open. Please close them and retry the Begin Transaction (Error 1548)

Но у меня никаких индексов-то нету...
Что это может быть? Помогите, пожалуйста.
...
Рейтинг: 0 / 0
удаление записей
    #33095365
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
k_svНо первой же строчке выдается сообщение ошибка:
Table v_tar_job has one or more non-structural indexes open. Please close them and retry the Begin Transaction (Error 1548)

Но у меня никаких индексов-то нету...
Что это может быть? Помогите, пожалуйста.
Значит есть! Видимо, где-то в коде было построение индексов для View (команда INDEX). Закрой ЯВНО все открытые НЕ структурные индексы:

Код: plaintext
1.
select v_tar_job 
SET INDEX TO

Можешь посмотреть что за индексы используя функцию ATAGINFO() - она появилась с 7 версии FoxPro. Для младших версий надо использовать TAGCOUNT() и NDX()
...
Рейтинг: 0 / 0
удаление записей
    #33095529
k_sv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирММожешь посмотреть что за индексы используя функцию ATAGINFO() - она появилась с 7 версии FoxPro. Для младших версий надо использовать TAGCOUNT() и NDX()

Нету индексов.
TAGCOUNT('v_tar_job')=0 фукция ndx() возврацает пустую строку.

У меня параметризованное представление. Или это без разницы?
...
Рейтинг: 0 / 0
удаление записей
    #33095560
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Fox зря ругаться не будет. При появлении ошибки войди в Debugger и посмотри там (в коне Watch), что вернет функция

TAGCOUNT('v_tar_job')

Кстати, может не структурный индекс был построен по какой-либо другой таблице. Не обязательно по View. Сделай поиск по всему своему коду на предмет команды INDEX.
...
Рейтинг: 0 / 0
удаление записей
    #33095641
k_sv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да, действительно, были установлены структурные индексы на другое представление, использующее с моим общую таблицу. Да, самостоятельно со всеми тонкостями долго пришлось бы разбираться.
Спасибо Вам огромное, ВладимирМ !!!
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
удаление записей
    #35602116
Игорь2004
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Недавно на практике столкнулся с ошибкой 1548
Table "alias" has one or more non-structural indexes open. Please close them and retry the Begin Transaction (Error 1548)
Close all non-structural (non-.CDX) indexes and try the operation again.
If other indexes are open on the file, their writes will go directly to disk and will not be reflected in the table changes until you issue END TRANSACTION. Consequently, if a ROLLBACK is issued, the non-structural indexes will be incorrect.
Частично о данной ошибке также идет речь в
http://]http://www.sql.ru/forum/actualthread.aspx?tid=332332&hl=1548
Таким образом вопрос заключается в том как "Close all non-structural (non-.CDX) indexes”
В связи с чем возникла идея перед каждым вызовом
Begin Transaction
вызывать метод, либо процедуру, которая будет закрывать non-structural индексные файлы.
Ничего лучшего чем нижеприведенный код мне придумать не удалось
Для базового класса форм создаю два метода closeallnonstructuralindexes и Doesnonstructuralindexexist
перед каждым вызовом
Begin Transaction
вызываю Thisform.closeallnonstructuralindexes()
** method closeallnonstructuralindexes
Код: 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.
*!*  2008 - 10 - 17  Igor Nikiforov
*!* to prevent the Error  1548 
*!*	Table "alias" has one or more non-structural indexes open. Please close them and retry the Begin Transaction (Error  1548 )
*!*	Close all non-structural (non-.CDX) indexes and try the operation again.
Local lnSelect, lnNumberoftablesopen, lnI, lcAlias, lcOrder, lcCdx
lnSelect = Select()
Local Array ladata[ 1 ]
lnNumberoftablesopen =Aused(ladata, Thisform.DataSessionId)

For lnI =  1  To lnNumberoftablesopen
   lcAlias = ladata(lnI,  1 )
   If .Not.Empty(Thisform.Doesnonstructuralindexexist(lcAlias))
      Select (lcAlias )
      lcOrder = Set("order")
      Close Indexes
      ** if the order was "non-structural", we have to restore it
      lcCdx = Cdx( 1 , lcAlias)
      If .Not.Empty(lcCdx )
         If Upper(Justfname(Right(lcOrder, Len(lcCdx)))) == Upper(Justfname(lcCdx)) && this is structural index
            If .Not.Empty(Atc([ of ], lcOrder))
               lcOrder = Left(lcOrder, Atc([ of ], lcOrder))
            Endif
            Set Order To &lcOrder
         Endif
      Endif
   Endif
Endfor
Select (lnSelect)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
** method Doesnonstructuralindexexist
**  2008 - 10 - 17  Igor Nikiforov
** returns .t. if the table or alias has non-structural indexes open
** else returns .f.
Lparameters tcTableName
If Type("tcTableName")<>"C" .Or. .Not.Used(tcTableName)
   Return .F.
Else
   Return Icase(.Not.Empty(Ndx( 1 , tcTableName)), .T., Empty(Cdx( 1 , tcTableName)), .F., .Not.Empty(Cdx( 2 , tcTableName)), .T., .Not.Forceext(Dbf(tcTableName),"CDX")==Cdx( 1 ,tcTableName))
Endif

Для обычных процедур соответсвенно
перед каждым вызовом
Begin Transaction
Do Closeallnonstructuralindexes

Код: 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.
Procedure Closeallnonstructuralindexes
   *!*  2008 - 10 - 17  Igor Nikiforov
   *!* to prevent the Error  1548 
   *!*	Table "alias" has one or more non-structural indexes open. Please close them and retry the Begin Transaction (Error  1548 )
   *!*	Close all non-structural (non-.CDX) indexes and try the operation again.
   Local lnSelect, lnNumberoftablesopen, lnI, lcAlias, lcOrder, lcCdx
   lnSelect = Select()
   Local Array ladata[ 1 ]
   lnNumberoftablesopen =Aused(ladata)

   For lnI =  1  To lnNumberoftablesopen
      lcAlias = ladata(lnI,  1 )
      If .Not.Empty(Doesnonstructuralindexexist(lcAlias))
         Select (lcAlias )
         lcOrder = Set("order")
         Close Indexes
         ** if the order was "non-structural", we have to restore it
         lcCdx = Cdx( 1 , lcAlias)
         If .Not.Empty(lcCdx )
            If Upper(Justfname(Right(lcOrder, Len(lcCdx)))) == Upper(Justfname(lcCdx)) && this is structural index
               If .Not.Empty(Atc([ of ], lcOrder))
                  lcOrder = Left(lcOrder, Atc([ of ], lcOrder))
               Endif
               Set Order To &lcOrder
            Endif
         Endif
      Endif
   Endfor
   Select (lnSelect)


Function Doesnonstructuralindexexist
   **  2008 - 10 - 17  Igor Nikiforov
   ** returns .t. if the table or alias has non-structural indexes open
   ** else returns .f.
   Lparameters tcTableName
   If Type("tcTableName")<>"C" .Or. .Not.Used(tcTableName)
      Return .F.
   Else
      Return Icase(.Not.Empty(Ndx( 1 , tcTableName)), .T., Empty(Cdx( 1 , tcTableName)), .F., .Not.Empty(Cdx( 2 , tcTableName)), .T., .Not.Forceext(Dbf(tcTableName),"CDX")==Cdx( 1 ,tcTableName))
   Endif
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / удаление записей
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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