На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Обязательно указание:
1) типа базы данных (Paradox/Oracle/Interbase и т.п.)
2) способа доступа к базе данных (ODBC/ADO/DAO/BDE и т.п.)
Например: Paradox/BDE, MS Access/ADO

Наиболее часто задаваемые вопросы:
Базы даных для начинающих. Первые шаги. Понятие о BDE.
Переход на клиент-сервер и начала ADO
Приёмы работы с BLOB (OLE/Memo) полями
Запросы и параметры или как избавиться от многих проблем. Проблемы с датами в запросах.
Нужели мне нужно устанавливать BDE? (или почему не работает программа на другом компьютере)
Модераторы: Bas, Rouse_
  
> Работа со связаными таблицами , Как лучше всего организовать сабж
    Я делаю прогу с БД. Структуру БД делал в Access. Для доступа к БД использую ADO. Там есть связаные таблицы. К примеру их 3. Я их связывал программно. Сделал три отдельных цепочки ADODataSet->ADODataSource->DBGrid. Что бы реализовать связь я отображаю одну таблицу и обрабатываю событие onDataChange для DataSource связаного с этим гридом. В этом обработчике опререляю выбранную запись и для этой записи делаю SQL запрос "SELECT" что-бы отобразить соответствующие записи из второй таблицы. Такое же событие я обрабатываю и во второй таблице. Вот такая связь ручками :) . Нет ли в Дельфи какого нииь автоматизированного способа? Ведь мне придется и удалять элементы из двух первых таблиц и в связи с этим удалять связаные с ними элементы в третьей. Мне идти по моему ручному пути? Или есть что-то изящнее?

    Добавлено
    Ну а пока я иду по своему ручному пути. И реальные ошибки выскакивают. В таблице № 2 я при удалении элемента удаляю соответствующие элементы из Таблицы № 3 . Делаю я это так:

    ExpandedWrap disabled
      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;

    Но выскакивае ошибка исполнения:
    Цитата
    Текущий проводник не поддерживает возврат нескольких наборов записей в результате одной операции.

    Не пойму какие еще несколько наборов?! Я просто хочу удалить записи. Что я неправильно делаю?
      Для исполнение команды DELETE лучше использовать:
      ADODataSetLL.ExecSQL;

      Удалять из связанных таблиц, лично я так делаю, нужно ручками, а вот связь делается следующим образом:
      Пусть в базе есть две таблицы (AdoTable1, DataSource1, ADOTable2, DataSource2). Нужно первую связать со второй, причем первая главная. У второй таблици даблклик на свойство MasterFields, там выбираешь в первом списке служебное поле второй таблицы для свящи с первой, во втором списке выбираешь поле в первом таблице, от которого зависит, что будет видно во второй и жмешь Add. Потом еще нужно поменять свойство MasterSource у второй таблицы, выбрав в нем первый сурс.
        отображение данных в подчиненном датасорсе можно сделать так, как сказал бигмак
        а удаление я бы реализовал в самой базе акцесс, выставив там свойство "Каскадное удаление" у связи между таблицами.
          А связь ведь делается программно, в Access'е только сами таблицы. Или я что-то не так понял?
            Цитата DDX @
            выставив там свойство "Каскадное удаление" у связи между таблицами.


            Цитата SexGenius @
            Но выскакивае ошибка исполнения: Цитата
            Текущий проводник не поддерживает возврат нескольких наборов записей в результате одной операции.

            Кажеться копать надо в эту сторону.
              Цитата
              Кажеться копать надо в эту сторону.

              То есть? Как раз с этим сообщением все ясно: нужно не открывать,а исполнять запрос.
                Цитата BigMaK @
                нужно не открывать,а исполнять запрос

                Полу правда, посмотри исходник.
                Тогда сообщение было типа
                ExpandedWrap disabled
                  Ошибка создания дескриптора курсора
                  или
                  Error creating cursor handle
                  Цитата BigMaK @
                  А связь ведь делается программно, в Access'е только сами таблицы. Или я что-то не так понял?

                  см. первый пост

                  Цитата
                  Структуру БД делал в Access
                    Возможно я немножко запутал вас своей неправильной формулировкой. Связь таблиц в Ассесе я не делал. В нем я сделал лишь сами таблицы и не связывал их. Делал связь программно. Сейчас я понимаю что мне повезло - именно программно мне и надо делать связь, т.к. у программы будет иная логика по удалению записей. Связаные записи будут удаляться по согласию пользователя. Если пользователь ответит "нет", то в записях будут просто меняться кое какие поля (тоесть они будут связываться с другими объектами). Однако приятно что связь можно было реализовать в самом Ассесе. Это действительно будет работать? Кто-то уже делал подобное?

                    Добавлено
                    Цитата BigMaK, 01.08.2005, 20:51:54, 792457
                    Для исполнение команды DELETE лучше использовать:
                    ADODataSetLL.ExecSQL;

                    Спасибо за совет. Правда в TADODataSet я не нашел метода ExecSQL, но зато я нашел его в TADOQuery. Удаление у меня получилось :)
                    Вот может в связи со всем этим кто подскажет в нете лин где по русски будет описано назначение кажлого из компонентов по работе с БД. TQuery ? TDataSet, TDataSource, TDataTable и д.р. Очень хочется по русски про это прочитать. Ато на инглише долго разбираться в хелпе. В хелп я лезу только когда сильно припекло, а тут просто надо ликбез пройти.
                        Цитата
                        Однако приятно что связь можно было реализовать в самом Ассесе. Это действительно будет работать? Кто-то уже делал подобное?


                        я делал, действительно будет работать. только свою логику удаления связанных записей уже не реализуешь, по-моему.
                        Сообщение отредактировано: DDX -
                          Я УСё понял. Спасибо всем! я счиатю вопрос решен.
                            Цитата DDX @
                            я делал, действительно будет работать. только свою логику удаления связанных записей уже не реализуешь, по-моему.

                            Тут такая проблема. В одной части моей проги реализовывать свою логику удаления неразумно. И вот в этой части я решил связать таблицы в Ассесе. Ну вот почитал хелп, начал делать как там написано и ничего не получается. Есть таблица - Шкаф, и есть несколько таблиц Аппарат1, Аппарат2, Аппарат3 ... АппаратN. Во всех таблицах есть поле НомерШкафа. Я хочу сделать так
                            1. Чтобы при изменении НомераШкафа в таблице Шкаф автоматически менялось этоже поле в таблицах Аппаратов.
                            2. При удалении записи из таблицы Шкаф удалялись соответстующие записи в Аппаратах.

                            Читал я этот тугой Аксессовский хелп. Делал так :
                            Жму кнопку "Схема данных" и указываю нужные таблицы. Из таблицы Шкаф перетягиваю поле НомерШкафа на такое же поле в Таблице одного из аппаратов. Ставлю Птицу "Обеспечение условия целостности данных" и птицу "Каскадное обновление связанных полей " жму Ok и получаю фигу в виде ошибки "Не обнаружен уникальный индекс для адресуемого поля главной таблицы". Жму справку и получаю
                            Цитата
                            Обнаружен повторяющийся индекс в адресуемом поле главной таблицы. (Ошибка 3609)
                            При создании связи между таблицами адресуемое поле главной таблицы должно иметь уникальный индекс. Более подробное описание см. в разделах справки для объекта Index и свойства Primary.

                            И что то нифига я не пойму как же заставить это работать. Почему не работает?

                            Добавлено
                            Поле НомераШкафа индексированое во всех таблицах.
                              Тебе нужен Primary Key на таблицу шкафы и там не должно быть два одинаковых номера шкафа.
                              Цитата SexGenius @
                              Поле НомераШкафа индексированое во всех таблицах.

                              В главной таблице он должен быть еще и уникальный.
                                Цитата Bas, 29.08.2005, 12:34:25, 839968
                                и там не должно быть два одинаковых номера шкафа.

                                А как же сделать чтобы работало с повторяющимися номерами шкафа в таблице Шкафы ? У меня в таблице Шкафы они будут повторяться, так как там еще есть поле Здание. И в Аппаратах есть поле Здание.
                                Тоесть номера шкафов могут повторяться и помера зданий тоже. Но не может быть только записей с одинаковыми ка номером шкафа так и здания ?
                                  Цитата SexGenius @
                                  Но не может быть только записей с одинаковыми ка номером шкафа так и здания

                                  Создай Primary Key по двум полям
                                    Цитата SexGenius @
                                    А как же сделать чтобы работало с повторяющимися номерами шкафа в таблице Шкафы ?

                                    Явно, надо почитать чтото о 4-х типах нормализованных таблиц.
                                      Цитата SexGenius @
                                      Есть таблица - Шкаф, и есть несколько таблиц Аппарат1, Аппарат2, Аппарат3 ... АппаратN. Во всех таблицах есть поле НомерШкафа

                                      Цитата SexGenius @
                                      У меня в таблице Шкафы они будут повторяться, так как там еще есть поле Здание. И в Аппаратах есть поле Здание.

                                      Bas, похоже надо более грамотно спроектировать сами таблицы... :huh:
                                          Хорошо, раз так то как, по вашему, будет
                                          Цитата
                                          более грамотно спроектировать сами таблицы...
                                          ?
                                          В упрощенном варианте описываемые объекты выглядят так.
                                          Есть Здания , их около 300. В каждом здании может быть произвольно количество шкафов (от одного до 30 к примеру).
                                          Каждый шкаф содержит разное количество Аппаратов разных типов.
                                          Это надо укатать в БД.

                                          Я сделал первую таблицу "Здания". В ней есть поле "Номер здания" и "Адрес здания".
                                          Но в моей проге мне надо отобразить для каждого здания количество и инвентарный номер шкафа.
                                          Для этого я создаю вторую таблицу и в которой есть поля "Номер здания", "номер шкафа в здании" и "инвентарный номер".
                                          Но в каждом шкафе есть аппараты. Аппаратов произвольное количество от 1 до 10. Аппараты бывают разных видов (разные устройства) .
                                          Поэтому я создаю еще ряд таблиц для каждого вида аапарата, в каждой из которых есть поля "Номер здания", "номер шкафа в здании" и ряд специфичных для этого вида устройства параметров.

                                          Как же мне иначе сделать структуру БД, что она была
                                          Цитата
                                          более грамотно спроектирована
                                          ?
                                            Примерно так
                                            Прикреплённый файлПрикреплённый файл_____.jpg (12.96 Кбайт, скачиваний: 312)
                                              Одна байда этот самый код должен формироваться по какому-то алгоритму из того же номера здания и номера шкафа в здании. Какой смысл вообще вводить этот самы й код ? Только лишь затем чтобы связываемое поле было уникально ? А по другому никак ?
                                              Мои таблицы нельзя заставить работать связано ?

                                              Добавлено
                                              И еще, если всё-таки создания поля с кодом не избежать, то как его создать в Ассесе ? Да так чтобы код сам формировался . Иначе его придется в Дельфи формировать .... И все тогда теряет смысл....
                                                Цитата 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
                                                И еще, если всё-таки создания поля с кодом не избежать, то как его создать в Ассесе ?


                                                Ну , вобщем-то и этот тоже.
                                                  Цитата SexGenius @
                                                  Одна байда этот самый код должен формироваться по какому-то алгоритму из того же номера здания и номера шкафа в здании. Какой смысл вообще вводить этот самы й код ?
                                                  Этот код может формироваться каким угодно образом и отношения к данным, которыми ты манипулируешь, не должен иметь совсем. Единственное его предназначение - связывать между собой значения в разных таблицах. Это нужно для того, чтобы избежать лишней работы вот здесь:
                                                  Цитата
                                                  1. Чтобы при изменении НомераШкафа в таблице Шкаф автоматически менялось этоже поле в таблицах Аппаратов.
                                                  То есть при изменении названия шкафа тебе ничего больше не придется менять, т.к. этот шкаф по-прежнему будет соответствовать тем же записям в таблице аппаратов что и раньше.
                                                  Цитата SexGenius @
                                                  И еще, если всё-таки создания поля с кодом не избежать, то как его создать в Ассесе ?
                                                  Задай этому полю тип "Счетчик" (в англ. версии кажется "Autoincrement") и его значение будет автоматически увеличиваться при добавлении новых записей в таблицу.

                                                  Добавлено
                                                  P.S. Oбщепринято, что во всех таблицах роль такого кода выполняет поле с именем id
                                                    Братцы, а если спроектировать базу так:

                                                    ЗДАНИЯ
                                                    Z_ID primary key
                                                    адрес
                                                    и все остальное

                                                    ШКАФЫ
                                                    S_ID primary key
                                                    Z_ID foreign key referenced ЗДАНИЯ
                                                    и все остальное

                                                    АППАРАТЫ
                                                    A_ID primary key
                                                    S_ID foreign key referenced ШКАФЫ
                                                    и все остальное

                                                    ну и расписать SQLи на выборку и изменение данных (в том числе и каскадные) :(
                                                      Вариант Коалы мне больше нравится - без дополнительной таблицы
                                                        Надо сделать так, чтобы первичный ключ был уникальный и связь шкаф-аппараты была "одна-ко-многим".

                                                        Цитата SexGenius @
                                                        А как же сделать чтобы работало с повторяющимися номерами шкафа в таблице Шкафы ? У меня в таблице Шкафы они будут повторяться, так как там еще есть поле Здание. И в Аппаратах есть поле Здание.

                                                        Т.е. первичным ключом "Шкафов" будет: <номер шкафа> и <здание>. Вместе эта группа будет однозначно ижентияифировать конкретный шкаф (и только один шкаф).

                                                        И внешний ключ (ключ связи) для таблицы "аппаратов" должен содержат первичный ключ таблицы "шкафы".
                                                          Цитата RuSA @
                                                          У меня в таблице Шкафы они будут повторяться, так как там еще есть поле Здание

                                                          т.е. ситуация такая что-ли:
                                                          шкаф здание
                                                          1 1
                                                          2 1
                                                          3 1
                                                          1 2
                                                          2 2
                                                          3 2
                                                          .......
                                                            Да , ситуация такая, но я теперь переделал свои таблицы так , как советовал ты и J. Bravo . Спасибо всем ;) Работает
                                                              Цитата Coala @
                                                              ШКАФЫ
                                                              S_ID NOT NULL
                                                              Z_ID foreign key referenced ЗДАНИЯ


                                                              primary key (Z_ID, S_ID)
                                                              1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                                              0 пользователей:


                                                              Рейтинг@Mail.ru
                                                              [ Script execution time: 0.1119 ]   [ 15 queries used ]   [ Generated: 10.07.26, 15:13 GMT ]