Работа со связаными таблицами
, Как лучше всего организовать сабж
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.217.20] |
|
|
ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi
Работа со связаными таблицами
, Как лучше всего организовать сабж
|
Сообщ.
#1
,
|
|
|
|
Я делаю прогу с БД. Структуру БД делал в Access. Для доступа к БД использую ADO. Там есть связаные таблицы. К примеру их 3. Я их связывал программно. Сделал три отдельных цепочки ADODataSet->ADODataSource->DBGrid. Что бы реализовать связь я отображаю одну таблицу и обрабатываю событие onDataChange для DataSource связаного с этим гридом. В этом обработчике опререляю выбранную запись и для этой записи делаю SQL запрос "SELECT" что-бы отобразить соответствующие записи из второй таблицы. Такое же событие я обрабатываю и во второй таблице. Вот такая связь ручками
. Нет ли в Дельфи какого нииь автоматизированного способа? Ведь мне придется и удалять элементы из двух первых таблиц и в связи с этим удалять связаные с ними элементы в третьей. Мне идти по моему ручному пути? Или есть что-то изящнее? Добавлено Ну а пока я иду по своему ручному пути. И реальные ошибки выскакивают. В таблице № 2 я при удалении элемента удаляю соответствующие элементы из Таблицы № 3 . Делаю я это так: ![]() ![]() if(MessageBox(0,'Удалять связаные элементы?' ,'Удаление',MB_YESNO or MB_ICONQUESTION)=IDYES) then begin ADODataSetLL.Active:=false; ADODataSetLL.CommandText:='DELETE * FROM TableLineLow WHERE Name="'+sTSnum+ '" AND NumKSO='+IntToStr(iCurBoxLV)+' AND NumKS='+IntToStr(iCurKS); ShowMessage(ADODataSetLL.CommandText); ADODataSetLL.Open; end; Но выскакивае ошибка исполнения: Цитата Текущий проводник не поддерживает возврат нескольких наборов записей в результате одной операции. Не пойму какие еще несколько наборов?! Я просто хочу удалить записи. Что я неправильно делаю? |
|
Сообщ.
#2
,
|
|
|
|
Для исполнение команды DELETE лучше использовать:
ADODataSetLL.ExecSQL; Удалять из связанных таблиц, лично я так делаю, нужно ручками, а вот связь делается следующим образом: Пусть в базе есть две таблицы (AdoTable1, DataSource1, ADOTable2, DataSource2). Нужно первую связать со второй, причем первая главная. У второй таблици даблклик на свойство MasterFields, там выбираешь в первом списке служебное поле второй таблицы для свящи с первой, во втором списке выбираешь поле в первом таблице, от которого зависит, что будет видно во второй и жмешь Add. Потом еще нужно поменять свойство MasterSource у второй таблицы, выбрав в нем первый сурс. |
|
Сообщ.
#3
,
|
|
|
|
отображение данных в подчиненном датасорсе можно сделать так, как сказал бигмак
а удаление я бы реализовал в самой базе акцесс, выставив там свойство "Каскадное удаление" у связи между таблицами. |
|
Сообщ.
#4
,
|
|
|
|
А связь ведь делается программно, в Access'е только сами таблицы. Или я что-то не так понял?
|
|
Сообщ.
#5
,
|
|
|
|
Цитата DDX @ выставив там свойство "Каскадное удаление" у связи между таблицами. Цитата SexGenius @ Но выскакивае ошибка исполнения: Цитата Текущий проводник не поддерживает возврат нескольких наборов записей в результате одной операции. Кажеться копать надо в эту сторону. |
|
Сообщ.
#6
,
|
|
|
|
Цитата Кажеться копать надо в эту сторону. То есть? Как раз с этим сообщением все ясно: нужно не открывать,а исполнять запрос. |
|
Сообщ.
#7
,
|
|
|
|
Цитата BigMaK @ нужно не открывать,а исполнять запрос Полу правда, посмотри исходник. Тогда сообщение было типа ![]() ![]() Ошибка создания дескриптора курсора или Error creating cursor handle |
|
Сообщ.
#8
,
|
|
|
|
Цитата BigMaK @ А связь ведь делается программно, в Access'е только сами таблицы. Или я что-то не так понял? см. первый пост Цитата Структуру БД делал в Access |
|
Сообщ.
#9
,
|
|
|
|
Возможно я немножко запутал вас своей неправильной формулировкой. Связь таблиц в Ассесе я не делал. В нем я сделал лишь сами таблицы и не связывал их. Делал связь программно. Сейчас я понимаю что мне повезло - именно программно мне и надо делать связь, т.к. у программы будет иная логика по удалению записей. Связаные записи будут удаляться по согласию пользователя. Если пользователь ответит "нет", то в записях будут просто меняться кое какие поля (тоесть они будут связываться с другими объектами). Однако приятно что связь можно было реализовать в самом Ассесе. Это действительно будет работать? Кто-то уже делал подобное?
Добавлено Цитата BigMaK, 01.08.2005, 20:51:54, 792457 Для исполнение команды DELETE лучше использовать: ADODataSetLL.ExecSQL; Спасибо за совет. Правда в TADODataSet я не нашел метода ExecSQL, но зато я нашел его в TADOQuery. Удаление у меня получилось Вот может в связи со всем этим кто подскажет в нете лин где по русски будет описано назначение кажлого из компонентов по работе с БД. TQuery ? TDataSet, TDataSource, TDataTable и д.р. Очень хочется по русски про это прочитать. Ато на инглише долго разбираться в хелпе. В хелп я лезу только когда сильно припекло, а тут просто надо ликбез пройти. |
|
Сообщ.
#10
,
|
|
|
|
|
Сообщ.
#11
,
|
|
|
|
Цитата Однако приятно что связь можно было реализовать в самом Ассесе. Это действительно будет работать? Кто-то уже делал подобное? я делал, действительно будет работать. только свою логику удаления связанных записей уже не реализуешь, по-моему. |
|
Сообщ.
#12
,
|
|
|
|
Я УСё понял. Спасибо всем! я счиатю вопрос решен.
|
|
Сообщ.
#13
,
|
|
|
|
Цитата DDX @ я делал, действительно будет работать. только свою логику удаления связанных записей уже не реализуешь, по-моему. Тут такая проблема. В одной части моей проги реализовывать свою логику удаления неразумно. И вот в этой части я решил связать таблицы в Ассесе. Ну вот почитал хелп, начал делать как там написано и ничего не получается. Есть таблица - Шкаф, и есть несколько таблиц Аппарат1, Аппарат2, Аппарат3 ... АппаратN. Во всех таблицах есть поле НомерШкафа. Я хочу сделать так 1. Чтобы при изменении НомераШкафа в таблице Шкаф автоматически менялось этоже поле в таблицах Аппаратов. 2. При удалении записи из таблицы Шкаф удалялись соответстующие записи в Аппаратах. Читал я этот тугой Аксессовский хелп. Делал так : Жму кнопку "Схема данных" и указываю нужные таблицы. Из таблицы Шкаф перетягиваю поле НомерШкафа на такое же поле в Таблице одного из аппаратов. Ставлю Птицу "Обеспечение условия целостности данных" и птицу "Каскадное обновление связанных полей " жму Ok и получаю фигу в виде ошибки "Не обнаружен уникальный индекс для адресуемого поля главной таблицы". Жму справку и получаю Цитата Обнаружен повторяющийся индекс в адресуемом поле главной таблицы. (Ошибка 3609) При создании связи между таблицами адресуемое поле главной таблицы должно иметь уникальный индекс. Более подробное описание см. в разделах справки для объекта Index и свойства Primary. И что то нифига я не пойму как же заставить это работать. Почему не работает? Добавлено Поле НомераШкафа индексированое во всех таблицах. |
|
Сообщ.
#14
,
|
|
|
|
Тебе нужен Primary Key на таблицу шкафы и там не должно быть два одинаковых номера шкафа.
Цитата SexGenius @ Поле НомераШкафа индексированое во всех таблицах. В главной таблице он должен быть еще и уникальный. |
|
Сообщ.
#15
,
|
|
|
|
Цитата Bas, 29.08.2005, 12:34:25, 839968 и там не должно быть два одинаковых номера шкафа. А как же сделать чтобы работало с повторяющимися номерами шкафа в таблице Шкафы ? У меня в таблице Шкафы они будут повторяться, так как там еще есть поле Здание. И в Аппаратах есть поле Здание. Тоесть номера шкафов могут повторяться и помера зданий тоже. Но не может быть только записей с одинаковыми ка номером шкафа так и здания ? |
|
Сообщ.
#16
,
|
|
|
|
Цитата SexGenius @ Но не может быть только записей с одинаковыми ка номером шкафа так и здания Создай Primary Key по двум полям |
|
Сообщ.
#17
,
|
|
|
|
Цитата SexGenius @ А как же сделать чтобы работало с повторяющимися номерами шкафа в таблице Шкафы ? Явно, надо почитать чтото о 4-х типах нормализованных таблиц. |
|
Сообщ.
#18
,
|
|
|
|
Цитата SexGenius @ Есть таблица - Шкаф, и есть несколько таблиц Аппарат1, Аппарат2, Аппарат3 ... АппаратN. Во всех таблицах есть поле НомерШкафа Цитата SexGenius @ У меня в таблице Шкафы они будут повторяться, так как там еще есть поле Здание. И в Аппаратах есть поле Здание. Bas, похоже надо более грамотно спроектировать сами таблицы... |
|
Сообщ.
#20
,
|
|
|
|
Хорошо, раз так то как, по вашему, будет
Цитата ? более грамотно спроектировать сами таблицы... В упрощенном варианте описываемые объекты выглядят так. Есть Здания , их около 300. В каждом здании может быть произвольно количество шкафов (от одного до 30 к примеру). Каждый шкаф содержит разное количество Аппаратов разных типов. Это надо укатать в БД. Я сделал первую таблицу "Здания". В ней есть поле "Номер здания" и "Адрес здания". Но в моей проге мне надо отобразить для каждого здания количество и инвентарный номер шкафа. Для этого я создаю вторую таблицу и в которой есть поля "Номер здания", "номер шкафа в здании" и "инвентарный номер". Но в каждом шкафе есть аппараты. Аппаратов произвольное количество от 1 до 10. Аппараты бывают разных видов (разные устройства) . Поэтому я создаю еще ряд таблиц для каждого вида аапарата, в каждой из которых есть поля "Номер здания", "номер шкафа в здании" и ряд специфичных для этого вида устройства параметров. Как же мне иначе сделать структуру БД, что она была Цитата ? более грамотно спроектирована |
|
Сообщ.
#22
,
|
|
|
|
Одна байда этот самый код должен формироваться по какому-то алгоритму из того же номера здания и номера шкафа в здании. Какой смысл вообще вводить этот самы й код ? Только лишь затем чтобы связываемое поле было уникально ? А по другому никак ?
Мои таблицы нельзя заставить работать связано ? Добавлено И еще, если всё-таки создания поля с кодом не избежать, то как его создать в Ассесе ? Да так чтобы код сам формировался . Иначе его придется в Дельфи формировать .... И все тогда теряет смысл.... |
|
Сообщ.
#23
,
|
|
|
|
Цитата SexGenius, 29.08.2005, 17:59:52, 840369 А по другому никак ? Мои таблицы нельзя заставить работать связано ? Я связал свои таблицы по двум полям, как писал Coala . Работает !!!! Цитата SexGenius, 29.08.2005, 17:59:52, 840369 Одна байда этот самый код должен формироваться по какому-то алгоритму из того же номера здания и номера шкафа в здании. Какой смысл вообще вводить этот самы й код ? Вот этот вопрос остается в силе! Жду ответа. Цитата SexGenius, 29.08.2005, 17:59:52, 840369 И еще, если всё-таки создания поля с кодом не избежать, то как его создать в Ассесе ? Ну , вобщем-то и этот тоже. |
|
Сообщ.
#24
,
|
|
|
|
Цитата SexGenius @ Этот код может формироваться каким угодно образом и отношения к данным, которыми ты манипулируешь, не должен иметь совсем. Единственное его предназначение - связывать между собой значения в разных таблицах. Это нужно для того, чтобы избежать лишней работы вот здесь:Одна байда этот самый код должен формироваться по какому-то алгоритму из того же номера здания и номера шкафа в здании. Какой смысл вообще вводить этот самы й код ? Цитата То есть при изменении названия шкафа тебе ничего больше не придется менять, т.к. этот шкаф по-прежнему будет соответствовать тем же записям в таблице аппаратов что и раньше.1. Чтобы при изменении НомераШкафа в таблице Шкаф автоматически менялось этоже поле в таблицах Аппаратов. Цитата SexGenius @ Задай этому полю тип "Счетчик" (в англ. версии кажется "Autoincrement") и его значение будет автоматически увеличиваться при добавлении новых записей в таблицу. И еще, если всё-таки создания поля с кодом не избежать, то как его создать в Ассесе ? Добавлено P.S. Oбщепринято, что во всех таблицах роль такого кода выполняет поле с именем id |
|
Сообщ.
#25
,
|
|
|
|
Братцы, а если спроектировать базу так:
ЗДАНИЯ Z_ID primary key адрес и все остальное ШКАФЫ S_ID primary key Z_ID foreign key referenced ЗДАНИЯ и все остальное АППАРАТЫ A_ID primary key S_ID foreign key referenced ШКАФЫ и все остальное ну и расписать SQLи на выборку и изменение данных (в том числе и каскадные) |
|
Сообщ.
#26
,
|
|
|
|
Вариант Коалы мне больше нравится - без дополнительной таблицы
|
|
Сообщ.
#27
,
|
|
|
|
Надо сделать так, чтобы первичный ключ был уникальный и связь шкаф-аппараты была "одна-ко-многим".
Цитата SexGenius @ А как же сделать чтобы работало с повторяющимися номерами шкафа в таблице Шкафы ? У меня в таблице Шкафы они будут повторяться, так как там еще есть поле Здание. И в Аппаратах есть поле Здание. Т.е. первичным ключом "Шкафов" будет: <номер шкафа> и <здание>. Вместе эта группа будет однозначно ижентияифировать конкретный шкаф (и только один шкаф). И внешний ключ (ключ связи) для таблицы "аппаратов" должен содержат первичный ключ таблицы "шкафы". |
|
Сообщ.
#28
,
|
|
|
|
Цитата RuSA @ У меня в таблице Шкафы они будут повторяться, так как там еще есть поле Здание т.е. ситуация такая что-ли: шкаф здание 1 1 2 1 3 1 1 2 2 2 3 2 ....... |
|
Сообщ.
#29
,
|
|
|
|
Да , ситуация такая, но я теперь переделал свои таблицы так , как советовал ты и J. Bravo . Спасибо всем
Работает |
|
Сообщ.
#30
,
|
|
|
|
Цитата Coala @ ШКАФЫ S_ID NOT NULL Z_ID foreign key referenced ЗДАНИЯ primary key (Z_ID, S_ID) |