powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Удаление (корректировка) группы записей при буферизации
10 сообщений из 10, страница 1 из 1
Удаление (корректировка) группы записей при буферизации
    #33389031
men dea
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВОПРОС 1. Возникнут ли у меня ошибки при работе в сети, если я с двумя FREE TABLES провожу подобную операцию удаления?

* ВОПРОС 2: нужна ли след. строка для конкретно для этой задачи?

Set Exclusive Off
Set Multilocks On
Use teams In 0 Shared
Use players In 0 Shared
CursorSetProp("Buffering",5,'teams')
CursorSetProp("Buffering",5,'players')
...
Locate For teams.Name='Алания'
...
If 6=Messagebox('Удалить?',4+32+256)

Delete All For players.idTeam=teams.idTeam In players
* ВОПРОС 3. Стоит ли заменить предыдущую строку нижеследующей?
* DELETE FROM players WHERE players.idTeam=teams.idTeam
IF Tableupdate(.T.,.T.,'players')
* успешно удалены игроки
ENDIF

Delete In teams
IF Tableupdate(.F.,.T.,'teams')
* успешно удалена команда
ENDIF

Endif

Собственно, ЗАГОГУЛИНА :) в том, что подходящий примерчик из книги с TRANSACTION тут не применить, т.к. это - не БД. А операция массового удаления в players не проверяет успешность удаления каждой конкретной записи. Может, цикл писать на проверку TableUpdate()=.T. ?
Или TableUpdate(.T.,.T.) все нипочем, лишь бы сервер не отрубился?
А вариант DELETE-SQL вроде сам должен разобраться с блокировками и удалениями...
...
Рейтинг: 0 / 0
Удаление (корректировка) группы записей при буферизации
    #33390122
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. Без транзакции - обязательно. В версии VFP9 есть возможность наложить транзакцию на свободные таблицы

2. Да. Поскольку в таком контексте, команда DELETE будет сравнивать каждую запись таблицы Players с одной единственной (текущей) записью из таблицы Teams. Поэтому предварительная установка указателя на нужную запись просто необходима.

3. Без разницы. Удаление ведь будет происходить не в исходной таблице, а в буфере таблицы. Причем еще не факт, что команда Delete-SQL сможет найти все нужные записи. Она ведь может проверять условие WHERE не в буфере, а в исходной таблице.

Со свободными таблицами у тебя только один вариант действия: перед сбросом буфера попытаться вручную заблокировать нужную таблицу. Примерно так:

Код: plaintext
1.
2.
3.
4.
5.
select MyTab
IF FLOCK() = .T.
	=TableUpdate(.T.,.T.)
	UNLOCK
ENDIF

В противном случае нет никакой гарантии в том, что будут удалены ВСЕ записи. Т.е. может оказаться так, что будет сброшен буфер только для некоторых записей, а остальные так и остануться не удаленными.

Впрочем, если для твоей задачи это не имеет значения, то можешь и не блокировать таблицы.
...
Рейтинг: 0 / 0
Удаление (корректировка) группы записей при буферизации
    #33390864
men dea
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВОПРОС 1. У меня 8-й VFP. Стало быть, транзакции free tables не для меня ?

ВОПРОС 2. Ошибочка вышла, следует читать так:

* ВОПРОС: нужна ли следующая строка конкретно для этой задачи?
Set Multilocks On
…..

Кстати, после вашего ответа, появился новый
ВОПРОС 2а
А если в тот момент, когда идет удаление в дочернем файле, в родительском "доброжелатели грохнут" запись для сравнения? С чем тогда сравнивать? Или эталон в любом случае остается в моем буфере, пока я его сам не "замочу"?

ВОПРОС 3. Почему команда Delete-SQL не сможет найти все нужные записи? Если она будет проверять условие WHERE не в буфере, а в исходной таблице, то это ж еще лучше. Там-то все реальные записи и живут. Или она непредсказуемо выбирает место своей деятельности: буфер или таблицу?
"…если для твоей задачи это не имеет значения, то можешь и не блокировать таблицы."
Это как надо понимать ? То, что я поиграл с буфером, а в таблицу реально ничего не сбрасываю? Или то, что у меня незагруженная сеть и столь редки конфликтные ситуации, что особенно и беспокоиться не о чем?
********************************
За основу сброса изменений взял ваш, Владимир М., примерный код кнопки "Сохранить" в режиме оптимистической табличной буферизации (5)
Правда, у меня не БД, а отдельные таблицы. Поэтому пришлось закомментировать следующие три строки:
BEGIN TRANSACTION
END TRANSACTION
ROLLBACK

Но при следующей последовательности событий выплыл эффект реанимации:

