Всем привет! Нужна инструкция и скрипт для обезличивания БД Oracle. Заранее благодарен

Нравится

1 комментарий

Здравствуйте, 

 

Обратитесь, пожалуйста, напрямую к команде технической поддержки, написав письмо на support@creatio.com. Чтобы мы смогли предоставить Вам нужный скрипт и соответствующую инструкцию.

 

Заранее благодарю!

С уважением, 

Анастасия

Показать все комментарии

В разделе Итоги при добавлении в дашбоард менеджера - на новую панель итогов - Графика (ChartDesigner.js) есть поле ввода "Объект" (EntitySchemaName). Оно грузит объекты частями и постепенно прогружается из-за чего поиск забагован. Нужно сразу все объекты прогрузить, но не знаю даже, куда копать...

Нравится

2 комментария

Добрый день!

 

В том случае, если Вам необходимо выводить больше записей, можно увеличить их количество в настройке:

 

 

Zhmurko Sergii, 

и где искать эту настройку?

 

Показать все комментарии

Добрый день всем! 

Просьба помочь кто  сталкивался:

Создала вью в БД, создала для нее объект "Представление в БД".

Данные выводит, если написать select.

В БПМ объект виден, колонки тоже (Уточнение: как видите, некоторые колонки справочного типа).

Но при попытке построить график в итогах по данному объекту получаю ошибочки. Не понимаю, чего от меня хочет приложение :( Мне показалось, БПМ ищет колонки с определенными названиями.

Хэлп!

SELECT TOP (1000) [UsrId]
      ,[UsrCaseId]
      ,[UsrCreatedOn]
      ,[UsrGroupId]
      ,[UsrUserid]
      ,[UsrStatusId]
  FROM [dbo].[Usr1LineReport]

Изображение удалено.Изображение удалено.

Нравится

2 комментария

А добавьте все необходимые колонки (Id, CreatedById, ModifiedById, ModifiedOn, ProccessListener - если наследуетесь от Base object) во View

Или можно ни от какой таблицы не наследоваться, тогда в Вашей схеме будут использоваться только те поля, которые есть в представлении. 

Показать все комментарии

Здравствуйте! При выполнении любого запроса в SQL Executor на демостенде(тестдрайв) версии 7.16.0.4461 выдаётся ошибка.

Например делаю такой запрос:

select * from Contact

Сама ошибка такая:

Npgsql.PostgresException (0x80004005): 42P01: relation "contact" does not exist
at Npgsql.NpgsqlConnector.d__157.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Npgsql.NpgsqlConnector.d__156.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Npgsql.NpgsqlConnector.d__156.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Npgsql.NpgsqlConnector.d__163`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Npgsql.NpgsqlDataReader.d__32.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Npgsql.NpgsqlDataReader.NextResult()
at Npgsql.NpgsqlCommand.d__71.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Npgsql.NpgsqlCommand.d__92.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at Polly.Policy.<>c__DisplayClass119_0`1.b__0(Context ctx, CancellationToken ct)
at Polly.Policy.<>c__DisplayClass129_0`1.b__0(Context ctx, CancellationToken ct)
at Polly.Policy.<>c__DisplayClass103_0.b__1(Context ctx, CancellationToken ct)
at Polly.NoOp.NoOpEngine.Implementation[TResult](Func`3 action, Context context, CancellationToken cancellationToken)
at Polly.Policy.<>c.b__103_0(Action`2 action, Context context, CancellationToken cancellationToken)
at Polly.Policy.ExecuteInternal[TResult](Func`3 action, Context context, CancellationToken cancellationToken)
at Polly.Policy.Execute[TResult](Func`3 action, Context context, CancellationToken cancellationToken)
at Polly.Policy.Execute[TResult](Func`1 action)
at Terrasoft.Core.DB.DBExecutor.FailoverExecuteReader(DbCommand command, Func`1 func)
at Terrasoft.Core.DB.DBExecutor.ExecuteCommand[TResult](Func`2 commandExecutionCallback, String sqlText, QueryParameterCollection queryParameters, CancellationToken cancellationToken)
at Terrasoft.Core.DB.DBExecutor.ExecuteReader(String sqlText, QueryParameterCollection queryParameters, CommandBehavior behavior, CancellationToken cancellationToken)
at Terrasoft.DB.PostgreSql.PostgreSqlExecutor.ExecuteReader(String sqlText, QueryParameterCollection queryParameters, CommandBehavior behavior, CancellationToken cancellationToken)
at Terrasoft.Core.DB.DBExecutor.ExecuteReader(String sqlText)
at Terrasoft.Configuration.SqlConsoleService.SqlConsoleService.ExecuteSqlScript(String sqlScript, Boolean logging)

