gifts2017

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

Опубликовал Maxim k (maxis33) в раздел Администрирование - Чистка базы

Иногда во время перевода 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

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
delete_all_duble!!! no select.sql
.sql 3,41Kb
25.05.10
53
.sql 3,41Kb 53 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Епрст (Ёпрст) 25.05.10 12:07
Всё это конечно хорошо, но что мешает сделать ТиИ в дбф базе перед выгрузкой ?

Или проверить прямым запросом дубли в самой дбф базе ?
2. Епрст (Ёпрст) 25.05.10 12:08
+1 да, и где гарантия того, что в скуль база уже целиком загрузилась ?
3. Maxim k (maxis33) 25.05.10 13:00
В sql сначала загружаются все данные, а затем уже начинают создаваться индексы, во время которых уже и вылетает программа. Следовательно данные на этот момент уже загружены.

На большой базе ТиИ идет долго, к тому же как написано выше "Для решения проблемы можно, конечно, предварительно удалить дубли сразу в DBF базе перед выгрузкой, но как правило о наличии проблемы узнаем уже когда база выгружена и даже наполовину загружена в SQL, так что предлагаемая методика получается быстрее."
4. Епрст (Ёпрст) 25.05.10 13:09
(3) забыл еще про операции и проводки
5. Maxim k (maxis33) 25.05.10 14:36
(4) Нужды небыло;) вот для операций и проводок еще можно добавить

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
...Показать Скрыть
6. Епрст (Ёпрст) 25.05.10 14:54
(5) ну, не у всех же оперучет один.. в бухне очень часто проводки "двоятся"

а в справочниках, при определенных условиях, так вообще интерактивными действиями можно создать элемент с дублирующимся id !
7. Епрст (Ёпрст) 25.05.10 14:54
ну и бух итоги еще придётся пересчитать..
8. Епрст (Ёпрст) 25.05.10 14:55
+8 да..и еще пересчет итогов по колонкам..
9. leov-001 (leov-001) 25.05.10 15:42
Вам принцип работы показали, остальное сами доделывайте для своих нужд.
С DBF отлично работает 1sqlite
http://www.1cpp.ru/forum/YaBB.pl?num=1192855975/0#0
http://www.1cpp.ru/forum/YaBB.pl?num=1214205575/0
10. Епрст (Ёпрст) 25.05.10 16:08
(9) Это к кому адресовано сообщение ?
Если мне, то скрипты такие ужо и так давно есть у меня..
А для дбф конкретно в этом случае 1sqlite вообще не катит - не умеет он апдейтить и удалять, только селект, если что.

11. Аркадий Кучер (Abadonna) 25.05.10 21:06
(9)
Вам принцип работы показали, остальное сами доделывайте для своих нужд.

Это ты Ёпрст-у что ли написал? :D
Хоть бы в профайл заглянул до того, как...
12. Виктор Виктор (virs) 26.05.10 09:38
А, что Ёпрст-у уже и написать ничего не моги...?
13. Maxim k (maxis33) 26.05.10 12:15
(8) Пересчет служебных данных потом нужен, это да..
14. Андрей (anc2002) 13.01.12 18:09
однако, на одной ненормальной базе и данный скрипт не помог, пришлось вырезать из базы проблемные типы документов и записывать их в базу sql через выгрузку загрузку
15. Виктор Сергиенко (nextkmv) 11.03.14 12:17
Спасибо большое! За день до дня X dbf версия выдала ошибка -120 и приказала переходить на sql(размер dbf файла 1,99 Гб). При загрузке базы в SQL выкинул ошибку о не уникальности индекса, а ведь день X уже пришел. Искать виновника в dbf версии не было времени и эта обработка нас спасла.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа