Конференция "Базы" » аудит в БД [D7]
 
  • Natalinrf (14.05.14 14:39) [0]
    Здравствуйте, уважаемые мастера Delphi. Прошу, не откажите в помощи..Существует некое рабочее место АРМ, например мастера, куда в табличной форме (DBGrid) выводятся данные по различным объектам (написано это АРМ на Delphi). В таблице мастер может данные редактировать, удалять, вносить новые строки заполняя их данными (при этом может сохранить введенные данные, а может и не сохранять). и вот требуется на этом рабочем месте дописать действия BeforeEdit, AfterInsert, чтобы и те данные которые были+новые+ фамилия того, кто изменения делал - записались в таблицу аудит. у меня скоро мозг взорвется.

    Код для того, чтобы старые данные переносились в другую таблицу до начала редактирования (BeforeEdit) , следующий:
    Код Delphi

    DataModule2.DataSet_material_audit.Close;
     DataModule2.DataSet_material_audit.DeleteVariables;
     DataModule2.DataSet_material_audit.SQL.Clear;
     DataModule2.DataSet_material_audit.SQL.Add('begin');
       DataModule2.DataSet_material_audit.SQL.Add('insert into develop.materials_audit(smelt_ident, number_processing, stage, material_kind, in_number,material_old, weight_old, event_time, material_new, weight_new, type_oper, familia) ');
       DataModule2.DataSet_material_audit.SQL.Add('values(:smI, :npr, :stg, ''1'', NVL((select max(in_number) from develop.materials_audit where smelt_ident=:smI), 0)+1,:mtrl_old,:wes_old, sysdate, null, null, ''2'', :fml);');
       DataModule2.DataSet_material_audit.SQL.Add('commit;');
     DataModule2.DataSet_material_audit.SQL.Add('end;');
     DataModule2.DataSet_material_audit.DeclareVariable('smI', otInteger);
     DataModule2.DataSet_material_audit.SetVariable('smI', Smelt.SmI);
     DataModule2.DataSet_material_audit.DeclareVariable('npr', otInteger);
     DataModule2.DataSet_material_audit.SetVariable('npr', 1);
     DataModule2.DataSet_material_audit.DeclareVariable('stg', otString);
     DataModule2.DataSet_material_audit.SetVariable('stg', Smelt.Stage);
     DataModule2.DataSet_material_audit.DeclareVariable('mtrl_old', otString);
     DataModule2.DataSet_material_audit.SetVariable('mtrl_old', DataModule2.DataSet_ferr.FieldByName('Additional_Name').AsString);
     DataModule2.DataSet_material_audit.DeclareVariable('wes_old', otInteger);
     DataModule2.DataSet_material_audit.SetVariable('wes_old', DataModule2.DataSet_ferr.FieldByName('AMOUNT').AsInteger);
     DataModule2.DataSet_material_audit.DeclareVariable('fml', otString);
     DataModule2.DataSet_material_audit.SetVariable('fml', Curr_user.Familia);
     DataModule2.DataSet_material_audit.Open;

    а как дальше сделать, что-то не соображу..может через динамический массив, где от типа действия (редактирование, удаление, добавление новой строки, сохранение) данные либо записываются в таблицу, либо затираются в памяти..как оформить не знаю..опыта еще мало..
  • [ВладОшин] © (15.05.14 09:50) [1]
    пора написать сверху на странице форума, Если вопрос по БД - указывайте СУБД
  • Inovet © (15.05.14 10:17) [2]
    > [1] [ВладОшин] ©   (15.05.14 09:50)
    > указывайте СУБД

    БД одна - TTable. Либо SQL сервер.

    > [0] Natalinrf   (14.05.14 14:39)

    Судя по контексту, в БД могут быть триггеры. В них и сделать.
  • [ВладОшин] © (15.05.14 10:42) [3]
    похоже на oracle
    но я совсем никак в фб. может это оно..
    все же, надо указавать субд

    И все же не триггер, а хранимку.
    1. триггер можно забыть учитывать потом
    2. Стимулирует табличный подход
  • Кщд (15.05.14 10:56) [4]
    >[ВладОшин] ©   (15.05.14 10:42) [3]
    sysdate, nvl - точно Oracle

    а автору, действительно, надо курить триггеры, чтобы не записывать(при этом через анонимный блок - зачем?) несуществующие данные в аудит
  • sniknik © (15.05.14 10:58) [5]
    а вообще смысл? переносить/синхронизировать данные во вторую таблицу если их же легко можно взять из первой ... ???
  • Natalinka © (15.05.14 12:29) [6]
    База данных Oracl.  Доступ осуществляется  по компоненту Direct Oracle Access 4.0.7.1..
  • Natalinka © (15.05.14 12:32) [7]
    Триггеры на базу не написать, так как доступ к базе закрыт(нет прав), можно писать только запросы к ней..
  • Кщд (15.05.14 12:45) [8]
    >Natalinka ©   (15.05.14 12:32) [7]
    1. кто создал таблицу аудита develop.materials_audit?
    2. что будет в in_number, если два пользователя одновременно выполнят insert?
    3. Зачем логировать то, что никогда не будет записано в базу?
  • Natalinka © (15.05.14 13:02) [9]
    Кщд   (15.05.14 12:45) [8]
    1. Таблицу создал руководитель,
    2. in_number  - это поле по порядку (в принципе оно не важно)
    3. так желает его величество руководитель..в общем-то тут еще с ним можно поспорить.
  • Кщд (15.05.14 13:10) [10]
    >Natalinka ©   (15.05.14 13:02) [9]
    1. доступ к схеме develop у вас есть?
    2. в данном случае, никаким "по порядку" и не пахнет, увы
    3. т.е. "руководитель" хочет, чтоб при попытке редактирования записи, её текущее состояние записывалось в лог? даже, если это редактирование НЕ БУДЕТ подтверждено(commit) в базе?
  • Natalinka © (15.05.14 13:15) [11]
    Кщд   (15.05.14 13:10) [10] 1.нет у меня еще ни какого доступа.
                                          3. именно так. он хочет видеть кто залазил в базу и какие изменения пытался внести.
  • [ВладОшин] © (15.05.14 13:32) [12]
    аля

     for i := 0 to DataSet.FieldCount - 1 do
     begin
       DataSetInsert.Parameters.Items[i].Value :=
          DataSet.Fields[0].OldValue;
       DataSetInsert.ExecSql;

       DataSetInsert.Parameters.Items[i].Value :=
          DataSet.Fields[0].NewValue;
       DataSetInsert.ExecSql;
     end;

    только в DOA по моему DataSetInsert.Params.Items[i].Value :=
  • [ВладОшин] © (15.05.14 13:44) [13]

    >  DataSetInsert.ExecSql;

    вынести за цикл Ж)
  • Кщд (15.05.14 14:16) [14]
    >Natalinka ©   (15.05.14 13:15) [11]
    >1.нет у меня еще ни какого доступа.
    если вставляете данные, значит, есть

    >3. именно так. он хочет видеть кто залазил в базу и какие изменения пытался внести.
    думаю, Вы неверно поняли руководителя
  • Natalinka © (15.05.14 14:34) [15]
    Кщд   (15.05.14 14:16) [14] >3. именно так. он хочет видеть кто залазил в базу и какие изменения пытался внести.
    думаю, Вы неверно поняли руководителя - в том-то и дело, что верно поняла...я просто не буду этот вариант прописывать..
    в общем вот, что у меня получилось
    вариант когда пользователь добавляет строку, вносит данные и сохраняет их, нажимая кнопку "Сохранить"
     
    объявление массива public
                                            Str_SQL: array of AnsiString;

    обработчики событий
              procedure TDataModule2.DataSet_ferrBeforeEdit(DataSet: TDataSet);
    begin
      try   // íà ñëó÷àé îøèáêè ïðîïèñûâàåì öèêë try...except
     DataModule2.DataSet_material_audit.Close;
     DataModule2.DataSet_material_audit.DeleteVariables;
     DataModule2.DataSet_material_audit.SQL.Clear;
     DataModule2.DataSet_material_audit.SQL.Add('begin');
       DataModule2.DataSet_material_audit.SQL.Add('insert into develop.materials_audit(smelt_ident, number_processing, stage, material_kind, in_number,material_old, weight_old, event_time, material_new, weight_new, type_oper, familia) ');
       DataModule2.DataSet_material_audit.SQL.Add('values(:smI, :npr, :stg, ''1'', NVL((select max(in_number) from develop.materials_audit where smelt_ident=:smI), 0)+1,:mtrl_old,:wes_old, sysdate, null, null, ''2'', :fml);');
       DataModule2.DataSet_material_audit.SQL.Add('commit;');
     DataModule2.DataSet_material_audit.SQL.Add('end;');
     DataModule2.DataSet_material_audit.DeclareVariable('smI', otInteger);
     DataModule2.DataSet_material_audit.SetVariable('smI', Smelt.SmI);
     DataModule2.DataSet_material_audit.DeclareVariable('npr', otInteger);
     DataModule2.DataSet_material_audit.SetVariable('npr', 1);
     DataModule2.DataSet_material_audit.DeclareVariable('stg', otString);
     DataModule2.DataSet_material_audit.SetVariable('stg', Smelt.Stage);
     DataModule2.DataSet_material_audit.DeclareVariable('mtrl_old', otString);
     DataModule2.DataSet_material_audit.SetVariable('mtrl_old', DataModule2.DataSet_ferr.FieldByName('Additional_Name').AsString);
     DataModule2.DataSet_material_audit.DeclareVariable('wes_old', otInteger);
     DataModule2.DataSet_material_audit.SetVariable('wes_old', DataModule2.DataSet_ferr.FieldByName('AMOUNT').AsInteger);
     DataModule2.DataSet_material_audit.DeclareVariable('fml', otString);
     DataModule2.DataSet_material_audit.SetVariable('fml', Curr_user.Familia);
     DataModule2.DataSet_material_audit.Open;
        except on E: Exception do begin
        ShowMessage('Ошибка :'+E.Message);
      end;
    end;
     ShowMessage('Все отработало');// потом это сообщение уберу

    end;

    procedure TDataModule2.DataSet_ferrAfterInsert(DataSet: TDataSet);
    var

    St: Integer; // строка

    begin
     DataModule2.DataSet_material_audit.Close;
     DataModule2.DataSet_material_audit.DeleteVariables;
     DataModule2.DataSet_material_audit.SQL.Clear;
     St:=length(Smelt.Str_SQL);
     Setlength(Smelt.Str_SQL,length(Smelt.Str_SQL)+1);
     Smelt.Str_SQL[St]:='insert into develop.materials_audit(smelt_ident, number_processing, stage, material_kind, in_number,material_old, weight_old, event_time, material_new, weight_new, type_oper, familia) ';
     St:=length(Smelt.Str_SQL);
     Setlength(Smelt.Str_SQL,length(Smelt.Str_SQL)+1);
     Smelt.Str_SQL[St]:='values('+IntToStr(Smelt.SmI)+',1, '''+Smelt.Stage+''', ''1'', NVL((select max(in_number) from develop.materials_audit where smelt_ident='+IntToStr(Smelt.SmI)+'), 0)+1, NULL, NULL, sysdate, '''+ DataSet_ferr.FieldByName('additional_name').AsString+''',  '+DataSet_ferr.FieldByName('amount').AsString+', ''0'', '+char(30)+Curr_user.Familia+char(30)+');';
          end;
         на кнопке "Сохранить " массив
    save_all_data(true);

    for i:=0 to length(Smelt.Str_SQL)-1  do begin
     DataModule2.DataSet_material_audit.SQl.ADD(Smelt.Str_SQL[i]);
    end;

    for i:=0 to length(Smelt.Str_SQL)-1  do begin
      Smelt.Str_SQL[i]:='';
    end;
    Setlength(Smelt.Str_SQL, 0);

    Smelt.my_search();
    N4Click(nil);
    Беда в том, что копируются данные всей таблицы...
  • Natalinka © (15.05.14 14:38) [16]
    как затереть данные, которые уже были записаны в таблицу, а пользователь решил не сохранять изменения?
  • Кщд (15.05.14 15:22) [17]
    >Natalinka ©   (15.05.14 14:38) [16]
    1. где затереть?
    2. зачем вы используете анонимный pl/sql-блок для записи данных?
    3. почему вы используете чудовищную и некорректную конструкцию: select max(in_number)...?
  • Дмитрий (15.05.14 16:16) [18]

    > как затереть данные, которые уже были записаны в таблицу,
    >  а пользователь решил не сохранять изменения?

    Их просто не нужно писать в лог до того, как пользователь подтвердит изменения.
    Вместо BeforePost обрабатывайте AfterPost
  • Natalinka © (15.05.14 20:30) [19]
    Кщд   (15.05.14 15:22) [17]
    2. зачем вы используете анонимный pl/sql-блок для записи данных?  - Что значит анонимный?
    3. почему вы используете чудовищную и некорректную конструкцию: select max(in_number)...? - а как нужно? у меня опыт равен нулю практически в базах данных
 
Конференция "Базы" » аудит в БД [D7]
Есть новые Нет новых   [118667   +44][b:0][p:0.001]