Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2002.01.21;
Скачать: [xml.tar.bz2];

Вниз

Delete from master-detail via stored procedure   Найти похожие ветки 

 
Гоша   (2001-12-13 19:00) [0]

Просто беда...
BDE, TDataBase, TQueries, TStoredProcedure, CachedUpdates...
2 (или более) TQuery связаны как master-detail (связаны "вручную" - не через DataSource, ибо, как выяснилось, так не прокатит! - господи, как я люблю BORLAND и его детище!)
Ладно, навтыкал обработчиков, чтобы переопредлять параметры для detail и переоткрывать его (их), когда надо мне, а не ему.
Теперь встал вопрос об удалении всей грозди. Слепил sp на сервере, к-рая по PK master-записи удаляет все веточки и ее саму(опять-же, а ну попробуй сделать это на клиенте: пиши циклы WHILE NOT EOF ! Я уже выражал свое мнение относительно "удобства" DELPHI для приложений БД - ну нету у нее "встроенного SQL", чтобы работать с наборами данных по-нормальному!!).
А теперь вопрос: процедура отрабатывает, на сервере записи удаляются, мне приходит result, что, типа, все OK, а на любое телодвижение с набором данных после этого получаю сообщение:"Connection is in use by another statement" !
Офигев от этого, делаю совершенно простенький пример (ничего лишнего на форме, только 2 Query, master-detail - правда, по-простому - через DataSource) и аналогичную sp.
Запускаю - работает ! И ничем мой connection не занимает.
Ну, думаю, блин... И добавляю пару строчек после StoredProc1.ExecProc:
Query1.Delete; //чтобы визуально удалить запись в моем наборе
Query1.CommitUpdates; //очистить кэш
И получаю на команду Delete ответ: сбой при обращении к странице памяти в модуле SQLMSS32.DLL !
И тут я шизею...
М.б. кто-нибудь подскажет, какой учебник тут читать надо ?


 
Mick   (2001-12-13 19:03) [1]

Учебник по принципам построения клиент-серверных приложений


 
Гоша   (2001-12-13 19:05) [2]

>Mick: Ну ты сказал !


 
drpass   (2001-12-13 23:07) [3]

Я, правда, не с MS SQL работаю, но... нафиг делать поддержку целостности данных в клиентском приложении? Почему бы не настроить ее на самой базе данных? Ведь есть в SQL Server триггеры или какой-то их аналог, там, скажеи, автоматический запуск хранимой процедуры при удалении записей


 
Гоша   (2001-12-14 10:13) [4]

>drpass: Я, конечно, понимаю, что с триггерами сподручнее, чем самому.
Но представьте ситуацию, когда изменять структуру БД невозможно (добавлять новые объекты типа sp или view можно, а менять существующие нельзя), так ведь бывает, правда ?
Но дело не в этом! Меня бесит непонимание того, что происходит!
Сначала я никак не мог понять, почему не работает master-detail через DataSource (во всех пособиях мило объясняется именно этот вариант и нигде ни слова о том, что так не пройдет с CachedUpdates). Спасибо, добрые люди подтвердили, что, действительно придется связывать самому, ручками через код.
Теперь вдруг этот несчастный connection, к-рый вдруг оказывается занят каким-то another statement после выполнения sp. У меня крепнет чувство, что чего-то глубоко здесь недопонимаю... А м.б. все проще гораздо?
Подскажите хоть, в каком направлении искать, откуда ноги растут у этой дряни.


 
Tonie   (2001-12-14 13:45) [5]

> drpass ©
MSSQL до 2000 версии имеет триггеры без деления на Befor After, не поддерживает каскадного удаления, а проверка referential integrity происходит раньше удаления записи, так что приходится действительно пользоваться легкими извратами.
> Гоша © собственно проблем со стандартным Master - Detail особенно не припоминаю, при подробном описании проблемы и знаниии версии MSSQL было бы проще помочь


 
Гоша   (2001-12-14 13:55) [6]

>Tonie: Дружище, помоги!
А проблему, собственно я уже описал... (MS SQL 2000 но не в этом дело, дело в том, что я не понимаю, как работает в данном случае DELPHI и что делать...)


 
Kapusto   (2001-12-14 14:06) [7]

Ну если MSSQL2000, тогда рыть в сторону referential constraints, on delete cascade


 
Гоша   (2001-12-14 14:47) [8]