1. Первый user открывает запись на корректировку.
2. Второй тем временем удаляет эту запись
3. Пытается сбросить изменения с Tableupdate(.F., .F.)
4. Естественно появляется предложение записать поверх.
5. Ответ "ДА".
6. Tableupdate(.F., .T.)

И тут чудо: удаленная запись восстанавливается со значениями первого user.

По логике, думаю, так и должно быть. Все бы ничего, но могли быть удалены связанные записи в дочерних free tables. Поэтому у меня

ВОПРОС 4. Вы даете примерный код, не утруждаясь на доп. разбор такой мелочи? И в код программы нужно внести доп. обработку записи?
Типа:

IF Curval("Deleted()")
=MessageBox('А записи-то уже нет, дружок!', 0)
ENDIF

ВОПРОС 5. Если я сам собираюсь изменить/удалить связанную с нею группу дочерних, то могу я так поступить?

SELECT players
DELETE ALL FOR players.idTeam=teams.idTeam IN players
IF FLOCK() = .T.
=TABLEUPDATE(.T.,.T.)
UNLOCK
ENDIF

Или вторую и третью строки программы стоит поменять местами?

Кстати, непонятно, в чем преимущество DELETE-SQL перед DELETE, если особого тока от ее блокировок нет? Да еще и может уменьшить производительность. Или оно только в БД проявляется?

ВОПРОС 6. Собственно у меня нет полной ясности с Tableupdated( lAllRows) ,
когда lAllRows =.T.
Скорость работы при оптимистической буферизации сильно зависит от того, 3-я это или 5-я? Или 5-я буферизация была введена, по большей части, для подобных однострочных, но "оптовых" операций с записями, а не для ускорения скорости путем "накопительства"? Не лучше ли, не отходя от кассы, сразу обрабатывать текущие изменения, не накапливая "на потом"? Но для этого, вроде есть "3-й вид оптимизма".

7. Кстати, а есть возможность сбрасывать, например в WORD, блоки русскоязычного текста в толковой кодировке?
...
Рейтинг: 0 / 0
Удаление (корректировка) группы записей при буферизации
    #33390938
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВОПРОС 1, 2, 2а

А самому попробовать? 5 минут экспериментов и все ясно. Не надо ждать пока тебе кто-то ответит.

ВОПРОС 3

Ты изменил в буфере значение поля players.idTeam на то значение, которое впоследствии служит признаком отбора записей на удаление. Надо ли удалить и эту запись тоже?

ВОПРОС 4

Насколько вероятна такая ситуация? Кто в этом случае прав? Тот кто удалил или тот кто восстановил? Откуда я знаю? Это как раз те "мелочи", которые каждый решает в зависимости от постановки задачи.

Тем более, Вы отказались от контейнера базы данных и теперь пытаетесь реализовать сильно навороченным программированием то, что элементарно решается через Referenty Integrities в контейнере базы данных. И это далеко не единственная проблема с которой Вы столкнетесь из-за работы с Free Tables.

ВОПРОС 5

Команда DELETE модифицирует буфер. Поэтому другие пользователи о ней просто ничего не знают. Хотя с точки зрения возможного отката изменений, более корректно сделать попытку блокировки ДО команды DELETE.

ВОПРОС 6

Тип буферизации не имеет никакого отношения к скорости. Это разный способ контроля буфера таблиц.

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

Табличный - это полный контроль со стороны программиста. Никаких автоматических попыток сброса буфера. Исключительно по команде TableUpdate().

ВОПРОС 7
Конечно. А какие проблемы?
...
Рейтинг: 0 / 0
Удаление (корректировка) группы записей при буферизации
    #33391233
men dea
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Конечно, скучно помогать упрямцу следующему порочным маршрутом. :)

Владимир М., я согласен с вами, БД была бы правильнее F/Tables. Но проблема в том, что у меня не получается классическое, как в книжных примерах, построение. Глядя на то, как она организуется, я не пойму, как этот "уродец" будет жить?

Моя задача гораздо сложнее, но суть проблемы проще представить таким образом: должны быть

1. справочник по агентам: agent
- idAGENT (AutoInc, код агента),
- nOPERATOR (оператор, последним работавший со справочной информацией по этому агенту),
- прочая справочная информация об агенте.

2. справочник по операторам: operator
- idOPERATOR (AutoInc код оператора),
- прочая справочная информация по оператору.

3. справочник по городам town
- idTOWN (AutoInc, код города),
- прочая справочная информация по городу.

4. собственно рабочий файл zakaz
- nAGENT агент
- nTOWN_FROM (откуда товар взял)
- nTOWN_TO (куда перевез)
- nOPERATOR (оператор, оформивший заказ)
- прочая информация

