Решение проблем с неуникальными записями при переводе 1С 7.7 на SQL


Иногда во время перевода DBF базы на SQL возникает ошибка связанная с наличием в таблицах нескольких записей с одинаковым идентификатором DOCID или ID.  Загрузка вылетает с ошибкой, так как SQL сервер не может создать уникальный индекс. Приложенный скрипт помогает бороться с этой проблемой.

Такая ситуация возникает когда по какой-то причине(сбитые индексы, например) в DBF базе создаются идентичные записи в таблицах. Пока база в DBF - этого не заметно и работать не мешает, но в SQL такая база не пролезает.

Предлагаемая методика такова:

1. Запускаем стандартно загрузку данных.

2. После вылетания загрузки с ошибкой открываем Enterprise Manager и запускаем приложенный скрипт. Скрипт удалит дубли строк в журналах, документах, справочниках, регистрах.

3. После выполнения скрипта запускаем программу монопольно - 1С закончит создание индексов и запустится. Далее следует самостоятельно перерассчитать итоги либо встроенными средствами 1С либо,  обработкой "ПересчетИтоговРегистров.ert"  (от: Ермоленко В.В.).

4. Радуемся что не пришлось делать всякого рода длительные тестирования и исправления в базе DBF.

Все, база готова!

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

 

Сам скрипт:

 

go
exec('delete from  _1SJOURN  where row_id <  (Select max(row_id) from _1SJOURN as t1   where _1SJOURN.iddoc = t1.iddoc);')
go
  SET NOCOUNT on
  DECLARE @DBName char(30)
  DECLARE @coun int
  DECLARE SysCur CURSOR FOR SELECT name  FROM    sysobjects WHERE     (xtype = 'u') AND (name LIKE 'dt%')
  OPEN SysCur
  FETCH NEXT FROM SysCur INTO @DBName
  WHILE @@FETCH_STATUS=0 BEGIN
    if @DBName <>'dtproperties                  '
    begin   
    exec ('alter table '+@DBName+' add id int identity(1,1);  ')
    exec ('delete from '+@DBName+' where id < (Select max(id) from '+@DBName+' as t1   where '+@DBName+'.iddoc = t1.iddoc and '+@DBName+'.lineno_ = t1.lineno_); ')
    set @coun=@@ROWCOUNT
    exec ('alter table '+@DBName+' drop column id; ')
         PRINT 'Base ' +@DBName+'  '+CAST(@coun AS CHAR(4)) +' records deleted'
    end
     FETCH NEXT FROM SysCur INTO @DBName
  END
  CLOSE SysCur
  DEALLOCATE SysCur
go
  SET NOCOUNT on
  DECLARE @DBName char(30)
  DECLARE @coun int
  DECLARE SysCur CURSOR FOR SELECT name  FROM    sysobjects WHERE     (xtype = 'u') AND (name LIKE 'dh%')
  OPEN SysCur
  FETCH NEXT FROM SysCur INTO @DBName
  WHILE @@FETCH_STATUS=0 BEGIN
    if @DBName <>'dtproperties                  '
    begin   
    exec ('alter table '+@DBName+' add id int identity(1,1);  ')
    exec ('delete from '+@DBName+' where id < (Select max(id) from '+@DBName+' as t1   where '+@DBName+'.iddoc = t1.iddoc); ')
    set @coun=@@ROWCOUNT
    exec ('alter table '+@DBName+' drop column id; ')
         PRINT 'Base ' +@DBName+'  '+CAST(@coun AS CHAR(4)) +' records deleted'
    end
     FETCH NEXT FROM SysCur INTO @DBName
  END
  CLOSE SysCur
  DEALLOCATE SysCur
go

  SET NOCOUNT on
  DECLARE @DBName char(30)
  DECLARE @coun int
  DECLARE SysCur CURSOR FOR SELECT name  FROM    sysobjects WHERE     (xtype = 'u') AND (name LIKE 'ra%')
  OPEN SysCur
  FETCH NEXT FROM SysCur INTO @DBName
  WHILE @@FETCH_STATUS=0 BEGIN
    exec ('alter table '+@DBName+' add id int identity(1,1);  ')
    exec ('delete from '+@DBName+' where id < (Select max(id) from '+@DBName+' as t1   where '+@DBName+'.iddoc = t1.iddoc and '+@DBName+'.actno = t1.actno); ')
    set @coun=@@ROWCOUNT
    exec ('alter table '+@DBName+' drop column id; ')
     PRINT 'Base ' +@DBName+'  '+CAST(@coun AS CHAR(4)) +' records deleted'
     FETCH NEXT FROM SysCur INTO @DBName
  END
  CLOSE SysCur
  DEALLOCATE SysCur
go

  SET NOCOUNT on
  DECLARE @DBName char(30)
  DECLARE @coun int
  DECLARE SysCur CURSOR FOR SELECT name  FROM    sysobjects WHERE     (xtype = 'u') AND (name LIKE 'sc%')
  OPEN SysCur
  FETCH NEXT FROM SysCur INTO @DBName
  WHILE @@FETCH_STATUS=0 BEGIN
    exec('delete from ' +@DBName+'  where row_id <  (Select max(row_id) from ' +@DBName+' as t1   where ' +@DBName+'.id = t1.id);')
    set @coun=@@ROWCOUNT
         PRINT 'Base ' +@DBName+'  '+CAST(@coun AS CHAR(4)) +' records deleted'
     FETCH NEXT FROM SysCur INTO @DBName
  END
  CLOSE SysCur
  DEALLOCATE SysCur

go


delete from _1SENTRY where row_id < (Select max(row_id) from _1SENTRY as t1 where _1SENTRY.docid = t1.docid and _1SENTRY.number = t1.number);
PRINT 'Base _1SENTRY '+CAST(@@ROWCOUNT AS CHAR(4)) +' records deleted'
go


delete from _1Soper where row_id < (Select max(row_id) from _1Soper as t1 where _1Soper.docid = t1.docid)
PRINT 'Base _1Soper '+CAST(@@ROWCOUNT AS CHAR(4)) +' records deleted'
go

Файлы обработки:

-