В чём может быть проблема?

Нравится

2 комментария
Лучший ответ

Дополнение «SQL Executor» делается компанией «Программные Технологии», лучше уточнить у них. Судя по сообщению, у Вас демка на Postgres. Возможно, под эту базу ещё не адаптировали (хотя указано, что СУБД независимо) или просто в этой базе другой синтаксис выполнения запросов. Попробуйте название таблицы в кавычках.

 

И что за версия 4.16.0.4461, Вы имели в виду 7.16?

Дополнение «SQL Executor» делается компанией «Программные Технологии», лучше уточнить у них. Судя по сообщению, у Вас демка на Postgres. Возможно, под эту базу ещё не адаптировали (хотя указано, что СУБД независимо) или просто в этой базе другой синтаксис выполнения запросов. Попробуйте название таблицы в кавычках.

 

И что за версия 4.16.0.4461, Вы имели в виду 7.16?

Зверев Александр, ковычки помогли. Благодарю. С версией действительно ошибся. Уже исправил.

Показать все комментарии

Здравствуйте.
Подскажите пожалуйста каким образом можно удалить созданные детали, которые уже не используются или же были созданы ошибочно? В Конфигурации удалил из папки всё. Однако, при добавлении ново созданных деталей в списке остаются и старые, которые были удалены.
Благодарю.

Нравится

4 комментария

Дмитрий, думаю, что данная статья поможет
http://www.community.terrasoft.ru/forum/topic/13214

"Демьяник Алексей Олегович" написал:Здравствуйте!

Сами разделы/детали (их страницы редактирования, а также объекты, на которые они ссылаются) Вы можете удалить из конфигурации.
При этом в базе данных останутся записи. Необходимо удалить записи с таблиц:
SysModule
SysModuleEdit
SysModuleEditLcz

Также обратите внимание на таблицу SysDetails.

Добрый день Дмитрий!!!

на будущее совет прежде чем удалять Деталь, Страницу редактирования, или раздел из конфигурации, скопируйте все Uid каждой схемы.
постройте запросы к таблицам
- SysSchema
- SysModuleEntity
- SysModuleEdit
- SysModuleEditLcz
- SysDetails
- SysModule
- SysModuleLcz
Найдите все хвосты, где хранятся ссылки на удаляемые схемы, вычистите таблицы, а уже после удаляйте схемы через конфигурацию. Так будет надежнее. И не забывайте о "Данных", именно с помощью данных мы фиксируем и переносим наши созданные новые страницы. Там тоже нужно не забывать вычищать все.

Здравствуйте.
Спасибо за помощь. Покопаюсь в таблицах.

Добрый день Дмитрий!!!

я бы вам посоветовал написать 1 UNION запрос в который бы собиралась вся информация о удаляемой схеме. вам бы так легче было бы.

Показать все комментарии

Здравствуйте!

Рассматриваем вариант с переносом базы данных Terrasoft на виртуальную машину под управлением Windows 7 Professional 64-bit + MS SQL Server Express. На данный момент система работает под управлением Windows SBS 2011 (Усечённая версия Windows Server 2008 R2). Просьба уточнить :

• Может ли данный перенос повлиять на работоспособность системы?
• Потребуется ли перезаказывать лицензии?

Нравится

1 комментарий

Здравстуйте.
Перенос не повлияет на работоспособность системы. Если речь идёт о BPMonline, то перезаказ лицензий обязателен. Ежели подразумевается Terrasoft 3.x, то перезаказ необходим в случае конкурентных лицензий. При наличии именных, нужно будет в ручном режиме создвать логины на SQL-сервере и "привязывать" их к пользователям в базе данных. Если понадобится - обращайтесь в поддержку (support@terrasoft.ru). Так будет проще и оперативнее решить вопрос.

Показать все комментарии

Добрый день!

Можно узнать, почему в версии 3.4 отказались от кластерных индексов на таблицах?
В таких условиях производительность БД будет неуклонно(!) снижатся по мере увиличения количества записей в таблицах.
Я конечно понимаю, что кластерный индекс по GUIDу не лутшее решение из за его быстрой фрагментации, но почему в таком случае не добавить в таблицы identity колонку?
С уважением,
Михаил

Нравится

3 комментария

Здравствуйте.

Уточню данную информацию у коллег из департамента разработки, и сообщу Вам в ближайшее время ответ.

Так и не уточнили?

Здравствуйте, Михаил.

"Домброва Михаил" написал:Можно узнать, почему в версии 3.4 отказались от кластерных индексов на таблицах?

Они не нужны.

"Домброва Михаил" написал:В таких условиях производительность БД будет неуклонно(!) снижатся по мере увиличения количества записей в таблицах.

В условиях, когда остальная окружающая базу среда не меняется.
"Домброва Михаил" написал:
Я конечно понимаю, что кластерный индекс по GUIDу не лутшее решение из за его быстрой фрагментации, но почему в таком случае не добавить в таблицы identity колонку?

А зачем?

Показать все комментарии

Начиная с версии 3.4.0 управлять отображением полей в реестре записей детали [Журнал изменений] можно установив настройку «Отображать в реестре».

Настройка выполняется следующим образом:

  1. Перейти в меню [Файл] - [Настройки] - [Журнал изменений БД];
  2. Выбрать таблицы и поля таблиц по которым необходимо отслеживать изменения. Для того, чтобы поля отображались в реестре записей детали [Журнал изменений], следует установить признак «Отображать в реестре» :
    a13

Нравится

Поделиться

0 комментариев
Показать все комментарии

Решил обобщить немного информации о том, какие действия чаще-всего требуется выполнять при перенесении базы данных Terrasoft для СУБД MS SQL.
Также хотелось бы ответить на часто задаваемый пользователями вопрос: переносить базу данных без проблем можно либо на SQL сервер той-же версии, либо версии старше (т.е. с MS SQL 2005 на MS SQL 2008 база данных может быть перенесена, наоборот же, с более новой версии на более старую, перенос базы данных не подразумевается).

Итак, при переносе базы данных с сервера на сервер выполняется следующая последовательность действий:

Необходимо сделать бэкап базы данных на одном сервере и восстановите его на втором.

Если использовались конкурентные лицензии, то в первую очередь очистите значение сервера сессий для базы данных. Сделать это можно с помощью следующего запроса к базе данных:
update tbl_DataBaseInfo set ServerSessionsInfo = NULL

Для выполнения запроса сделайте следующее:
Вызовите контекстное меню, нажав правой кнопкой мыши на названии базы данных, и выбрать New Query.

Далее ввести запрос и нажать Execute для его выполнения.

После этого Вам необходимо будет перезаказать конкурентные лицензии.

Также при переносе базы данных на другой сервер необходимо производить сопоставление пользователей базы данных Terrasoft с именами входа в MS SQL.

Предварительно необходимо создать соответствующие имена входа на SQL сервере.

Для этого на сервере необходимо перейти во вкладку [Security]>[Logins] и там создать соответствующие имена входа.

Обязательно при создании имени входа для пользователя указать тип авторизации – «SQL аторизация»:

Также обязательным условием является установка серверной роли «сисадмин» для имени входа системного администратора Terrasoft.

Далее необходимо провести, собственно, сопоставление. Сделать это можно выполнив запрос к базе данных следующего рода:

sp_change_users_login 'update_one', 'fkeys', 'fkeys'

Данный запрос необходимо выполнить для каждого пользователя Terrasoft заменив в запросе слово “fkeys” на соответственное (например для supervisor’a данный запрос примет вид sp_change_users_login 'update_one', 'supervisor', 'supervisor').

Далее, если предполагается перенос базы данных в другой домен (следовательно, и пользователи с домена изменятся) для изменения пользователей Вам необходимо выполнить следующий порядок действий:
1. В таблице tbl_AdminUnit базы данных Terrasoft в полях .Name и .SQLObjectName заменить соответствующие записи пользователей из старого домена на новые. Например если пользователь раньше имел имя tm/Yakovenko (домен tm), а стал tcrm/Yakovenko (домен tscrm), то записи в указанных полях Вы должны заменить на tcrm/Yakovenko.

2. Создать login (подтянуть из Active Directory).
3. Добавить пользователя в БД с новым логином.
4. Если пользователь имел роль системного администратора в Terrasoft, то его логину необходимо дать роль sysadmin.
5. Если пользователь имел роль обычного администратора в Terrasoft, то его логину необходимо дать роль dbowner.
6. После этого в Terrasoft в разделе [Администрирование] каждому пользователю на детали [Группы] необходимо удалить и добавить все группы (таким образом пользователю перераздадутся права доступа).

Нравится

Поделиться

14 комментариев

А что делать, если нет колонки ServerSessionsInfo в tbl_DataBaseInfo? У меня TS CRM 3.2.0.10. Хотя у меня и так сработало, без этого update.

Анна, дело в том, что в версии 3.2.0 еще не было конкурентных лицензий, а данный скрипт:

update tbl_DataBaseInfo set ServerSessionsInfo = NULL

необходимо выполнять только при использовании конкурентных лицензий.
Если их нет, то соответственно, таблицы тоже не будет :wink:

Переносил Terrsfoft XRM 3.3.2 в новый Win 2008 домен.
Вот скрипты шагов 1-5, описанных Владом для MS SQL Server 2008 R2.

-- восстановили БД
RESTORE DATABASE [TSXRM] FROM DISK = 'c:\TSXRM.BAK'
GO
 
--подключаемся к восстановленной БД
USE TSXRM
GO
 
--пересвязываем системного юзера 
EXEC sp_change_users_login 'update_one', 'fkeys', 'fkeys'
GO
 
-- создаем заново имена входа (проверяем не существует ли уже такое имя входа, 
-- чтобы можно было запускать скрипт многократно)
IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = N'SQLServerAuthLoginName') 
	CREATE LOGIN [SQLServerAuthLoginName] WITH password = '123456', DEFAULT_DATABASE = [TSXRM], DEFAULT_LANGUAGE=[русский]
go
 
-- пересвязываем созданные sqlserver`ные имена входа с пользователями
EXEC sp_change_users_login @action = 'update_one', @UserNamePattern = 'SQLServerAuthUserName', @LoginName = 'SQLServerAuthLoginName'
GO
 
-- создаем NT`ные (виндовые, доменные) имена входа 
IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = N'MyNewDomainName\TSAdminUserName') 
	CREATE LOGIN [MyNewDomainName\TSAdminUserName] FROM WINDOWS WITH DEFAULT_DATABASE=[TSXRM], DEFAULT_LANGUAGE=[русский]
 
--добавляем в группу db_owner, если юзер есть админ в TS
EXEC sys.sp_addrolemember  @rolename = 'db_owner', @membername = N'MyNewDomainName\TSAdminUserName'	
 
--создаем пользователя для имени входа (создание собственной схемы вроде не нужно)
--CREATE SCHEMA [MyNewDomainName\TSAdminUserName] AUTHORIZATION [MyNewDomainName\TSAdminUserName]
IF  NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = N'MyNewDomainName\TSAdminUserName')
	CREATE USER [MyNewDomainName\TSAdminUserName] FOR LOGIN [MyNewDomainName\TSAdminUserName] -- WITH DEFAULT_SCHEMA=[MyNewDomainName\TSAdminUserName]
 
--удаляем старых пользователей (сначала удалив собственную схему)
IF  EXISTS (SELECT * FROM sys.database_principals WHERE name = N'OldDomainName\TSAdminUserName')
BEGIN
	DROP schema	[OldDomainName\TSAdminUserName]
	DROP USER [OldDomainName\TSAdminUserName]
END
GO
 
--правим имя домена в таблице AdminUnit
DECLARE @OldDomainName AS NVARCHAR(255)
DECLARE @NewDomainName AS NVARCHAR(255)
SET @OldDomainName = N'OldDomainName'
SET @NewDomainName = N'MyNewDomainName'
 
UPDATE 
	[tbl_AdminUnit]
SET		
	Name = REPLACE([Name], @OldDomainName, @NewDomainName),  
	SQLObjectName = REPLACE([SQLObjectName], @OldDomainName, @NewDomainName)
WHERE 
	IsDomainUnit = 1

Интересно, если бы перенос был на MS SQL Server 2012, получилось бы сделать БД Terrasoft contained database, дабы избежать необходимости отдельного переноса имен входа?

Здравствуйте.
При создании пользователя в базе данных он автоматически дублируется логином на уровне СУБД. Если Вы перенесёте базу на другой SQl-сервер, пользователи вместе с базой перенесутся, а логины, соответственно - нет. Их нужно будет создавать в ручном режиме и связывать с пользователями "хранимкой" sp_change_users_login. Если пользователей очень много, то можно пробовать это выполнять путём переноса\модификации системной базы master. Протестированного механизма - нет. Всё же рекомендую выполнить сопоставление логинов через процедуру.
С уважением, Terrasoft Support Team.

Александр, особенность contained database в том, что они включают в себя такие объекты уровня сервера, как например, имена входа (логины). Эта возможность появилась в MS SQL Server 2012.
Другое дело, что не каждая легаси-БД с прежней версии сервера может быть приведена к виду contained database.
Как раз в этом и была суть моей мысли - может ли база TS приведена к такому виду.

Здравствуйте.
Официально мы не декларировали возможность работы с СУБД MS SQL Server 2012. По сему подобную возможность нужно тестировать. Как вариант можете ознакомиться с тематическими материалами по ссылках: http://reznik.uneta.com.ua/post/2011/05/09/sql-server-denali-contained-…
http://blogs.msdn.com/b/sqlsecurity/archive/2010/12/03/contained-databa…
С уважением, Terrasoft Support Team.

Нужен хэлп.
Скрипт sp_change_users_login 'update_one', '', '' выдаёт ошибку:

"Msg 15291, Level 16, State 1, Procedure sp_change_users_login, Line 114
Terminating this procedure. The User name 'fkeys' is absent or invalid".

Читал вот здесь: http://www.community.terrasoft.ru/forum/topic/6775 , что причина может крыться в недостатке прав юзера, из под которого мы пытаемся его выполнить, однако, я это пробовал делать даже из под "sa".

Раньше каким-то чудом на другой машине умудрился восстановить бэкап master. Сейчас такой фокус не проходит (после восстановления сервер не стартует), а при ручном добавлении логинов, появляется проблема описанная выше.

Игорь, у меня была та же проблема! Причина была в "...'fkeys' is absent...". Создал пользователя и хранимая процедура выполнилась.

Добры день!

Переносим тестовую базу на другой сервер. Работаем по конкурентным лицензиям,

Terrasoft Sales, версия 3.3.2.47

MSSQL 2010

При попытке адмнов перенести логины все сразу, появляется сообщение
The database 'Terrasoft332_Sales' does not exist. Supply a valid database name. To see available databases, use sys.databases.

'Terrasoft332_Sales' - это название боевой базы, с которой берутся лицензии для тестовой. Подскажиет пожалуйста, в чем может быть проблема?

Здравствуйте. Каким образом переносили все логины сразу? Они содержатся в системной базе "master". Можно попробовать выполнить это путём преноса базы "master", но процедура довольно нетипиная, лежит исключительно в области администрирования СУБД и требует тестирования. Дело в том, что манипуляции с системными легко могут повредить сам SQL-сервер. Гораздо проще логины создать в ручном режиме. После переноса базы с конкурентными лицензиями их необходимо будет перезаказать. Так же, если использовался сервер сессий, то он должен быть доступен для нового сервера БД.

Последний раз я так как Вы сказали я и сделал, всё получилось. А перенести "master" первый раз удалось, действительно задача, прямо скажем: мягко говоря нетривиальная, это удалось сделать в сингл-юзер режиме под пользователем "sa" из консоли. Больше я этим заниматься желанием не горю

Почему в статье самое главное не указывается, т.е. если информацию по собственно переносу базы можно найти без проблем в открытых источниках, то я лично застрял на совершенно глупом на мой взгляд шаге, и фича чисто террасофтовская - изменить строку соединения сервера сессий конкурентных лицензий.
Два дня убил на поиски проблемы почему у меня база после переноса с сервера А на сервер B все равно смотрит на сервак А. Выяснял этот факт тоже опытным путем - гашу инстанцию на сервере А после переноса (что бы пользователи не имели доступа к старой базе не при каких обстоятельствах) нет коннекта к новой базе на сервере B - ошибка - отсутствует доступ к базе, периодически ошибка сменялась на отсутствие доступа из под логина. Первоначально грешил на соответственно на логины - и скрипт c update_one затер просто до дыр.
Запускаю сервис MS SQL на старой могу заходить в новую базу. Netstat-ом выяснил, что есть обращения с B на A, но по какой причине - не было понятно.
Совершенно случайно, когда стало окончательно понятно, что проблема не на стороне SQL и логинов в базе master, я начал перебирать уже все, что можно настраивать на стороне 3ки, так я и набрел на эту настройку.
Переезд базы задача не повседненвная и держать настройки в голове по сервису конкурентных лицензий вообще не получается. Странно что эти грабли нигде не описаны.

