Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Проблема с обновлением измененной записи  [new]
ROLpogo
Member

Откуда: Реутов
Сообщений: 219
Проблема следующая:
В программе открывается ADO рекордсет на основе запроса select * from v_MyView where ID = 1.
Здесь:
v_MyView - обновляемое представление (view with metadata) с триггерами на вставку, обновление и удаление;
ID - первичный ключ одной из таблиц (MyTable) во view.
Открытие рекордсета происходит так:

rs->CursorLocation = adUseClientBatch;
rs->Open("select * from v_MyView where ID = 1", Connection, adOpenStatic, adLockBatchOptimistic, adCmdText);

Обновление происходит так:
rs->UpdateBatch(adAffectAll);

Все работает без ошибок, пока кто-то не сделает исправление какого-либо поля в MyTable в период между открытием рекордсета и его обновлением.
В этом случае получаем всем известную ошибку:
"Row cannot be located for updating. Some values may have been changed since it was last read
(Не удается обнаружить строку для обновления. Некоторые значения строки могли быть изменены с момента последнего чтения)".

Возникает она из-за того, что на сервер отправляется запрос вида:
update v_MyView set MyField1 = 'MyText' where ID = 1 and MyField1 = '' and MyField2 = 0 and MyField3 = 1 and ... и так далее по всем полям.
И т.к. одно из полей было кем-то изменено, то запись не находится и генерится ошибка. Мне же, в моем случае, не важно, были ли сделаны кем-то какие-либо изменения в каком-либо из полей кроме MyTable.ID.
И поэтому, хотелось бы заставить ADO как-то сформировать запрос на UpdateBatch() вида:
update v_MyView set MyField1 = 'MyText' where ID = 1.

В ADO есть решение проблемы, путем выставления свойства:
rs->GetProperties()->GetItem("Update Criteria")->Value = adCriteriaKey;
В этом случае, в условие подставляется только проверка на первичный ключ, т. е. то что мне нужно. Но!
Это св-во, почему-то, никак не хочет работать, когда рекордсет построен на основе выборки из view.
Работает только, если запрос на основе голых таблиц. Вероятно, для view ADO не может определить нужный первичный ключ.
Пытаюсь помочь, прописав свойство:
rs->GetProperties()->GetItem("Unique Table")->Value = "MyTable";
Не помогает!

Вопрос: Можно ли заставить это св-во работать с использованием view? Или, если нельзя, то что тут можно ещё придумать для решения проблемы?
Подставлять вместо view запрос из связанных таблиц не хотелось бы, ибо на триггерах столько функционала, что с переносом тот ещё геморрой предстоит.
22 янв 14, 13:22    [15451899]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с обновлением измененной записи  [new]
StarikNavy
Member

Откуда: Москва
Сообщений: 2414
ROLpogo,

создайте на сервере свою процедуру апдейта, и дергайте из АДО её
22 янв 14, 14:04    [15452119]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с обновлением измененной записи  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
StarikNavy
ROLpogo,

создайте на сервере свою процедуру апдейта, и дергайте из АДО её
Да можно и без процедуры сделать ещё один компонент ADO специально для апдейта по ID.
Текст запроса туда жёстко задавать.
22 янв 14, 14:08    [15452137]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с обновлением измененной записи  [new]
ROLpogo
Member

Откуда: Реутов
Сообщений: 219
iap,

В этом рекордсете записи не только изменяются, но и удаляются и добавляются. Пока не представляю, можно ли динамически, средствами ADO, сгенерить запросы под эти 3 случая?
22 янв 14, 15:27    [15452612]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с обновлением измененной записи  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
ROLpogo
iap,

В этом рекордсете записи не только изменяются, но и удаляются и добавляются. Пока не представляю, можно ли динамически, средствами ADO, сгенерить запросы под эти 3 случая?
Там же запрос - это текст.
Кто мешает этот текст формировать перед выполнением?
22 янв 14, 15:45    [15452724]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с обновлением измененной записи  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74930
ROLpogo,

Со стандартным ADO рекордсетом вы нормальной каши не сварите.
22 янв 14, 15:47    [15452737]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с обновлением измененной записи  [new]
ROLpogo
Member

Откуда: Реутов
Сообщений: 219
iap, не совсем понял.
Т.е. перед тем как запустить rs->UpdateBatch(adAffectAll) можно выдрать все тексты запросов, которые уйдут на сервер?
22 янв 14, 16:04    [15452824]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с обновлением измененной записи  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
ROLpogo
iap, не совсем понял.
Т.е. перед тем как запустить rs->UpdateBatch(adAffectAll) можно выдрать все тексты запросов, которые уйдут на сервер?
У Вас C++ Builder?
Я могу поделиться опытом в Delphi.
Существует, например, компонент ADOCommand. У него есть свойство CommandText.
Что мешает туда записывать запрос на UPDATE каждый раз перед выполнением?
Или параметры сделать и задавать их перед запуском.

