Добавлено: Пн Окт 22, 2012 2:54 pm Заголовок сообщения: Преобразование базы данных из DAO в SQL
Добрый день!
На днях предстоит преобразовать базу данных формата 7.0 DAO в формат 7.40 SQL
Может кто даст пару добрых советов.
Например, что лучше, переносить в совершенно чистую базу и накатывать решение потом.
Тут вопрос, захочет ли решение устанавливаться, оно и так уже стоит.
Или взять чистую базу с установленным решением и туда перенести данные.
Тут вопрос, как подружатся существующие данные решения с данными самой базы.
Если в решении есть привязка к ИД или если есть неявные связи вроде Op.Params("Long1") = Op2.ID, то только тупым переносом данных с сохранением ИДшников.
Занимался таким года 3 назад в последний раз, алгоритм примерно такой:
1. Создаем пустую сиквельную базу
2. Накатываем структуру
3. Переносим все специфичные хранимки и (если есть) добавляем пользовательские поля/таблицы
4. Перегоняем данные в каждой таблице с предварительным отключением идентификаторов (делается по-таблично, т.к. отключить можно только для 1 таблицы одновременно). Подробностей уже не помню, если скрипт сохранился - брошу сюда.
Всего вермени заняло полу-вручную часа 2-3, не считая написания скриптов, в процессе коего изучил много интересного :)
Из подводных камней - структура некоторых таблиц немного отличается (подробностей, опять-таки не помню), допиливал руками, добавляя нужные колонки (и дефолтные значения) в исходную базу.
set @db_from = 'ForImport4'
set @db_to = 'GarantSystem'
--set @tbl_name = 'AG_BANKS'
-- подготовительные работы с исходной базой
print 'подготовительные работы с исходной базой'
set @sql = 'alter table ' + @db_from + '.dbo.SYS_LOG add FLAGS1 int null'
exec(@sql)
set @sql = 'alter table ' + @db_from + '.dbo.SYS_LOG add SYS_ACTION nchar(1) null'
exec(@sql)
set @sql = 'update ' + @db_from + '.dbo.SYS_LOG set SYS_ACTION = ACTION'
exec(@sql)
set @sql = 'alter table ' + @db_from + '.dbo.SYS_LOG drop column ACTION'
exec(@sql)
set @sql = 'alter table ' + @db_from + '.dbo.SYS_LOG alter column SYS_ACTION nchar(1) not null'
exec(@sql)
set @sql = 'alter table ' + @db_from + '.dbo.SYS_LOG drop column UID'
exec(@sql)
set @sql = 'alter table ' + @db_from + '.dbo.SYS_LOG add UID smallint null'
exec(@sql)
set @sql = 'update ' + @db_from + '.dbo.SYS_LOG set UID = ' + cast(user_id('_Admin') as varchar)
exec(@sql)
set @sql = 'update ' + @db_from + '.dbo.JOURNAL set J_QTY = 0 where J_QTY is null'
exec(@sql)
set @sql = 'update ' + @db_from + '.dbo.JOURNAL set JF_QTY = 0 where JF_QTY is null'
exec(@sql)
set @sql = 'delete from ' + @db_from + '.dbo.JRN_TAX'
exec(@sql)
set @sql = 'update ' + @db_from + '.dbo.MENU_ACTIONS set MA_NAME = left(MA_NAME,50)'
exec(@sql)
set @sql = 'update ' + @db_from + '.dbo.MENU_ACTIONS set MA_FILE = left(MA_FILE,50)'
exec(@sql)
-- подготовительные работы с новой базой
print 'подготовительные работы с новой базой'
set @sql = 'alter table ' + @db_to + '.dbo.DOCUMENTS alter column DOC_PS1 nvarchar(255) null'
exec(@sql)
set @sql = 'alter table ' + @db_to + '.dbo.DOCUMENTS alter column DOC_PS2 nvarchar(255) null'
exec(@sql)
set @sql = 'alter table ' + @db_to + '.dbo.DOCUMENTS alter column DOC_PS3 nvarchar(255) null'
exec(@sql)
--set @sql = 'alter table ' + @db_to + '.dbo.AG_BANKS drop constraint PK_AG_BANKS'
--exec(@sql)
-- объявим курсор для всех таблиц
declare Cur cursor for
select NAME
from sys.sysobjects
where TYPE = 'U'
order by NAME
open Cur
fetch next from Cur
into @tbl_name
while @@FETCH_STATUS = 0
begin
print @tbl_name
set @cols = ''
set @sql = ''
select @cols = @cols + name + ',' from syscolumns where object_name(id)=@tbl_name
set @cols = left(@cols, len(@cols)-1)
if exists (select * from syscolumns where object_name(id) = @tbl_name and status = 0x80)
begin
set @sql = @sql + ' set IDENTITY_INSERT ' + @db_to + '.dbo.' + @tbl_name + ' on'
print 'has identity column...'
end
set @sql = @sql +
' insert into ' + @db_to + '.dbo.' + @tbl_name + '(' + @cols + ')' +
' select ' + @cols +
' from ' + @db_from + '.dbo.' + @tbl_name
if exists (select * from syscolumns where object_name(id) = @tbl_name and status = 0x80)
begin
set @sql = @sql + ' set IDENTITY_INSERT ' + @db_to + '.dbo.' + @tbl_name + ' off'
end
exec(@sql)
fetch next from Cur
into @tbl_name
end
close Cur
deallocate Cur
--set @sql = 'alter table ' + @db_to + '.AG_BANKS WITH NOCHECK ADD CONSTRAINT PK_AG_BANKS PRIMARY KEY NONCLUSTERED (AB_PK) ON PRIMARY'
set @tbl_name = 'AG_BANKS'
print @tbl_name
set @cols = ''
set @sql = ''
select @cols = @cols + name + ',' from syscolumns where object_name(id)=@tbl_name
set @cols = left(@cols, len(@cols)-1)
if exists (select * from syscolumns where object_name(id) = @tbl_name and status = 0x80)
begin
set @sql = @sql + ' set IDENTITY_INSERT ' + @db_to + '.dbo.' + @tbl_name + ' on'
print 'has identity column...'
end
set @sql = @sql +
' insert into ' + @db_to + '.dbo.' + @tbl_name + '(' + @cols + ')' +
' select ' + @cols +
' from ' + @db_from + '.dbo.' + @tbl_name
if exists (select * from syscolumns where object_name(id) = @tbl_name and status = 0x80)
begin
set @sql = @sql + ' set IDENTITY_INSERT ' + @db_to + '.dbo.' + @tbl_name + ' off'
end
exec(@sql)
set @tbl_name = 'JOURNAL'
print @tbl_name
set @cols = ''
set @sql = ''
select @cols = @cols + name + ',' from syscolumns where object_name(id)=@tbl_name
set @cols = left(@cols, len(@cols)-1)
if exists (select * from syscolumns where object_name(id) = @tbl_name and status = 0x80)
begin
set @sql = @sql + ' set IDENTITY_INSERT ' + @db_to + '.dbo.' + @tbl_name + ' on'
print 'has identity column...'
end
set @sql = @sql +
' insert into ' + @db_to + '.dbo.' + @tbl_name + '(' + @cols + ')' +
' select ' + @cols +
' from ' + @db_from + '.dbo.' + @tbl_name
if exists (select * from syscolumns where object_name(id) = @tbl_name and status = 0x80)
begin
set @sql = @sql + ' set IDENTITY_INSERT ' + @db_to + '.dbo.' + @tbl_name + ' off'
end
exec(@sql)
update SYS_PARAMS
set PRM_STR = '7.0', PRM_LONG = 297
where PRM_NAME = 'VERSION'
Добавлено: Пн Окт 22, 2012 6:04 pm Заголовок сообщения: Re: Преобразование базы данных из DAO в SQL
nikman писал(а):
что лучше, переносить в совершенно чистую базу и накатывать решение потом.
Тут вопрос, захочет ли решение устанавливаться, оно и так уже стоит.
Возможность повторной установки решения(цепочки обновлений) трудно реализуется, поэтому даже если таковая предусмотрена разработчиками, лучше не надеяться что сработает безупречно.
nikman писал(а):
Или взять чистую базу с установленным решением и туда перенести данные.
Тут вопрос, как подружатся существующие данные решения с данными самой базы.
Для абстрактного двухстандартного решения различие будет только в наличии хранимых процедур, содержимое таблиц одинаково.
Предлагаю ещё один вариант перевода DAO-SQL, поскольку тема весьма актуальна всвязи с развитием А2.
Модуль запускается из открытой в Акценте чистой (или образцовой) SQL-ной базы данных.
Очищает все таблицы открытой базы данных Акцента, открывает диалог выбора файла базы DAO, после чего копирует данные из таблиц DAO в SQL.
Давно им не пользовался, поэтому тоже as-is. Чем лучше DTS - c DTS придётся повозиться, а этот модуль с большой вероятностью даст результат сразу.
Модуль копирует столбцы по их наличию в DAO таблицах, значит можно переносить данные из 6,7 версии в 7.40, но этой возможностью лучше не злоупотреблять, а перевести DAO-базу Акцентом-DAO соответствующей версии. Столбцы, добавленные в решении, должны существовать в SQL-ьных таблицах, т.е. решение должно быть накатано в обоих базах.
Из текста протокола работы модуля можно сделать чистый SQL-скрипт переноса данных путём удаления информационных сообщений.
Слегка доработанная версия находится здесь
http://www.nansi.com.ua/44058109/DAO-SQL.rar
Добавлен обход ограничения UNIQ_ACC_TREE, убрана авторизация в DAO-базе, работа проверена на нескольких базах.
Последний раз редактировалось: Юров Ю.С. (Пт Окт 26, 2012 11:24 am), всего редактировалось 1 раз
я это делал много раз и каждый раз полностью руками.
времени тратится примерно пол дня.
1. создаем новую базу со структурой
2. вычищаем все данные из таблицы валют и параметров базы данных (т.е. все таблицы д.б. пустыми)
3. переносим только основные справочники и названия параметров
4. подкидываем деревья к ним и прочие справочники
5. деревья к прочим справочникам
6. потихоньку все оставшиеся таблицы
при импорте таблиц ОБЯЗАТЕЛЬНО указывать переносить ключи как есть(не помню точное название галочки)
перед импортом таблицы JOURNAL необходимо поля j_qty и еще одно поле тоже с qty все что is null присвоить 0
Добавлено: Чт Окт 25, 2012 6:48 am Заголовок сообщения:
AllexL писал(а):
Jeck писал(а):
при импорте таблиц ОБЯЗАТЕЛЬНО указывать переносить ключи как есть(не помню точное название галочки)
set identity insert <tablename> on/off;
У меня манагер русский - разрешить вставку в столбец индификаторов.
проверил записи: 2 - 4 часа, все зависит от базы.
этот параметр необходимо проставлять при импорте каждой таблицы через ИЗМЕНИТЬ
Добавлено: Чт Окт 25, 2012 8:56 am Заголовок сообщения:
Jeck писал(а):
я это делал много раз и каждый раз полностью руками.
времени тратится примерно пол дня.
А чем скрип-то плох? Тем более, если делать это надо часто. Вручную что-то пропустил и ... Если делаете часто, берите мой или товарища Юрова, дорабатывайте все возможные нюансы и выкладываете в общее достояние )
я это делал много раз и каждый раз полностью руками.
времени тратится примерно пол дня.
А чем скрип-то плох? Тем более, если делать это надо часто. Вручную что-то пропустил и ... Если делаете часто, берите мой или товарища Юрова, дорабатывайте все возможные нюансы и выкладываете в общее достояние )
... повторный экспорт бессмысленен, вроде в SQL не так жёстко со ссылочной целостностью как в DAO ...
вот из-за этой фразы.
я столкнулся наоборот.
импорт д.б. только поэтапным
когда делал в первый раз, то не во всех таблицах поставил эту галочку и тоже начинал с импорта в чистую базу без структуры акцента. Ох и намучался
Добавлено: Пт Окт 26, 2012 5:56 am Заголовок сообщения:
Добрый день!
Спасибо всем за советы. Вроде получилось.
Расскажу по порядку, как все было. С самого начала.
1. Заказ ПО.
Юридическое лицо, на которое оформлена старая лицензия, уже давно не существует.
Но Импакту это сложно понять, поэтому он делает новую лицензию на несуществующую фирму.
Глупость? Ну да ладно, переживем.
2. Покупка ПО.
Казалось бы, ничего сложного.
Есть лицензия на Акцент 7.0 DAO 3 р.м.
Фирма переходит на Акцент 7.40 SQL 3 р.м.
Считаем стоимость нового ПО, делаем скидку 35% и все. Не тут-то было.
Оказывается скидку можно делать только на сумму Акцент 7.40 DAO.
А переход от DAO на SQL -- уже без скидки.
Выставил клиенту честную цену. Импакту доплатил из своих. Не обеднею.
В платежке так и написал: "доплата за обман и жадность".
3. Установка SQL Server.
SQL Server 2012 не захотел ставиться на Windows Server 2003.
Ладно, скачал SQL Server 2008 Express.
Блин, где же SQL Server Managment Studio (средства управленя БД)?
Ага, нужно скачать Express with Tools. Ок.
Блин, ну где же SQL Server Managment Studio?!
Ага, нужно скачать отдельно Express Managment Studio.
Ладно, заморочки MS поборол.
4. Перенос данных. Собственно.
Первым делом обновил DAO-базу до формата 7.40. На всякий случай.
Создал SQL-базу, запустил скрипт "script74_404.sql".
Переносить решил стандартными средствами SQL Server DTS.
В настройках DTS включил для всех таблиц "вставлять идентификаторы"
Остальное DTS сам сделал.
4.1 SQL-база не пустая.
Скрипт, который должен создавать пустую базу, создает не совсем пустую базу.
В конце делает записи в т. CURRENCIES и в т. SYS_PARAMS
DTS ругается, что существует записи с одинаковыми ID.
Закомментировал.
4.2 Ярлыки.
В таблице ACC_TREE стоит ограничение записи с одинаковыми полями ID и P0.
Но ведь как раз такие записи и создаются ярлыками. Странно.
Пришлось удалить все ярлыки в плане счетов.
4.3 Таблица ENTITIES
Откуда-то затесался ОУ с именем NULL. Удалил.
4.4 Таблица JOURNAL
Оказывается поле J_QTY не может быть NULL!
Очень неожиданно! Таких записей в любой базе примерно половина.
Пришлось скрипт создания базы еще подредактировать.
Убрал ограничение J_QTY not NULL.
4.5 Таблица SYS_LOG
В SQL-базе поле UID имеет тип smallint,
а в DAO-базе там везде стоит "admin". Загадочно.
Почистил логи. Надо было сразу это сделать.
Ура! Экспорт завершен успешно!
Но при запуске Акцент выдает какое-то странное сообщение
"Папку нельзя удалить, поскольку она используется в форме или диалоге... и т.д."
Удивился.
Вспомнил, что в скрипте создания базы комментировал добавление строк в таблицу SYS_PARAMS.
Исправил строку VERSION 6.0 202 на VERSION 7.4 404.
Помогло.
5. Напослелок запустил установку решения Казначея последней версии,
чтобы оно создало в новой базе все, чего ему надо.
Добавлено: Пт Окт 26, 2012 8:56 am Заголовок сообщения:
П. 4.4 - неправильно сделали. Может все и нормально будет, но 0<>null. Надо было все нулы земенить нулями, а то в будущем может непредсказуемо где-то вылезти. А может и не вылезти. Тут только Кухтин может точно сказать
Ну а по поводу остальных проблем - так они вроде достаточно описаны в данных вам скриптах?
Добавлено: Пт Окт 26, 2012 9:03 am Заголовок сообщения:
Jeck писал(а):
... повторный экспорт бессмысленен, вроде в SQL не так жёстко со ссылочной целостностью как в DAO ...
вот из-за этой фразы.
я столкнулся наоборот.
импорт д.б. только поэтапным
когда делал в первый раз, то не во всех таблицах поставил эту галочку и тоже начинал с импорта в чистую базу без структуры акцента. Ох и намучался
Не одну и ту же базу несколько раз выгружать, а разные базы. По крайней мере из ваших слов я понял именно так.
А по поводу identity_insert так мне и вовсе не понятно:
Цитата:
At any time, only one table in a session can have the IDENTITY_INSERT property set to ON. If a table already has this property set to ON, and a SET IDENTITY_INSERT ON statement is issued for another table, Microsoft® SQL Server™ returns an error message that states SET IDENTITY_INSERT is already ON and reports the table it is set ON for.
И именно в этом проблема, и именно потому я в курсоре включаю/выключаю его потаблично.
Добавлено: Пт Окт 26, 2012 11:11 am Заголовок сообщения:
Jeck писал(а):
... повторный экспорт бессмысленен, вроде в SQL не так жёстко со ссылочной целостностью как в DAO ...
вот из-за этой фразы.
я столкнулся наоборот.
импорт д.б. только поэтапным
Это в мой адрес замечание.
Следует уточнить: "не так жёстко со ссылочной целостностью как в DAO" относиться только к базам, сформированным скриптом struct_7x_xxx.sql, если запускался скрипт ссылочной целостности DRI - придётся ту же таблицу DOCUMENTS копировать по частям, сначала родительские документы, после документы которые на них ссылаются по полю DOC_LINK.
Ну тогда можно еще немного извратиться и накатить структуру в 2 этапа: сначала только структуру таблиц, потом собственно импорт данных, а уж после накатывать индексы, ключи и все такое. Если не ошибаюсь, именно чтобы не делать этого, я прогонял все таблицы, получал ошибки на банках (ссылается на корреспондентов) и джорнале (ссылается на все, на что может), клал на эти ошибки и просто в скрипт дописал в конце заполнение этих таблиц. Некрасиво, конечно, но работает
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах