Форум: "Базы";
Текущий архив: 2007.06.03;
Скачать: [xml.tar.bz2];
ВнизОбновление автоинкремента в мёртвых запросах Найти похожие ветки
← →
Sour Smile (2007-03-14 14:20) [0]В
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"
...
Как же заставить обновлять автоинкрементное поле в кэше при вставке новой записи?
← →
Sergey13 © (2007-03-14 15:07) [1]AutoRefresh - это не оно?
← →
Johnmen © (2007-03-14 15:12) [2]
> Как же заставить обновлять автоинкрементное поле в кэше
> при вставке новой записи?
После ApplyUpdates, если не было ошибок, кэш пуст. Это так, к слову....
А вот в наборе данных "увидеть" ID - только перезапрашивать НД (close-open) при тех условиях, которые приведены (Paradox+BDE).
Извращения не рассматриваем...
← →
Desdechado © (2007-03-14 15:22) [3]> Но переоткрывать запрос после каждой вставки нехорошо,
Однако сохранять каждое изменение каждой записи отдельно ты почему-то не считаешь дурным тоном:
> на событиях "AfterPost" и "AfterDelete" у компонента "Query1" прописан код: Query1.ApplyUpdates; Query1.CommitUpdates
Обычно сохраняют изменения пачкой, когда пользователь все наредактировал, что ему хотелось, и нажал "сохранить". Тут и переоткрыть запрос не грех. Заодно увидишь, как изменился порядок записей, если он редактировал сортируемые поля.
← →
Sour Smile (2007-03-14 16:09) [4]
> 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
текущей записи.
← →
Sergey13 © (2007-03-14 16:26) [5]> [4] Sour Smile (14.03.07 16:09)
Дурной тон работать с такими объемами в Парадоксе и брать всю таблицу сразу, да еще с сортировкой.
← →
Mike Kouzmine © (2007-03-14 16:39) [6]Можно сделать индекс по филду1, открыть ттайблем, установив ему indexname := пофилду1 и добавлять. Все ид после пост будут видны.
← →
Sour Smile (2007-03-14 17:32) [7]
> 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
)
Однако это отклонение от сути вопроса
← →
Desdechado © (2007-03-14 17:55) [8]> Переоткрывать после каждой вставки дурной тон, так как:
Кто тебе говорил о переоткрытии после каждой? Я тебе говорил о переоткрытии после сохранения (одного на пачку).
Ку?
> пользователь за один сеанс может ввести 100 или 1000 записей
> и все эти введённые данные могут не примениться из-за одной
> ошибочной записи из этой "пачки"
Глупости. Сохранять их можно и по одной (каждая в своей транзакции, а не все в одной транзакции), но по команде пользователя, а не автоматом.
Или у тебя все данные взаимозависимы (первая запись не прошла, остальные уже не смогут из-за логической завязки на предыдущие)?
И работать с данными надо по критериям, а не как с физической таблицей "более 70 мегабайт и продолжает расширяться".
Sour Smile (14.03.07 17:32) [7]
Это реклама АДО? Чего ж не пользуешься?
← →
Mike Kouzmine © (2007-03-14 18:03) [9]Для работы с парадоксом адо лишняя надстройка. Работа идет через бде. Гораздо функциональнее и проще работать с родными для этого формата компонентами, а именно TTable из вкладки БДЕ.
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2007.06.03;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.042 c