Переезд версии 3.4.х  c MSSQL 2005 на 2012.

Сделал обычный полный бэкап базы на 2005

Восстановил эту базу на 2012

На 2005 запустил системную процедуру sp_help_revlogin, исходник которой есть на просторах интернета. Она выдаёт готовый скрипт на создание имён входа. Подчистил скрипт, чтобы он не пересоздал уже имеющиеся системные логины, типа SA и т.п.

Запустил этот скрипт на 2012. Все имена входа создались. Самое главное, что их ID, роли и права абсолютно идентичны старому серверу.

Предыдущие два пункта выполняются под пользователем, имеющем достаточные права к базе master. Лучше под sa.

При запуске ServiceDesk создал новую конфигурацию, указав новый сервер. Заход под пользователем с именной лицензией прошел сразу. Под конкурентными лицензиями не пускало. 

Из мененджера лицензий штатно создаю запрос, получаю ответ, загружаю. И всё работает.

Показать все комментарии

Ни раз возникала задача переноса данных из одной БД в другую. Как правило, это Контакты, Контрагенты, Задачи. Задача усложнялась тем, что БД могут быть не совсем похожи по структурам. Приходилось писать insert-select конструкции с перечислением всех полей, которые необходимо перенести. Дабы упростить, а главное ускорить сей процесс был написал скрипт, которому собственно и посвящен этот пост.
Собственно, что делает сам скрипт. Идет по списку таблиц, указанных пользователем, проверяет соответствие полей в таблицах обеих БД, формирует запрос и выполняет его.
Возможно эти труды будут кому-то полезны.
Скрипт:

begin transaction
declare @syncTablesNames TABLE (TableName varchar(50));
declare @sourceDBName varchar(50),
                @tableName varchar(50),
                @columnName varchar(50),
                @sourceColumnExists bit,
                @insertSQLText nvarchar(MAX),
                @selectSQLText nvarchar(MAX),
                @columnExistsSQLText nvarchar(MAX),
                @idExistsCondition nvarchar(MAX),
                @resultSQLText nvarchar(MAX);

SET @sourceDBName = 'SourceDataBaseName';

-- set tables names
INSERT INTO @syncTablesNames
        SELECT 'tbl_Contact' UNION
        SELECT 'tbl_Account';


declare tableNameCursor cursor LOCAL FAST_FORWARD FOR SELECT * FROM @syncTablesNames;

open tableNameCursor;

fetch next FROM tableNameCursor INTO @tableName