Как видно, справочник по операторам должен быть прицеплен сразу к agent и zakaz, а справочник town к двум полям в zakaz.

Если все эти 4 файла сцепить нитками связей в Database–дизайнере, то мне кажется, что ничего не будет работать, т.к. этот квартет будут раздирать внутренние противоречия. В файлах zakaz и operator VFP может потребоваться одновременно сделать активными по 2 записи. А открывать дополнительные курсоры Designer не позволяет, хотя и не возражает против столь дикой, IMHO, реляции файлов в БД.

5-мин. экспериментом тут не отделаешься, тем более, что одних только справочников у меня далеко не 3. Поэтому я и направился по пути free tables. Мне казалось, что так проще надежнее…

Может, я зря в панику ударяюсь? И VFP прекрасно "разрулит" все дела в этой БД?
...
Рейтинг: 0 / 0
Удаление (корректировка) группы записей при буферизации
    #33393596
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы перепутали понятия.

Связи в контейнере базы данных - это вовсе не обязательная вещь. Это всего-лишь инстурмент для автоматической генерации некоторых триггеров.

В FoxPro недопустимо делать дублирующие связи. Т.е. настраивать между двумя таблицами две разные связи. В данном случе не пройдет связка между таблицей городов (town) и рабочей таблицей (zakaz), поскольку здесь требуется установить 2 паралельные связи.

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

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

Собственно, почитайте по триггерам статью

Триггер

Ну, и для большей ясности о связях

Связи и отношения между таблицами

Тут важно понять простую вещь. Все то, что делается в FoxPro через дизайнеры, во-первых, всегда "ущербно". Не в смысле "не правильно", а в смысле "ограничено". Поскольку далеко не все возможные ситуации можно автоматизировать.

А, во-вторых, все то, что делает дизайнер ВСЕГДА можно повторить программно БЕЗ дизайнера. Ну, а раз дизайнером не пользуемся, то получаем значительно больше возможностей. Устраняются ограничения, накладываемые собственно дизайнером.

Т.е. зря в панику ударились. ВСЕ контейнер базы данных не разрулит. Но он позволит существенно облегчить процесс написания приложения. Автоматические триггера снимут хотя бы часть проблем, что само по себе ценно. Все остальное - уже придется писать вручную.

Но написать код триггера задача существенно более простая, чем писать технологию обеспечения ссылочной целостности на свободных таблицах.
...
Рейтинг: 0 / 0
Удаление (корректировка) группы записей при буферизации
    #33393620
Igor Korolyov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hi men dea!

> Как видно, справочник по операторам должен быть прицеплен сразу к agent и
> zakaz, а справочник town к двум полям в zakaz.

Это нормальная ситуация для БД.

> Если все эти 4 файла сцепить нитками связей в Database-дизайнере, то мне
> кажется, что ничего не будет работать, т.к. этот квартет будут раздирать
> внутренние противоречия.

В некоторых версиях фокса, при генерации тел триггеров ссылочной целостности
есть ошибка, которая проявляется как раз в ситуации когда из одной таблицы
имеется более одной связи к другой таблице (как у тебя в случае со связкой
заказ-город). Но эта ошибка довольно легко исправляется, после чего никаких
проблем не возникает. И никакие "противоречия" никого "раздирать" не будут.
Тем более что ты строишь свою схему на основании AUTOINC полей, и тем самым
сразу отвергаешь любые нездоровые попытки модификации поля первичного ключа
(и если собственно AUTOINC я лично недолюбливаю, то подобное ограничение на
правку PK - могу лишь приветствовать).
Сделать тест для твоей базы - это если не 5, то 10 минут - в т.ч.
сгенерировать все триггера, и посмотреть как они себя поведут в случае
попыток нарушения ссылочной целостности. Как совет - не покупайся на
cascade, хотя это и звучит круто - это весьма своеобразное правило, и
применяется оно не так часто как Restrict - т.е. простое поддержание
целостности путём запрета операций эту самую целостность нарушающих.
Если действтельно интересно - посмотри как "внутри" работают тригера
созданные построителем - увидишь, что никакого конфликта там не будет - для
своих целей триггера повторно открывают (а потом конечно закрывают) нужные
таблицы.

Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Удаление (корректировка) группы записей при буферизации
    #33396058
Igor Korolyov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hi Владимир!

> В FoxPro недопустимо делать дублирующие связи

Они не дублирующие, они разные - от поле1 к Справочник_PK и от поля2 к
Справочник_PK (т.е. 2 внешних ключа, ссылающихся на одну таблицу) - это
вполне допустимо для фоксового контейнера БД.
Другой вопрос, что есть небольшая помарочка в RI триггерах - я помнится
описывал где и что надо "подкрутить" чтобы и для таких связей корректно
работал RI.

Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Удаление (корректировка) группы записей при буферизации
    #33401150