Или ADOQuery.SQL.Text, если Вам этот компонент привычнее.

Слово "выдрать" я не понял в данном контексте.
До этого говорили про простой UPDATE по ID.

Чувствую, меня щас скушает pkarklin
Могу сказать, что много лет варю нормальную кашу!
22 янв 14, 16:37    [15453020]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с обновлением измененной записи  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74930
ROLpogo,

Найдите бесплатный\напишите свой\купите компонент доступа к данным, который позволяет иметь 4ре свойства:

1. Инструкция для получения набора данных;
2. Инструкция для добавления одной записи;
3. Инструкция для обновления одной записи;
4. Инструкция для удаления одной записи,

куда вписываются имена хп (запросы на T-SQL с параметрами, наконец). Этот компонент должен уметь получить и забуфферизировать на клиенте набор данных из любой валидной инструкции на T-SQL и не:

1. быть завязанным на возможность обновления источника;
2. генерить CRUD запросы самостоятельно.

и будет Вам счастье без говнокодинга. Время надо тратить на решение прикладных задач.
22 янв 14, 16:52    [15453114]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с обновлением измененной записи  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
pkarklin
ROLpogo,

Найдите бесплатный\напишите свой\купите компонент доступа к данным, который позволяет иметь 4ре свойства:

1. Инструкция для получения набора данных;
2. Инструкция для добавления одной записи;
3. Инструкция для обновления одной записи;
4. Инструкция для удаления одной записи,

куда вписываются имена хп (запросы на T-SQL с параметрами, наконец). Этот компонент должен уметь получить и забуфферизировать на клиенте набор данных из любой валидной инструкции на T-SQL и не:

1. быть завязанным на возможность обновления источника;
2. генерить CRUD запросы самостоятельно.

и будет Вам счастье без говнокодинга. Время надо тратить на решение прикладных задач.
Вот, кстати, я давно для этих самых целей использую Views из DevExpess Grid, не привязанные к БД.
Сам заполняю их, сам обновляю только нужную запись во View (а не весь Grid).

А ТС редактирует через вечно открытый DataSet...
И обновить может только всё целиком.
22 янв 14, 17:00    [15453169]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с обновлением измененной записи  [new]
ROLpogo
Member

Откуда: Реутов
Сообщений: 219
iap, у меня не Борланд, а MS Visual C++. Рекордсет на основе _RecordsetPtr. Пример c "update" привел, т.к. именно на нем возникает затык, когда хотя бы одно из полей было изменено после открытия рекордсета. Но даже если отбросить поддержку вставок и удаления, я не могу понять, каким образом можно заранее узнать тексты запросов, посылаемые серверу при выполнении команды UpdateBatch(), для того, чтоб их потом можно было распарсить и подменить своими вызовами. Если смотреть в профайлер, то там, при UpdateBatch(), на сервер уходит несколько простыней из update по нескольким полям (тех, что были отредактированы) с условием проверки по всем полям. И так для каждой отредактированной записи в таблице. Т.е. если мы в одной записи изменили поля MyField1 и MyField2, а в другой MyField 2 и MyField3 то на сервер уйдет 2 апдейта вида: update v_MyView set MyField1 = 'XXX', MyField2 = 123 where (перечисление всех полей) и update v_MyView set MyField2 = 456, MyField3 = 789 where (перечисление всех полей).
22 янв 14, 17:03    [15453189]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с обновлением измененной записи  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74930
iap
Сам заполняю их, сам обновляю только нужную запись во View (а не весь Grid).

И обновить может только всё целиком.


Что значит "весь грид"? Почему, только "все целиком"? Открыли набор (есть желание, даже коннект к бд можно закрыть) из 20 записей. 2 изменили, 2 добавили, 1 удалили. Все это происходит в локальном буфере на клиенте и на сервер уйдет 5 инструкций. И это всё без единой строчки кода.
22 янв 14, 17:06    [15453208]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с обновлением измененной записи  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74930
ROLpogo
у меня не Борланд, а MS Visual C++.


Вам следует задать вопрос в профильном разделе форума.
22 янв 14, 17:07    [15453215]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с обновлением измененной записи  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
ROLpogo,

я правильно понимаю, что данные отображаются в каком-то гриде?
Или в полях какой-нибудь формы?
Значит, Вам известны все значения полей, которые надо сохранить в таблице?
И ID записи, конечно, знаете, да?
Почему бы в таком случае не написать строку с корректным UPDATE самостоятельно?
И послать её на сервер?
22 янв 14, 17:09    [15453225]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить