![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Обновление автоинкремента в мёртвых запросах [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 - это не оно?