men dea
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"Вы перепутали понятия"
Понял, что означает эта фраза, только после того, как экспериментальный вариант БД заработал.
:)
Вы правы. Подобные "нитки" (2 к 1 и 1 к 2) прокатывают.

Что не понравилось:
1. Надоело везде выставлять RESTRICT после каждого изменения. Чуть поменял что-то в структуре файла или чихнул, – тут же исправляй REFERENTIAL INTEGRITY. Они по умолчанию упрямо превращаются в IGNORE.
Есть способ, чтобы сразу все состояния перегонять в RESTRICT?

2. Когда ввожу новую запись, (например, в zakaz), хотелось все пункты формы-бланка содержали белые (пустые) поля. Видно, где уже данные ввел, а где нет. В реальной задаче миллион справочников, и не все поля вводится по порядку. Бланк будет содержать многостраничный PageFrame и от значений будет в глазах рябить. .NULL. не во всех случаях допустимо, а непустой default может оказаться не таким, что нужно по логике задачи. Смотришь, вроде все заполнено, а что-то забыл переставить в нужное состояние, и "пошла" гулять ошибка оператора, хотя INTEGRITY is OK.

APPEND BLANK с готовыми пустыми значениями вызывает ошибку триггера, а присваивать default "абы что-нибудь" не хочется… Как и вводить в справочники нулевые значения.
Пришлось навесить на кнопку НОВАЯ ЗАПИСЬ дополнительно

APPEND BLANK (со значениями default)
SCATTER memvar BLANK EXCEPT поля AutoInc
GATHER memvar

чтобы переписать значения "удобной пустотой". Ведь до тех пор, пока не сделана TABLEUPDATE ошибки не будет…
Что обычно делают в этих случаях?

3. Когда при вводе происходит ошибка, то непонятно, в каком из полей произошло нарушение целостности. Приходится пробежаться по всем, проверить самому. В Free Tables так и делал, чтобы ошибки не было. Вешал на кнопку СОХРАНИТЬ что-то вроде:

Do Case
Case Empty(mycursor.MYFIELD) && или иная проверка
Thisform.Pageframe1.ActivePage=1
Thisform.Pageframe1.Page1.tMYFIELD.SetFocus()
…..
Endcase

Может, где-то имеется готовая ссылка на поле – причину беспокойства триггера? Aerror() не возвращает, вроде…
...
Рейтинг: 0 / 0
Удаление (корректировка) группы записей при буферизации
    #33401337
Igor Korolyov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hi men dea!

1) У меня ничего не "слетает" конечно если не разрушать и не пересоздавать
сами связи.
2) Установить их можно програмно - открыв dbc как dbf (USE MyDB.dbc IN 0
AGAIN ) и там заменив 3 символа в поле RIInfo для записей с
Objecttype="Relation" - эти 3 символа - типы ограничений. т.е. RRR - это
restrict по всем 3-м операциям. Конечно от необходимости запускать RI
построитель и перегенерировать код это не избавляет - ЕСЛИ конечно появились
новые связи или существенно изменились связанные таблицы (в плане полей
связи конечно). Иначе ничего делать не надо - рабортоспособность уже
созданного триггера не завивит от наличия связи в БД (именно для триггеров
создаваемых штатным построителем RI!!! Для других триггеров это может
оказаться более критично).
3) Разберись с буферизацией. Если включена буферизация, то можно добавлять
пустую запись - триггера будут работать ТОЛЬКО при попытке её сохранения. А
вообще часть довольно удобно держать в справочниках служебные записи -
например с кодом 0 и надписью типа "не заполнено" - т.е. можно тогда даже
сохранять "неполные" записи - а уже отдельными режимами искать всех подобных
"недозаполненных" и решать что с ними делать. Представь что пользователю по
зарез надо ввести скажем клиента, а из какого он города, или на какой улице
его офис - он не знает. Не стоит запрещать ему ввод значения типа "не знаю"
:)
4) NULL в качестве внешнего ключа мне не нравтся, а вот для полей не
связанных ни с чем - он вполне уместен - через SET NULLDISPLAY можно его
"красиво" отображать.
5) Если ты имел в виде ошибку триггера - то надо смотреть глобальный массив
gaErrors - его создаёт и заполняет любой триггер в случае ошибки (конечно
опять таки это особенность триггера созданного RI построителем. Твой триггер
может возвращать такую информацию иными средствами). AERROR() конечно будет
просто сообщать что Trigger Failed...

Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Удаление (корректировка) группы записей при буферизации
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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