Блин, да устал уже говорить, что не могу МЕНЯТЬ структуру существующих объектов в БД ! Это не мои объекты.
Ди и не хочу ! Хорошо, переформулирую вопрос: Если RI не обеспечивается средствами сервера, то что же выходит - в DELPHI нельзя ее обеспечить програмным способом ?! Причем, по большому счету - какая разница, идет ли CASCADE DELETE через, напр., триггер на master-таблице, или через вызов sp?
Делается-то ведь одно и то же (и делается на сервере хорошо)! Проблема-то совсем в другом (8-:O)!!!


 
Tonie   (2001-12-14 15:06) [9]

>Гоша ©
Немного кода не помешало бы, и какие проблемы со стандартной реализацией Master-Detail


 
Гоша   (2001-12-14 15:50) [10]

>Tonie: Ты, правда, хочешь помочь?
Тогда вопрос: приходилось ли тебе реализовывать master-detail через TQuery и CachedUpdates? (заметь, ни слова про тип сервера). Если да, то готов поспорить о том, что вряд-ли ты это сделашь стандартным способом...
Если нет, то попробуй...


 
Tonie   (2001-12-14 18:28) [11]

> Гоша ©
Собственно опять же непонятно:
1. Как организованна связь между запросами
2. Как идет запись в DB, UpdateSQL ??, отдельные запросы ....
3. Какие поля используются для связи, автоинкрементные или задаются с клиента??
4. Код обработки транзакции ...
....
Кстати не обязательно sp писать, можно в запросе на удаление записи в Master DataSet предварительно удалить соответствующие записи в Detail DataSet, прекрасно функционирует


 
Гоша   (2001-12-17 10:50) [12]

>Tonie:
Ну давай по кусочкам:
1. Связь между запросами прописана кодом на (напр.) событие AfterScroll mast-qry:
- det-qry.Close;
- det-qry.ParamByName("field_i").AsInteger:=mast-qry.FieldByName("field_i").Value;
- det-qry.Open;
2. Запись в БД идет через UpdateSQL (Database.ApplyUpdates([mast-qry,det-qry]);) кроме операции удаления (она выполняется посредством StoredProc.ExecProc;)
3. Про поля для связи см. п.1
4. "Код обработки транзакции ..." ? - не понял, что ты имеешь в виду.
Если запись ИЗМЕНЕНИЙ через ApplyUpdates, то полагаюсь на механизм DataBase.ApplyUpdates, если же запись УДАЛЕНИЯ, то транзакция объявляется в stored proc на сервере.
PS: насчет необязательности писания sp: IMHO код будет гораздо кучерявее:
1) удалить все записи в det-qry (а их неск-ко) и master-запись
2) а потом мудрить с кодом для транзакции подтверждения всех этих изменений в БД (последовательно вызывать ApplyUpdates для всех det-qry, и, если все пройдет, то делать ApplyUpdates для mast-qry)
3) обрабатывая все неожиданности... Стоит оно того ?
Что-нибудь еще ?


 
Гоша   (2001-12-17 13:54) [13]

Кажись, чуть-чуть разобрался... (Оно меня с ума сведет !)

Фича с "Connection is in use by another statement" исчезла после того, как я убрал StoredProc1.Prepare (и соотв. Unprepare) из событий DataBase1.AfterConnect (соотв. BeforeDisconnect).

Вот ведь блин ! Не надо, стало быть, читать всяческие умные советы в Help"ах насчет того, что-де, лучше это сделать самому, если-де предполагается исп-ть компонент неск-ко раз.

Почему-то в случае предварительного и явного (одноразового) Prepare выполнение StoredProc транслируется на сервер так (из SQL Monitor):

48 12:07:27 SQL Stmt: MSSQL - Close
49 12:07:27 SQL Prepare: MSSQL - a_del_zoom_loc_sp :1, :2,
50 12:07:27 SQL Data In: MSSQL - Param = 1, Name = , Type = fldINT32, Precision = 0, Scale = 0, Data = 26100
51 12:07:27 SQL Data In: MSSQL - Param = 2, Name = , Type = fldINT32, Precision = 0, Scale = 0, Data = 600
52 12:07:27 SQL Execute: MSSQL - a_del_zoom_loc_sp :1, :2,
и все !