WHILE (@@fetch_status = 0)
BEGIN
        SET @insertSQLText = 'insert into ' + @tableName + '(';
        SET @selectSQLText = 'select ';
        SET @idExistsCondition = ' where not ID in (select ID from ' +
           @tableName + ');';

        --Disable Table Constraint
        exec ('alter table ' + @tableName + ' nocheck constraint all; ');

        declare columnNameCursor cursor LOCAL FAST_FORWARD FOR SELECT COLUMN_NAME                                                  
                                                     FROM information_schema.COLUMNS
                                                     WHERE TABLE_NAME = @tableName;
        open columnNameCursor;
        fetch next FROM columnNameCursor INTO @columnName;
        while (@@fetch_status = 0)
        begin
                SET @columnExistsSQLText = 'if exists (select COLUMN_NAME ' +
                                                'from ' + @sourceDBName +  
                                                '.information_schema.columns ' +
                                                'where TABLE_NAME = ''' +
                                                       @tableName + ''' AND ' +
                                                      'COLUMN_NAME = ''' +  
                                                       @columnName + ''') ' +
                                              'set @sourceColumnExists = 1 ' +
                                           'else ' +
                                              'set @sourceColumnExists = 0 ';
       
                --check remote table column exists
                exec sp_executesql @columnExistsSQLText,
                                   N'@sourceColumnExists bit out',
                                   @sourceColumnExists = @sourceColumnExists output

                --include column into select-insert statment
                IF (@sourceColumnExists = 1)
                begin
                        SET @insertSQLText = @insertSQLText + @columnName + ', ';
                        SET @selectSQLText = @selectSQLText + @columnName + ', ';
                end;

                fetch next FROM columnNameCursor INTO @columnName;
        end;
        close columnNameCursor;
        deallocate columnNameCursor;

        SET @insertSQLText = substring(@insertSQLText, 1, len(@insertSQLText) - 2);
        SET @selectSQLText = substring(@selectSQLText, 1, len(@selectSQLText) - 2);

        SET @insertSQLText = @insertSQLText + ') ';
        SET @selectSQLText = @selectSQLText + ' from ' + @sourceDBName + '.dbo.' +    
           @tableName + @idExistsCondition;
       
        --result select-insert statment
        SET @resultSQLText = @insertSQLText + @selectSQLText;

        exec (@resultSQLText);

        fetch next FROM tableNameCursor INTO @tableName
END;

close tableNameCursor;
deallocate tableNameCursor;


--Enable Table Constraint
declare tableNameCursor cursor LOCAL FAST_FORWARD FOR SELECT * FROM @syncTablesNames;
open tableNameCursor;
fetch next FROM tableNameCursor INTO @tableName;

WHILE (@@fetch_status = 0)
BEGIN
        exec ('alter table ' + @tableName + ' check constraint all; ');
        fetch next FROM tableNameCursor INTO @tableName;
END;

close tableNameCursor;
deallocate tableNameCursor;

rollback

Нравится

Поделиться

16 комментариев

Юрий, в принципе очень добротный скрипт, но есть пара замечаний:
1. Я бы обрамлял идентификаторы в []
2.

"Доленко Юрий" написал:TableName varchar(50)

Есть системный тип - sysname, он лучше подходит для идентификаторов таблиц, колонок
3.
"Доленко Юрий" написал:--Disable Table Constraint
      exec ('alter table ' + @tableName + ' nocheck constraint all; ');

Я бы еще и триггера отключал, ну и ";" - лишнее
4.
"Доленко Юрий" написал:rollback

Это как говорится: "Счастливой отладки:)"?

В принципе это нужный скрипт (если разговор идет только в рамках MSSQL). Сам столкнулся с такой проблемой, но решил ее стандартными средствами. Нужно было перенести данные с 3.2.0 FB в 3.3.2 MSSQL.В версии 3.3.2 появилась возможность выгружать и загружать данные таблиц (wnd_DataManager). Эти сервисы переносятся и в 3.2 (была такая необходимость :)).
Во всяком случае два варианта лучше чем один :smile:

5.

"Доленко Юрий" написал:@insertSQLText nvarchar(MAX),

К сожалению для mssql 2000 не пойдет... Для него можно пойти путем как сделано в ХП - tsp_AdministratedByRecords

Александр, большое спасибо за советы, обязательно учту. (я рассчитывал черпнуть чего полезного из этого поста :) )

"Евгений Либин" написал:В версии 3.3.2 появилась возможность выгружать и загружать данные таблиц (wnd_DataManager).

Как же все-таки полезно писать блоги ). Относительно давно работаю с террасофтом, но о такое полезной утилитке не слышал. Действительно, выгружает/загружает xml, хотя судя по коду не отключаются ни триггера, ни constraint и грузится только по одной таблице. Могут ли быть нарушения целостности в процессе?

Нет, она не отключает не триггеры и констреинты. Можно выгружать сразу несколько таблиц. Я делал так, сначала выгрузил все справочники и загружал полученный скрипт пока на уйдут ошибки о несуществующих данных в связанных справочниках :lol:
После этого перешел к контактам и контрагентам. Тут как всегда философия "что было раньше контакт или контрагент?". В общем, сделал сначала загрузку контактов без ссылки на контрагента, а потом загрузил контрагентов и еще раз загрузил контакты.:lol:

Тоже была подобная задача по перебросу из FB в MS SQL. Есть такая штука как EMS SQL Managment studio для фаерберда. Там можно выгружать sql-скрипт(вида insert ... values) таблицы в синтаксисе t-sql(в нашем случае), при чем выбирать поля, которые будут фигурировать в запросе.
Потом можно отключить ограничения и просто выполнить каждый по одному разу...

DataManager позволяет выгрузить несколько таблиц в один файл и соответственно загрузить. Причиной его создания было то, что разработчики решили упростить перенос создаваемого в процессе разработки наполнения с базы разработки на живую базу, это как правило были записи справочников.

В вашем скрипте есть пара неточностей, которые мешают нормально загружать данные.
в скрипте scr_DataManagerUtils
процедура SetDatasetValuesByDataRowNode
строку

if (DataRowNode.GetAttributeAsStr(DataField.Name, '') == 'IsNull') {

надо заменить на

if (DataRowNode.GetAttributeAsStr(DataField.Name, 'IsNull') == 'IsNull') {

процедура LoadDataFromDataRowNodeToDataset
строку

Log.Write(2, "Ошибка загрузки: " + e.Message)

надо заменить на

Log.Write(2, "Ошибка загрузки: " + e.message)

Если вы посчитаете мои замечания корректными - то включите их в базовую версию

Евгений, спасибо за замечания.

"Евгений Либин" написал:надо заменить на

if (DataRowNode.GetAttributeAsStr(DataField.Name, 'IsNull') == 'IsNull') 

{


В таком случае выйдет, что если в базе, в которую загружают, есть поле, которого не было в базе, из которой выгрузили данные, и данные обновляются (например, повторная загрузка), а значение этого поля было заполнено, то оно перетрется. Не думаю, что это всегда правильно. Думаю, правильнее будет дописать еще одно условие:

if (DataRowNode.GetAttributeAsStr(DataField.Name, '') == '') {
	continue;
}

Четко подмечено :twisted:

Т.е. в результате мы получим такой код?

		if (DataRowNode.GetAttributeAsStr(DataField.Name, '') == 'IsNull') {
			DataField.Value = null;
			continue;
		}
		if (DataRowNode.GetAttributeAsStr(DataField.Name, '') == '') {
			continue;
		}

Надо бы добавить обработку загрузки контрактов-контрагентов

Да, думаю, такой, только вынести бы в отдельную переменную

var DataFieldNameAttr = DataRowNode.GetAttributeAsStr(DataField.Name, '');

"Евгений Либин" написал:Надо бы добавить обработку загрузки контрактов-контрагентов

Какую именно обработку Вы имеете ввиду?

Если переносить в чистую базу раздел контакты, то без контрагентов контакты не зальются (Поле контрагент заполнено), а контрагента нельзя залить пока не залиты контакты (поле основной контакт). Вот и получается что нужно сделать признак вида "сохранять контакт при отсутствующем контрагенте" и в коде проверять: если грузим контакты, то проверить наличие контрагента и тд.... Хотя, наверно, у вас найдется более изящное решение этой проблемы :wink:

Теперь я чувствую себя просто обязанной придумать альтернативный вариант :) Не уверена, что изящно, но можно удалять связи контрагента с контактом и контакта с контрагентом в таблицах, а после импорта создавать заново. Тогда должен быть более сложный выбор таблиц, потом полей, на которые не должна срабатывать проверка связи. Зато это будет в один проход.

"Раловец Ольга" написал:придумать альтернативный вариант :)

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

"Доленко Юрий" написал:Раловец Ольга пишет:
придумать альтернативный вариант :)
Так вот же он) в первом посте.

Юрий, отличный вариант :) Просто мы с Евгением уже начали обсуждение в контексте Datamanager.

К сожаление скрипт не смотрел, но идея с переносом ссылок должна быть такой:
1. Переносим все данные без внешних ссылок
2. Обновляем все записи, где проставляем ссылки, благо у нас GUID, и тем более все ссылки уже физически присутствуют в БД
Есть вопрос со ссылками, когда они обязательны на уровне БД. Тогда надо проверить, если поле ссылка обязательное, то в таблицу справочник вносим мнимую запись скажем нулевым GUID или с каким-то признаком в Name (как правило такое поле есть) - например со значением "Импорт. Удалить после привязки ссылок". И тогда во все записи с таким и полями вставляем ссылку на мнимую запись и обновляем ее после переноса всех записей.

Показать все комментарии