Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Обновление автоинкремента в мёртвых запросах [D6, Paradox]


Sour Smile ©   (2007-03-14 14:20:00) 

В DBGrid1отображаются данные из Query1.
Запрос элементарный: 'SELECT Id, Field1, Field2 FROM Table1 ORDER BY Field1'( Id- автоинкрементное поле, предназначенное для задания уникальности каждой записи, а Field1и Field2- собственно поля с данными).
Тем не менее использование оператора 'ORDER BY'делает этот запрос мёртвым (т.е. нередактируемым даже при установленном в Trueсвойстве RequestLive). Собственно об этой плохой особенности оператора 'ORDER BY'сказано в справке по LocalSQL.
Поэтому, чтобы пользователь всё же мог редактировать данные в гриде, приходится устанавливать в Trueсвойство CachedUpdatesи подключать к Query1компонент UpdateSQL1.
Запросы в UpdateSQL1тоже элементарные:
1) вставка: 'insert into Table1 (Field1, Field2) values (:Field1, :Field2)'
2) модификация: 'update Table1 set Field1 = :Field1, Field2 = :Field2 where Id = :OLD_Id'
3) удаление: 'delete from Table1 where Id = :OLD_Id'

Для того чтобы после изменения или удаления пользователем каждой записи, данные из кэша применялись собственно в таблицу, на событиях 'AfterPost'и 'AfterDelete'у компонента 'Query1'прописан код: Query1.ApplyUpdates; Query1.CommitUpdates

Теперь собственно описание проблемы: когда пользователь добавляет новую запись, вносит в неё данные и применяет изменения (Post), новая запись с введёнными данными действительно добавляется в таблицу, однако в гриде автоинкрементное поле остаётся пустым (в самой таблице естественно в него записывается некоторое значение).

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

Однако, предположим, что пользователь заметил ошибку и решил подредактировать только что введённую запись и вот теперь, после нажатия Post вылетает ошибка: 'Update failed'... И это можно понять: ведь в запросе на обновление указано, что 'update ... where Id = :OLD_Id', но ведь OLD_Idпустое (!).

По той же причине будет ошибка и при удалении этой записи. И совсем наоборот: и обновление и удаление прекрасно работают если запись была добавлена ранее, до последнего 'Query1.Open'. Но переоткрывать запрос после каждой вставки нехорошо, да и нужно после переоткрытия спозиционировать фокус ввода на вновь добавленную запись, а как же спозиционируешь, если неизвестно значения его поля 'Id'...

Как же заставить обновлять автоинкрементное поле в кэше при вставке новой записи?


Mike Kouzmine   (2007-03-14 18:03:00) [1]

Для работы с парадоксом адо лишняя надстройка. Работа идет через бде. Гораздо функциональнее и проще работать с родными для этого формата компонентами, а именно TTable из вкладки БДЕ.


Desdechado   (2007-03-14 17:55:00) [2]

> Переоткрывать после каждой вставки дурной тон, так как:
Кто тебе говорил о переоткрытии после каждой? Я тебе говорил о переоткрытии после сохранения (одного на пачку).
Ку?

> пользователь за один сеанс может ввести 100 или 1000 записей
> и все эти введённые данные могут не примениться из-за одной
> ошибочной записи из этой "пачки"
Глупости. Сохранять их можно и по одной (каждая в своей транзакции, а не все в одной транзакции), но по команде пользователя, а не автоматом.
Или у тебя все данные взаимозависимы (первая запись не прошла, остальные уже не смогут из-за логической завязки на предыдущие)?

И работать с данными надо по критериям, а не как с физической таблицей "более 70 мегабайт и продолжает расширяться".

Sour Smile   (14.03.07 17:32) [7]
Это реклама АДО? Чего ж не пользуешься?


Sour Smile   (2007-03-14 17:32:00) [3]


> Sergey13 ©   (14.03.07 16:26) [5]
> > [4] Sour Smile   (14.03.07 16:09)
> Дурной тон работать с такими объемами в Парадоксе и брать
> всю таблицу сразу, да еще с сортировкой.