А вот если не забивать себе голову ерундой и положиться на Борланда (дедушка умный! он сам сообразит насчет и Prepare и Unprepare), то тогда будет так:

48 11:52:20 SQL Prepare: MSSQL - a_del_zoom_loc_sp :1, :2,
49 11:52:20 SQL Data In: MSSQL - Param = 1, Name = , Type = fldINT32, Precision = 0, Scale = 0, Data = 26100
50 11:52:20 SQL Data In: MSSQL - Param = 2, Name = , Type = fldINT32, Precision = 0, Scale = 0, Data = 600
51 11:52:20 SQL Execute: MSSQL - a_del_zoom_loc_sp :1, :2,
52 11:52:20 SQL Stmt: MSSQL - Close //Вот этого и не хватало!
53 11:52:20 SQL Stmt: MSSQL - Close //Вот Connection и оставался in use!

Объясните, кто понимает, чего старичок (я) не сообразил.

А вот на закуску:
Я (наивный!) полагал, что если запись на сервере благополучно удалена, то визульно удалить ее в моем наборе не просто, а очень просто:

Query.Delete; //запишем в кэш как удаленную
Query.CommitUpdates; //очистим кэш

А вот фиг вам!!!
Знаете, что транслируется на сервер по команде CommitUpdates ?
Попытка выполнить команду DELETE...FROM...WHERE...!
Я не могу это откомментировать...

PS:Конечно, понимаю, что верный способ отобразить изменения через Close, Open. Но опять же, зачем огород городить...


 
Tonie   (2001-12-17 14:40) [14]

1. Если непременно нужно через sp стирать и UpdateSql использовать то тогда лучше вызов sp сделать прямо из UpdateSql : exec YourSp :Param1 :Param2, тогда на уровне клиента вообще про нее неизвестно и все с помощью UpdateSql проходит.

2. Я в испуге набросал попробовал сам (может я чего забыл) короче две таблицы : MAST - DTL, связь ID - ID_MAST, два запроса связаны через
DataSource, для мастера UpdateSql.DeteteSql =

Delete from Dtl where MAST_ID = :OLD_ID
Delete from Mast where ID = :OLD_ID


Запись в базу


begin
try
db1.StartTransaction;

quMaster.ApplyUpdates;
quDetail.ApplyUpdates;

db1.Commit;
except
db1.Rollback;
raise
end;

quMaster.CommitUpdates;
quDetail.CommitUpdates;
end


P.S. это конечно модель, но работает, т.е. в чем основная проблема я так и не понял


 
Гоша   (2001-12-17 17:32) [15]

>Tonie:
Что касается твоего MAST-DTL и записи в базу: это классический пример, с к-рого собственно и начался весь геморрой. Ты действительно убеждался в том, что он работает в случае:

а) добавления master-записи, detail-записей а потом их всех скидывания в БД через твой фрагмент кода.

б) и даже проще: в уже имеющейся (считанной из БД) комбинации внести изменения в detail-набор а потом попытаться что-то отредактировать в master-записи (просто в локальном (кэшируемом) варианте, без передачи изменений на сервер) ?

Я столкнулся с тем, что это невозможно: при изменении статуса master-записи (dsBrowse->dsEdit или DsInsert->dsBrowse) detail-набор переоткрывается автоматически и все твои незафиксированные изменения в нем херит !!!

Буду удивлен, услышав, что у тебя ничего подобного не происходит (мне неск-ко человек подтвердили, что так и должно быть...)

