uses Classes, Graphics, Controls, Forms, Dialogs, cfutils, Windows, StdCtrls, ComCtrls, ExtCtrls,DB,IBDatabase,IBquery,unMain, sysutils; var sl: TStringList; strDiffDay: string; q_db, q_db2, q_trig: TIBQuery; db_clean: TIBDatabase; trn, trn2: TIBTransaction; ar_trig: TStringList; i: integer; procedure Log(Text:string); var F : TextFile; FileName : String; dt:string; begin FileName := ExtractFilePath(Application.ExeName) + 'UpdateDBDateTime.log'; AssignFile(F, FileName); if FileExists(FileName) then Append(F) else Rewrite(F); dt:=DateToStr(Date); dt:=dt+' '+TimeToStr(Time); WriteLn(F, dt+': '+text); CloseFile(F); end; begin try //Определяем строку подключения к БД sl:=TStringList.Create; GetParamList(sl); //Проверка, есть ли монопольный доступ к БД DeleteFile(sl[2]+'~tmp'); RenameFile(sl[2], sl[2]+'~tmp'); if Not FileExists(sl[2]+'~tmp') then begin log('ОШИБКА: нет монопольного доступа к БД '+sl[1]+sl[2] + '. Отключите все программы, которое могут её использовать'); log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'); exit; end; //Делаем копию файла с БД log('------ Начало обновления всех дат в БД '+sl[1]+sl[2]+' ------'); CopyFile(sl[2]+'~tmp', sl[2]+'~', true); if FileExists(sl[2]+'~') then log('Копия БД выполнена в '+sl[1]+sl[2]+'~'); else begin log('Ошибка. Не удается выполнить копирование файла БД на '+sl[1]+' в каталог '+sl[2]+'~' + '. Возможно неверно указан файл БД'); exit; end; //Подключаемся к БД db_clean:= TIBDatabase.Create(nil); db_clean.Params.clear; db_clean.DatabaseName:=sl[1]+sl[2]+'~'; //'localhost:C:\DISTRIBS\Standart-N(dress)\base\ztrade.fdb' db_clean.Params.Add('user_name=SYSDBA'); db_clean.Params.Add('password=masterkey'); db_clean.Params.Add('sql_role_name='); db_clean.Params.Add('lc_ctype=WIN1251'); db_clean.AllowStreamedConnected:=True; db_clean.LoginPrompt:=False; db_clean.SQLDialect:=3; db_clean.Connected:=true; // log('Подключились к БД ' + sl[1]+sl[2]+'~'); trn:=TIBTransaction.create(nil); trn.DefaultDatabase:=db_clean; q_trig:=TIBQuery.create(nil); q_trig.UniDirectional:=true; q_trig.BufferChunks:=100; q_trig.Database:=db_clean; q_trig.Transaction:=trn; q_db:=TIBQuery.create(nil); q_db.UniDirectional:=true; q_db.BufferChunks:=100; q_db.Database:=db_clean; q_db.Transaction:=trn; q_db2:=TIBQuery.create(nil); q_db2.UniDirectional:=true; q_db2.BufferChunks:=100; q_db2.Database:=db_clean; q_db2.Transaction:=trn; if not trn.Active then trn.StartTransaction; else trn.Commit; //Определяем все активные триггеры и деактивируем их ar_trig:=TStringList.Create; q_trig.Active:=false; q_trig.SQL.text:='SELECT RDB$TRIGGER_NAME FROM RDB$TRIGGERS WHERE RDB$TRIGGER_INACTIVE = 0 AND RDB$TRIGGER_SOURCE IS NOT NULL'; //RDB$TRIGGER_NAME= ''ADDRS_BI'''; // q_trig.Active:=true; while not q_trig.Eof do begin q_db2.Active:=false; ar_trig.add(q_trig.FieldByName('RDB$TRIGGER_NAME').AsString); q_db2.SQL.text:='ALTER TRIGGER ' + q_trig.FieldByName('RDB$TRIGGER_NAME').AsString + ' INACTIVE'; q_db2.Active:=true; q_trig.Next; end; trn.Commit; log('ШАГ 1 из 3. Триггеры в БД ' + sl[1]+sl[2]+'~'+' отключены. Всего ' + inttostr(ar_trig.Count) + ' шт.'); if not trn.Active then trn.StartTransaction; else trn.Commit; //Определяем на сколько дней смещать в базе даты q_db.Active:=false; q_db.SQL.text:='SELECT CAST (DATEDIFF(DAY, (SELECT MAX(DOCDATE) FROM DOCS), DATEADD(DAY, -1, CURRENT_DATE)) AS VARCHAR(1024)) AS REZ FROM rdb$database'; q_db.Active:=true; strDiffDay:= q_db.FieldByName('REZ').AsString //Генерируем SQL запросы по всем полям с типом DATE / TIMESTAMP q_db.Active:=false; q_db.SQL.text:='SELECT F.RDB$RELATION_NAME, F.RDB$FIELD_NAME FROM RDB$RELATION_FIELDS AS F ' + 'INNER JOIN RDB$RELATIONS AS R ON R.RDB$RELATION_NAME = F.RDB$RELATION_NAME ' + 'INNER JOIN RDB$FIELDS AS FT ON F.RDB$FIELD_SOURCE = FT.RDB$FIELD_NAME ' + 'WHERE R.RDB$RELATION_TYPE = 0 AND ' + //'R.RDB$FORMAT = 1 AND ' + представляет собой счётчик количества изменений метаданных 'R.RDB$SYSTEM_FLAG = 0 AND ' + '(FT.RDB$FIELD_TYPE = 12 OR FT.RDB$FIELD_TYPE = 35) ' + //--12 DATE, 35 TIMESTAMP 'ORDER BY F.RDB$RELATION_NAME'; q_db.Active:=true; while not q_db.Eof do begin q_db2.Active:=false; q_db2.SQL.text:='UPDATE '+q_db.FieldByName('RDB$RELATION_NAME').AsString+' SET '+q_db.FieldByName('RDB$FIELD_NAME').AsString+'= DATEADD(DAY, '+strDiffDay+' , '+q_db.FieldByName('RDB$FIELD_NAME').AsString+') ORDER BY '+q_db.FieldByName('RDB$FIELD_NAME').AsString+' DESC;'; q_db2.Active:=true; q_db.Next; end; trn.Commit; log('ШАГ 2 из 3. Все даты успешно обновлены в БД ' + sl[1]+sl[2]+'~'); if not trn.Active then trn.StartTransaction; else trn.Commit; log('Активируем обратно все триггеры, которые были активны до операции'); //Активируем обратно все триггеры, которые были активны до операции for i := 0 to ar_trig.Count-1 do begin q_db2.Active:=false; q_db2.SQL.text:='ALTER TRIGGER ' + ar_trig[i] + ' ACTIVE'; q_db2.Active:=True; end; trn.Commit; log('ШАГ 3 из 3. Триггеры в БД ' + sl[1]+sl[2]+'~'+' включены'); db_clean.Connected:=False; //Отключаемся от БД RenameFile(sl[2]+'~', sl[2]); DeleteFile(sl[2]+'~tmp'); log('Работа программы по обновлению дат успешно завершена для БД '+ sl[1]+sl[2]); log('__________________________________________________________________________________________________________________________________'); Except //в случае ошибки откатываем файл с БД обратно trn.Rollback; db_clean.Connected:=False; //Отключаемся от БД RenameFile(sl[2]+'~tmp', sl[2]); DeleteFile(sl[2]+'~'); log('ОШИБКА! Даты не обновлены в БД '+ sl[1]+sl[2]); log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'); end; end;