Если речь зашла о дурном тоне, то лично я вообще считаю дурным тоном работать через BDE. К счастью по работе мне не приходится с ним работать - моя основная среда работы с базами: MSSQL (через ADO). В MSSQL таких простецких вопросов не возникло бы (при 'order by' возвращаются живые, редактируемые данные). А если бы и возникло думаю и их обошёл бы.

Например, одна из проблем в моём вопросе (это также и проблема компонента TUpdateSQL), как узнать какое значение получило поле Id (автоинкрементное) после добавления новой записи (т.е. 'insert into ...')и я думаю что эту проблему (нормальными способами) в BDE к сожалению решить нельзя. А вот в MSSQL достаточно изменить запрос для добавления новой записи на такой: 'insert into Table1 (Field1, Field2) values (:Field1, :Field2) select @@identity'и если открывать его не через ADOQuery1.ExecSQL, а через ADOQuery1.Open, то добавится новая запись и откроется датасет с единственным полем и единственной записью в котором собственно и будет идентификатор (т.е. значение автоинкрементного поля)  добавленной записи (узнать его элементарно: ADOQuery1.Fields[0].AsInteger)

Однако это отклонение от сути вопроса


Mike Kouzmine   (2007-03-14 16:39:00) [4]

Можно сделать индекс по филду1, открыть ттайблем, установив ему indexname := пофилду1 и добавлять. Все ид после пост будут видны.


Sergey13   (2007-03-14 16:26:00) [5]

> [4] Sour Smile   (14.03.07 16:09)
Дурной тон работать с такими объемами в Парадоксе и брать всю таблицу сразу, да еще с сортировкой.


Sour Smile   (2007-03-14 16:09:00) [6]


> Sergey13 ©   (14.03.07 15:07) [1]
> AutoRefresh - это не оно?
Ксожалению AutoRefresh на мёртвых запросах не работает (об этом вроде тоже в справке есть).


> Desdechado ©   (14.03.07 15:22) [3]
> > Но переоткрывать запрос после каждой вставки нехорошо,
>
> Однако сохранять каждое изменение каждой записи отдельно
> ты почему-то не считаешь дурным тоном:
> > на событиях 'AfterPost' и 'AfterDelete' у компонента 'Query1'
> прописан код: Query1.ApplyUpdates; Query1.CommitUpdates
>
> Обычно сохраняют изменения пачкой, когда пользователь все
> наредактировал, что ему хотелось, и нажал "сохранить". Тут
> и переоткрыть запрос не грех. Заодно увидишь, как изменился
> порядок записей, если он редактировал сортируемые поля.

Переоткрывать после каждой вставки дурной тон, так как: 1) после этого необходимо спозиционироваться на эту запись (а как это сделать, если неизвестно Id вновь вставленной записи?); 2) таблица огромная (более 70 мегабайт и продолжает расширяться) и на каждое её открытие уходит масса времени (разве не дурной тон? а так у пользователя есть кнопка по которой он может её переоткрыть в любой момент для пересортировки)

Первоначально у меня пачками и обновлялись записи, однако и тут я столкнулся с некоторыми проблемами и в первую очередь с тем что пользователь за один сеанс может ввести 100 или 1000 записей и все эти введённые данные могут не примениться из-за одной ошибочной записи из этой "пачки"... (я ещё жить хочу :). Вторая же проблема в том, что мне в любой моментнужно знать Idтекущей записи.


Desdechado   (2007-03-14 15:22:00) [7]

> Но переоткрывать запрос после каждой вставки нехорошо,
Однако сохранять каждое изменение каждой записи отдельно ты почему-то не считаешь дурным тоном:
> на событиях 'AfterPost' и 'AfterDelete' у компонента 'Query1' прописан код: Query1.ApplyUpdates; Query1.CommitUpdates

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


Johnmen   (2007-03-14 15:12:00) [8]


> Как же заставить обновлять автоинкрементное поле в кэше
> при вставке новой записи?

После ApplyUpdates, если не было ошибок, кэш пуст. Это так, к слову....
А вот в наборе данных "увидеть" ID - только перезапрашивать НД (close-open) при тех условиях, которые приведены (Paradox+BDE).
Извращения не рассматриваем...


Sergey13   (2007-03-14 15:07:00) [9]

AutoRefresh - это не оно?


Наверх

Титульная страница Поиск, карта сайта Написать письмо