Но повторюсь: Собственно проблему с вызовом sp я решил (вернее, случайно наткнулся на способ избежать ошибки) и остались (риторические?) вопросы касательно поведения BDE.
Ну не вижу я в нем здравого смысла :(


 
Mick   (2001-12-17 17:47) [16]

Если честно, то использование на клиенте конструкций Master_Detail при работе с SQL сервером это все же не совсем клиент-серверный подход (хоть и работает)
Это и многое другое сводит на нет все преимущества двузвенки.


 
Гоша   (2001-12-17 18:06) [17]

>Mick: Вот-те раз! А почему же master-detail это не наш метод для client-server ? Потому что много записей из master-таблицы выбирает ? А если всего несколько ? А если всего одну ?
Я даже больше скажу: мне удивительно такое индифферентное отношение практически всех здесь присутствующих к теме. Такое ощущение, что никто форм на master-detail не пишет. А по мне так не может быть сколько-нибудь значащего приложения для БД без таких форм...
Вот.


 
Mick   (2001-12-17 18:20) [18]

Понимаете, Гоша, я не говорил что это неработоспособно.
Но когда что-то пишется и тестируется на одной машине и на сотне другой записей и одним пользователем это одно.
А когда приложение начинает работать в реальном мире (нормальное количество пользователей, нормальные объемы данных, есть каналы 128 кбит) то это совсем другое.


 
Гоша   (2001-12-17 18:26) [19]

>Mick:Понимаете, Mick, я тоже не говорил, что "это работоспособно а все остальное нет". Я всего лишь удивился Вашим словам:

"использование на клиенте конструкций Master_Detail при работе с SQL сервером это все же не совсем клиент-серверный подход".

Не могли бы Вы эту фразу расшифровать ?


 
Mick   (2001-12-17 18:33) [20]

Пожалуйста, но это конечно только мое мнение:
Если пользователь на форме последовательно жмет кнопки Up/Down не выходя за пределы уже зафетченных с сервера записей, а на сервер продолжают улетать запросы, для отображения Detail секции это плохо.


 
Гоша   (2001-12-17 18:38) [21]

>Mick: Ну же, еще одной фразы не хватает: а как же лучше ?
PS: А если выходит "за пределы уже зафетченных с сервера записей" (напр., выбирает с сервера новую-одну! master-запись) - то тогда хорошо, тогда можно использовать master-detail ?!


 
Mick   (2001-12-17 18:47) [22]

Смысл на самом деле простой, и ясен ребенку:
Не тянуть с сервера ничего без необходимости.
Хочет юзер посмотреть записи связанные с основной - открыть ему отдельную форму. Как вариант - сделать объединение на сервере этих наборов (это уже НАМНОГО лучше простого M/D).


 
Гоша   (2001-12-17 18:57) [23]

>Mick: Я все никак не возьму в толк: "сделать объединение на сервере этих наборов (это уже НАМНОГО лучше простого M/D)" - да чем лучше-то? Какое-такое объединение ты сделаешь для счета-фактуры со строками, для человека с детьми (несть числа примерам).
"Хочет юзер посмотреть записи связанные с основной - открыть ему отдельную форму" - пользователи "тащатся" от такого интерфейса.
Все, не могу больше. Что, в самом деле все считают, что формы master-detail не нужны ? (Я имею в виду формы для разумного ввода/редактирования, ест-но)


 
Mick   (2001-12-17 19:08) [24]

Видимо мы про разное говорим, но все же.
* Чем лучше объединение на сервере? *
тем, что на клиента detail-записи будут фетчиться ОДИН раз. Это не самое оптимальное решение объединить одну мастер - запись со всеми детайл - записями(как красиво это отобразить на клиенте - это другой вопрос).
Клиент-сервер был придуман для того, чтобы минимизировать трафик между хостом, на котором лежат данные и клиентом, а не для того, чтобы пользователи тащились от интерфейсов.
Именно это я и имел ввиду, говоря что Master/Detail - не клиент серверный подход.
Про пользовательский интерфейс речи не было и нет.


 
Гоша   (2001-12-18 10:35) [25]

>Mick: Ладно, давай завязывать. Я так понимаю, что каждый остался при своем мнении, и пусть каждый реализует клиентский интерфейс и способ обмена данными с сервером как ему (и клиентам) удобнее (и разумнее). Это, в конце концов, тема для абстактной дискуссии.
А по простому вопросу, к-рый я привел выше, нет никаких комментариев? Я имею в виду поведение оператора Query.CommitUpdates для визуального удаления записи в наборе данных на клиенте после того, как она была удалена на сервере.
Да и Tonie что-то замолчал...



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2002.01.21;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.003 c
7-66367
Sergiu
2001-10-04 10:15
2002.01.21
Вызов диалоговых окон из .rc файлов


1-66259
Quest
2001-12-29 09:44
2002.01.21
Пропадает каретка в режиме редактирования ячейки TStringGrid


4-66415
Константин
2001-11-17 21:50
2002.01.21
По(ту)сторонние звуки


3-66211
Байкер
2001-12-17 13:44
2002.01.21
Печать DBGrid


3-66207
borisich
2001-12-16 18:51
2002.01.21
Какой лучше формат СУБД использовать для локальных





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский