Конференция "Базы" » Каскадное обновление связных таблиц Oracle+Delphi [D7]
 
  • Geo (11.06.11 16:32) [0]
    Я сам никогда не сталкивался с БД, с работой через ADO, новичек. с делфи все обстоит немного лучше.
    Проблема в следующем
    Код
     //проверка уникальности и не 0 и нашелся в базе и не равен текущему
    if  ((Login_Form.QPatient.Locate('id_patient',id_pat_copy,[loCaseInsensitive])) and (id_patient<>id_pat_copy))  then
      begin
        ShowMessage('Пациент с таким кодом уже существует');
        exit;
      end;

         begin
             if (id_patient=StrToInt(EIdPat.Text)) then
               begin

                 ind_copy:=true  //создать нового пациента;
               end
             else   id_patient:=StrToInt(EIdPat.Text);

             with Login_form.QPatient do
              begin
                 if ind_copy then
                 begin
                   Locate('id_patient',id_pat_copy,[loCaseInsensitive]);
                   Edit;
                 end
                 else  Append;

                 FieldValues['id_patient']:=id_patient;
                 FieldValues['id_plot']:=id_plot;
                 FieldValues['id_doctor']:=id_doctor;
                 FieldValues['id_policlinic']:=id_policlinic;
                 FieldValues['id_speciality']:=id_speciality;
                 FieldValues['id_street_reg']:=id_street_reg;
                 FieldValues['id_street_home']:=id_street_home;
                 FieldValues['id_ed_inst']:=id_ed_inst;
                 FieldValues['name']:=Pname;
                 FieldValues['surname']:=surname;
                 FieldValues['patronymic']:=patronymic;
                 FieldValues['DOB']:=DOB;
                 FieldValues['insurance_org']:=insurance_org;
                 FieldValues['insurance_num']:=insurance_num;
                 FieldValues['house_reg']:=house_reg;
                 FieldValues['house_home']:=house_home;
                 FieldValues['father']:=father;
                 FieldValues['mother']:=mother;
                 FieldValues['sisters']:=sisters;
                 FieldValues['brothers']:=brothers;
                 FieldValues['SNILS']:=SNILS;
                 if num_card <>'' then
                 FieldValues['num_card']:=num_card;
                 FieldValues['document_type']:=document_type;
                 FieldValues['invalidity']:=invalidity;
                 FieldValues['dipans_uch']:=dipans_uch;
                 Post;
               end;

                ////*******************************start******************************
                  //Diary-каскадное обновление
                 with Login_form.QPatDiary do
                     begin
                        Sql.Clear;
                        Sql.Add('Select * from diary_survey where id_patient='+IntToStr(id_pat_old));
                        Open;
                        if FieldValues['id_diary']<>null then
                            begin

                               First;
                               Edit;
                               while not EOF  do//Цикл обновления по всем дневникам пациента
                                 begin
                                     Edit;
                                     FieldValues['id_patient']:=id_patient;
                                     FieldValues['id_plot']:=id_plot;
                                     FieldValues['id_doctor']:=id_doctor;
                                     FieldValues['id_policlinic']:=id_policlinic;
                                     FieldValues['id_speciality']:=id_speciality;
                                     FieldValues['id_street_reg']:=id_street_reg;
                                     FieldValues['id_street_home']:=id_street_home;
                                     FieldValues['id_ed_inst']:=id_ed_inst;
                                     Post;
                                     Next;
                                  end;
                              end;
                     end;
         ///******************************end**********************************

                     // льготы
                     with Login_form.QBenefits do
                     begin
                        Sql.Clear;
                        Sql.Add('Select * from BENEFITS where id_patient='+IntToStr(id_pat_old));
                        Open;
                        if FieldValues['id_benefit']<>null then
                            begin

                               First;
                               Edit;
                               while not EOF  do//Цикл обновления по всем льготам пациента
                                 begin
                                     Edit;
                                     FieldValues['id_patient']:=id_patient;
                                     FieldValues['id_plot']:=id_plot;
                                     FieldValues['id_doctor']:=id_doctor;
                                     FieldValues['id_policlinic']:=id_policlinic;
                                     FieldValues['id_speciality']:=id_speciality;
                                     FieldValues['id_street_reg']:=id_street_reg;
                                     FieldValues['id_street_home']:=id_street_home;
                                     FieldValues['id_ed_inst']:=id_ed_inst;
                                     Post;
                                     Next;
                                  end;
                              end;
                          SQL.Clear;
                          SQL.Add('SELECT * FROM BENEFITS');
                     end;

                   with Login_form.QPatient do
                     begin
                     if not ind_copy then      //если создавалась копия
                         begin
                      //удалям старую запись
                           Locate('id_patient',id_pat_old,[loCaseInsensitive]);
                           Delete;
                          end;
                     end;
         end;



    На выделенном Post, если мы не меняем id_patient, но меняем id_plot срабатывает триггер
  • Geo (11.06.11 16:33) [1]
    DECLARE NUMROWS INTEGER;
    BEGIN
     /* ERwin Builtin Trigger */
     /* Patients  Diary_survey on parent update restrict */
     /* ERWIN_RELATION:CHECKSUM="000d657c", PARENT_OWNER="", PARENT_TABLE="Patients"
       CHILD_OWNER="", CHILD_TABLE="Diary_survey"
       P2C_VERB_PHRASE="", C2P_VERB_PHRASE="",
       FK_CONSTRAINT="R_10", FK_COLUMNS="id_patient""id_plot""id_doctor""id_policlinic""id_speciality""
                 id_street_reg""id_street_home""id_ed_inst" */
     IF
       /* %JoinPKPK(:%Old,:%New," <> "," OR ") */
       :old.id_patient <> :new.id_patient OR
       :old.id_plot <> :new.id_plot OR
       :old.id_doctor <> :new.id_doctor OR
       :old.id_policlinic <> :new.id_policlinic OR
       :old.id_speciality <> :new.id_speciality OR
       :old.id_street_reg <> :new.id_street_reg OR
       :old.id_street_home <> :new.id_street_home OR
       :old.id_ed_inst <> :new.id_ed_inst
     THEN
       SELECT count(*) INTO NUMROWS
         FROM Diary_survey
         WHERE
           /*  %JoinFKPK(Diary_survey,:%Old," = "," AND") */
           Diary_survey.id_patient = :old.id_patient AND
           Diary_survey.id_plot = :old.id_plot AND
           Diary_survey.id_doctor = :old.id_doctor AND
           Diary_survey.id_policlinic = :old.id_policlinic AND
           Diary_survey.id_speciality = :old.id_speciality AND
           Diary_survey.id_street_reg = :old.id_street_reg AND
           Diary_survey.id_street_home = :old.id_street_home AND
           Diary_survey.id_ed_inst = :old.id_ed_inst;
       IF (NUMROWS > 0)
       THEN
    /* ********************************MY COD************            */
     /* UPDATE Diary_survey SET Diary_survey.id_plot=:new.id_plot WHERE Diary_survey.id_patient=:new.id_patient;
    /* ********************************END OF MY COD************            */
        raise_application_error(
           -20005,
           'Cannot update Patients because Diary_survey exists.'
         );
       END IF;
     END IF;



    Тригер сгенерирован Erwin, схема в прикрепленном файле
    если я пишу то, что помечено как /* ********************************MY COD************ , то срабатывает другой триггер целостности Diary_survey.

    Как лучше поступить в данном случае, сорри за длинный пост, просто выложил, чтобы была видна полная картина

    Схема - http://www.imageup.ru/img55/dlya-sql678942.png
  • Loginov Dmitry © (11.06.11 21:26) [2]
    Курсовая горит? Или диплом?

    Судя по объемам выложенного кода, Вам лень со своими проблемами разбираться. Выделенного Post - не видно. Изображение png - нечитабельное. На что рассчитываете?
  • Geo (11.06.11 23:31) [3]
    Забыл закрыть тег
     
       FieldValues['document_type']:=document_type;
                FieldValues['invalidity']:=invalidity;
                FieldValues['dipans_uch']:=dipans_uch;
                Post;
              end;



    вот этот, самый первый Post

    http://www.imageup.ru/img158/1111679227.png

    В большем разрешении
  • Geo (11.06.11 23:32) [4]
    Да, вы правы, диплом.
  • Loginov Dmitry © (12.06.11 00:00) [5]
    Попробуйте сформулировать суть проблемы другими словами. В текущей постановке не понятно, что вам нужно.

    Смысл триггера не ясен. Каким образом пользователь может умудриться ввести 2 одинаковые записи, у которых одновременно совпадают 8 полей? Контроль подобных вещей обычно не триггерами реализуется, а ограничениями первичного ключа или уникального индекса.


    > /* ********************************MY COD************  
    >          */
    >  /* UPDATE Diary_survey SET Diary_survey.id_plot=:new.id_plot
    > WHERE Diary_survey.id_patient=:new.id_patient;
    > /* ********************************END OF MY COD************
    >            */


    Сомневаюсь, что данное решение приведет к желаемому результату. Этим вы все равно не избежите генерацию ошибки raise_application_error, а возникшая ошибка отменит ваш UPDATE.
  • Loginov Dmitry © (12.06.11 00:00) [6]

    > Да, вы правы, диплом.


    Защита должно быть завтра?
  • Geo (12.06.11 00:05) [7]
    Нет)
  • Geo (12.06.11 00:11) [8]
    Ошибка заключается в следующем.
    У текущего id_patient есть связные поля в diary_survey и по-этому тригер (если его отключить, то уже оракл) выдает ошибку, что изменить это поле нельзя.
    Тоже самое обстоит и с id_plot, т.к. это поле также есть в diary_survey.
    Как бы все это каскадно обновить?

    Есть бредовая идея - создать еще "нулевую стоку", значение в связной таблице с текущей строки помять на нулевую, переименовать, вернуть значения на место.

    Но по-моему это порнография...
  • Виталий Панасенко(дом) (12.06.11 00:43) [9]
    А что, у Оракла нету каскадного обновления на уровне БД? бред по моему
  • Geo (12.06.11 00:52) [10]
    Ну у той схемы, что создал Erwin-только предупреждения об ошибках. точнее ошибки с указанием таблиц.
  • Игорь Шевченко © (12.06.11 11:31) [11]

    > А что, у Оракла нету каскадного обновления на уровне БД?
    >  


    нету, есть только каскадное удаление
  • Виталий Панасенко (12.06.11 11:49) [12]

    > Игорь Шевченко ©   (12.06.11 11:31) [11]

    это стеб или внатуре нету? я просто с Ораклом как-то несталкивался(раза два-три и то на уровне выборки данных)
  • Geo (12.06.11 13:03) [13]
    В том то и дело, нету ON UPDATE CASCADE, вся задача его сэмулировать.
  • Loginov Dmitry © (12.06.11 17:52) [14]

    > В том то и дело, нету ON UPDATE CASCADE, вся задача его
    > сэмулировать.


    Необходимость в каскадном обновлении чаще всего свидетельствует о неудачной структуре БД. Зачем его эмулировать?
  • Geo (12.06.11 18:33) [15]
    Вот если на схему -   http://www.imageup.ru/img158/1111679227.png посмотреть, нормально, что ключи дублируются ErWinом дочерним таблицам (например в diary_survey есть id_plot), хотя с таблицей plot она не связана напрямую(только через Patients)
  • Geo (12.06.11 18:34) [16]
    *? - в смысле это было не утверждение, а вопрос
  • Игорь Шевченко © (12.06.11 22:35) [17]
    Виталий Панасенко   (12.06.11 11:49) [12]

    нету, так как незачем
  • Geo (13.06.11 00:35) [18]
    Если erwin так проектирует автоматически, возможно в этом есть доля здравого смысла? Никто не знает, можно ли в Ервин отключить дублирование по всем дочерним таблицам FK?
  • Виталий Панасенко(дом) (13.06.11 10:12) [19]

    >  Игорь Шевченко ©   (12.06.11 22:35) [17]

    Ну, это типа спор об искусственных и натуральных ключах..:-) Почему-то во многих СУБД ЭТО :-) присутствует. Видимо, не зря...
  • Игорь Шевченко © (13.06.11 20:54) [20]

    > Почему-то во многих СУБД ЭТО :-) присутствует. Видимо, не
    > зря...


    ну вот касательно оракла:

    "Primary keys are supposed to be imutable, never changing, constant.  It is an excessively
    bad practice to have to update them ever.  If there is a 0.00001% chance you will have to
    update a primary key -- then it is not a primary key, its a surrogate key and you need to
    find the true primary key (even if you have to make it up via a sequence) "

    http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:5773459616034
  • Anatoly Podgoretsky © (14.06.11 08:44) [21]
    > Игорь Шевченко  (13.06.2011 20:54:20)  [20]

    Оракл всегда стоял особняком.
 
Конференция "Базы" » Каскадное обновление связных таблиц Oracle+Delphi [D7]
Есть новые Нет новых   [134431   +10][b:0][p:0.007]