-
Для работы с БД использую ADO. Файл обычный аксесовский mdb. В базе всего одна таблица из 4-х полей без автоинкрементного поля. Все поля текстовые. Первое поле (screen_name) индексное, совпадения запрещены, в остальных полях совпадения разрешены.
Перед добавлением данных в таблицу делается проверка:
if form1.ADODataSet1.Locate('screen_name',Acc,[])=false then begin //такого имени в базе нет - добавляем его try form1.ADODataSet1.Insert; form1.ADODataSet1['screen_name']:=Acc; form1.ADODataSet1.Post; except end; end;
На всякий пожарный блок добавления данных в БД помещен в try/except.
Периодически, пользователи сообщают о том, что в ходе записи в базу появляется сообщение "Изменения не были успешно внесены из-за повторяющихся значение в индексе". Не моуг понять как такео возможно. Во-первых я проверяю есть ли запись в базе прежде чем в нее пишу. Во-вторых подобную месагу должен задержать блок try/except. Получается что Locate отрабатывает не верно или что?
-
при отсутствии ключевого поля в выборке/или при не указании использовать ключ для формирования запроса/или при не считывании значения ключа(автоинкремента) из базы в рекордсет, определение записи идет по всем возможным полям. + Locate ищет в локальной выборке, а указанная ошибка идет из базы. ++ есть хорошие статьи про ADO на королевстве...
-
sniknik я правильно понял, что нужно все же добавить автоинкрементное поле?
На счет Locate. Не очень понял на счет локальной выборки. Перед началом работы с таблицей выполняется следующий код: form1.ADODataSet1.Active:=false; form1.ADODataSet1.CommandText:='SELECT * FROM '+TableName; form1.ADODataSet1.Open
в итоге ADODataSet1 хранит всю таблицу.
-
> что нужно все же добавить автоинкрементное поле? если хочешь по нему обновлять записи то обязательно.
> Не очень понял на счет локальной выборки. любой запрос возвращает набор данных, получается копия на клиенте, без синхронизации с сервером (даже если он у тебя тут же на твоем же компе) ты можешь хоть сто раз делать локейт... на клиенте, но при записи в базу они там могут дублироваться.
> в итоге ADODataSet1 хранит всю таблицу. программа одна работает? из другого источника записи быть не может? это раз.
-
-
Уточняю. Программа работает с БД монопольно, база на том же компе что и программа. Поэтому все же склоняюсь к тому, что один раз при коннекте с БД (при старте программы) загрузив в нее всю таблицу я обеспечиваю в дальнейшем Locate возможность искать по всей таблице а не по ее части. Другой вопрос. Если скажем при старте программы в базе было 100 записей и в ADODataSet1 загрузили их все, но в ходе работы записи то постепенно добавляются. Будет ли Locate искать все время по первым 100 записям или его поле поиска будет расширятсья вместе с ростом кол-ва записей?
На счет оновление записей по автоинкрементному полю.
Вот расширенние кода приведенного мной выше где видно что именно я обновляю если запись в БД уже имеется.
if form1.ADODataSet1.Locate('screen_name',Acc,[])=false then begin //такого имени в базе нет - добавляем его try form1.ADODataSet1.Insert; form1.ADODataSet1['screen_name']:=Acc; form1.ADODataSet1['dt']:=DateTimeToUnixTime(Now); form1.ADODataSet1['id']:=UserID; form1.ADODataSet1['main_list']:='1'; form1.ADODataSet1.Post; except end; end else begin //имя в базе присутсвует - обновим запись form1.ADODataSet1.Edit; form1.ADODataSet1['dt']:=DateTimeToUnixTime(Now); form1.ADODataSet1['main_list']:='1'; form1.ADODataSet1.Post; end;
-
уточняю. или работаешь правильно, или смирись с ошибками, обвиняй во всем "этот глючный виндовс".
> где видно что именно я обновляю если запись в БД уже имеется. еще из него видно, что описанная ошибка произойдет при нажатии на кнопку с этим кодом более 1 раза в секунду. если ты проигнорировал все ранее мной (в основном конечно ссылка, мои объяснения подозреваю не очень понятны) сказанное.
|