SQL_scripts
/
синхронизация баз данных серверов (деплой).sql
1863 строки · 63.8 Кб
1
2--скрипт запускается на сервере приемнике, который должен быть смапен по базам с источником (в таблице #db_list)
3--при @ops = 0 генерируется скрипт на устранение различий в схемах объектов, запускается отдельно, возможен выбор объектов
4--при @ops = 1 выполняется накатывание всех найденных различий
5
6set nocount, xact_abort on
7
8declare
9-- 0=только сгенерировать скрипт, 1=устранить все различия
10@ops int = 0
11-- фильтр для таблиц (разделитель | )
12,@exclude_tables nvarchar(max) = ''
13-- фильтр для индексов (разделитель | )
14,@exclude_indexes nvarchar(max) = ''
15-- фильтр для модулей (разделитель | )
16,@exclude_modules nvarchar(max) = ''
17-- фильтр для ограничений (разделитель | )
18,@exclude_defaults nvarchar(max) = ''
19--минимальное значение даты принятое в системе
20,@min_year nvarchar(4) = '1900'
21--в какой базе хранить метаданные
22,@metadata_db sysname = 'TempDB'
23
24--перечень серверов и их баз данных на которых возможен запуск скрипта
25drop table if exists #db_list
26select *
27into #db_list
28from (values
29('сервер источник 1', 'база данных 1', 'сервер приемник 1', 'файловая группа')
30,('сервер источник 1', 'база данных 2', 'сервер приемник 1', 'файловая группа')
31,('сервер источник 2', 'база данных 3', 'сервер приемник 2', 'файловая группа')
32,('сервер источник 3', 'база данных 4', 'сервер приемник 2', 'файловая группа')
33) as t (src_srv, db, trg_srv, trg_filegr)
34
35--*******************************************************************************************************--
36declare
37@query nvarchar(max)
38,@applock_const nvarchar(50) = 'SYNCHRO'
39,@result int
40,@user sysname = system_user
41,@message nvarchar(max) = ''
42,@source_server sysname
43,@db sysname
44,@sysTable sysname
45,@target_filegroup sysname
46,@current_step nvarchar(10)
47,@step_desc nvarchar(max)
48,@sql_text nvarchar(max)
49,@sql_text2 nvarchar(max)
50,@synch_result_tbl sysname = @metadata_db + '..synch_result_' + format(getdate(), 'HHmmss')
51
52if (@@servername like '%PROD%')
53throw 50000, 'СКРИПТ НЕ ДЛЯ ПРОДА !', 1
54
55if cast(serverproperty('ProductMajorVersion') as int) < 14
56throw 50000, 'ВЕРСИЯ СЕРВЕРА МЛАДШЕ ДОПУСТИМОЙ !', 1
57
58if exists (select * from #db_list where db = @metadata_db)
59throw 50000, 'ДЛЯ ХРАНЕНИЯ МЕТАДАННЫХ УКАЖИТЕ БД КОТОРАЯ НА УЧАСТВУЕТ В СИНХРОНИЗАЦИИ ДАННЫХ !', 1
60
61if exists (select * from #db_list where db = 'tempdb')
62throw 50000, 'TEMPDB НЕ ДОЛЖНА УЧАВСТВОВАТЬ В СИНХРОНИЗАЦИИ ДАННЫХ !', 1
63
64declare
65@c_nl char(2) = char(13)+char(10)
66,@t_source nvarchar(10) = 'source'
67,@t_target nvarchar(10) = 'target'
68,@t_schema nvarchar(10) = 'schema'
69,@t_table nvarchar(10) = 'table'
70,@t_column nvarchar(10) = 'column'
71,@t_index nvarchar(10) = 'index'
72,@t_constraint nvarchar(10) = 'constraint'
73,@t_function nvarchar(10) = 'function'
74,@t_procedure nvarchar(10) = 'procedure'
75,@t_trigger nvarchar(10) = 'trigger'
76,@t_view nvarchar(10) = 'view'
77,@t_synonym nvarchar(10) = 'synonym'
78,@t_sequence nvarchar(10) = 'sequence'
79,@t_partition_function nvarchar(20) = 'partition_function'
80,@t_partition_scheme nvarchar(20) = 'partition_scheme'
81,@t_create nvarchar(10) = 'create'
82,@t_drop nvarchar(10) = 'drop'
83,@t_alter nvarchar(10) = 'alter'
84,@marker nvarchar(10) = ';;;'
85
86select @exclude_tables = string_agg(concat('t.[name] like ', quotename(trim([value]), '''')), ' or ')
87from string_split(@exclude_tables, '|')
88where [value] <> ''
89
90select @exclude_indexes = string_agg(concat('i.[name] like ', quotename(trim([value]), '''')), ' or ')
91from string_split(@exclude_indexes, '|')
92where [value] <> ''
93
94select @exclude_modules = string_agg(concat('o.[name] like ', quotename(trim([value]), '''')), ' or ')
95from string_split(@exclude_modules, '|')
96where [value] <> ''
97
98select @exclude_defaults = string_agg(concat('df.[name] like ', quotename(trim([value]), '''')), ' or ')
99from string_split(@exclude_defaults, '|')
100where [value] <> ''
101
102set @metadata_db = quotename(parsename(@metadata_db,1))
103
104exec @result = sys.sp_getapplock
105@Resource = @applock_const
106,@LockMode = 'exclusive'
107,@LockOwner = 'session'
108,@LockTimeout = 0
109,@DbPrincipal = @user
110
111if @result < 0
112begin
113select @message = string_agg(request_session_id, ',')
114from sys.dm_tran_locks (nolock)
115where
116resource_type = 'APPLICATION'
117and request_owner_type = 'SESSION'
118and resource_description like '%' + @applock_const + '%'
119
120set @message = concat('ЗАКРОЙТЕ СЕССИИ: ', @message, ' !')
121
122;throw 50000, @message, 1
123end
124
125drop table if exists [#SCRIPT_TABLE]
126
127create table [#SCRIPT_TABLE] (
128db sysname not null
129,current_step int not null
130,step_desc nvarchar(max) not null
131,sql_text nvarchar(max) not null
132,object_desc nvarchar(128) not null
133,index ix_db clustered (db)
134)
135
136declare cursDB cursor for
137select
138src_srv
139,db
140,trg_filegr
141from #db_list
142where @@servername like '%' + trg_srv + '%'
143open cursDB
144fetch next from cursDB into @source_server, @db, @target_filegroup
145while @@fetch_status = 0
146begin
147
148begin--получение метаданных
149
150drop table if exists [#SYS_schemas]
151drop table if exists [#SYS_tables]
152drop table if exists [#SYS_columns]
153drop table if exists [#SYS_columns_alter]
154drop table if exists [#SYS_indexes]
155drop table if exists [#SYS_constraints]
156drop table if exists [#SYS_modules]
157drop table if exists [#SYS_synonyms]
158drop table if exists [#SYS_sequences]
159drop table if exists [#SYS_partition_schemes]
160drop table if exists [#SYS_partition_functions]
161drop table if exists [#SYS_partition_alter]
162
163create table [#SYS_schemas] (
164[purpose] nvarchar(10) not null
165,[server] nvarchar(128) not null
166,[db] nvarchar(128) not null
167,[id] int not null
168,[name] nvarchar(128) not null
169,[purpose.id] as concat(purpose, ':', [id]) persisted not null
170)
171
172create table [#SYS_tables] (
173[purpose] nvarchar(10) not null
174,[server] nvarchar(128) not null
175,[db] nvarchar(128) not null
176,[id] int not null
177,[schema] nvarchar(128) not null
178,[name] nvarchar(128) not null
179,[is filetable] bit
180,[is in-memory] bit
181,[durability] nvarchar(128)
182,[is external] bit
183,[is node] bit
184,[is edge] bit
185,[is encrypted] bit
186,[is fake] bit
187,[is temporal] bit
188,[lock escalation] nvarchar(128)
189,[schema.table] as ([schema] + '.' + [name]) persisted not null
190,[purpose.id] as concat(purpose, ':', [id]) persisted not null
191,[not supported] as ([is filetable] | [is in-memory] | [is external] | [is node] | [is edge] | [is encrypted] | [is fake] | [is temporal])
192)
193
194create table [#SYS_columns] (
195[purpose] nvarchar(10) not null
196,[server] nvarchar(128) not null
197,[db] nvarchar(128) not null
198,[table id] int not null
199,[name] nvarchar(128) not null
200,[ordinal position] int
201,[is nullable] bit
202,[is rowguidcol] bit
203,[is identity] bit
204,[is filestream] bit
205,[is xml_document] bit
206,[is sparse] bit
207,[is column_set] bit
208,[is hidden] bit
209,[is masked] bit
210,[seed value] bigint
211,[increment value] bigint
212,[last value] bigint
213,[is computed] bit
214,[definition for computed] nvarchar(max)
215,[is persisted] bit
216,[collation] nvarchar(128)
217,[type name] nvarchar(128)
218,[type size] nvarchar(128)
219,[default for type] nvarchar(128)
220,[purpose.table id] as concat(purpose, ':', [table id]) persisted not null
221)
222
223create table [#SYS_columns_alter] (
224[schema.table] nvarchar(128) not null
225,[name] nvarchar(128) not null
226,primary key ([schema.table], [name])
227)
228
229create table [#SYS_indexes] (
230[purpose] nvarchar(10) not null
231,[server] nvarchar(128) not null
232,[db] nvarchar(128) not null
233,[table id] int not null
234,[name] nvarchar(128)
235,[key column names] nvarchar(max)
236,[included column names] nvarchar(max)
237,[index type] nvarchar(128)
238,[ignore dup key] bit
239,[is unique] bit
240,[is padded] bit
241,[is disabled] bit
242,[is hypothetical] bit
243,[fill factor] int
244,[allow row locks] bit
245,[allow page locks] bit
246,[optimize for sequential key] bit
247,[has filter] bit
248,[filter definition] nvarchar(max)
249,[is primary key] bit
250,[is unique constraint] bit
251,[rowcount] bigint
252,[data_size] bigint
253,[data space id] int not null
254,[partition scheme] nvarchar(128)
255,[partition column] nvarchar(128)
256,[purpose.table id] as concat(purpose, ':', [table id]) persisted not null
257)
258
259create table [#SYS_constraints] (
260[purpose] nvarchar(10) not null
261,[server] nvarchar(128) not null
262,[db] nvarchar(128) not null
263,[table id] int not null
264,[name] nvarchar(128) not null
265,[column names] nvarchar(max)
266,[type] nvarchar(128)
267,[definition] nvarchar(max)
268,[definition_full] nvarchar(max)
269,[purpose.table id] as concat(purpose, ':', [table id]) persisted not null
270)
271
272create table [#SYS_modules] (
273[purpose] nvarchar(10) not null
274,[server] nvarchar(128) not null
275,[db] nvarchar(128) not null
276,[id] int not null
277,[schema] nvarchar(128) not null
278,[name] nvarchar(128) not null
279,[object type] nvarchar(2) not null
280,[is trg disabled] bit
281,[is encrypted] bit
282,[is binding] bit
283,[definition] nvarchar(max)
284,[type desc] nvarchar(128)
285,[parent id] int
286,[parent schema] nvarchar(128)
287,[parent name] nvarchar(128)
288,[schema.object] as ([schema] + '.' + [name]) persisted not null
289,[parent schema.object] as ([parent schema] + '.' + [parent name])
290,[purpose.id] as concat(purpose, ':', [id]) persisted not null
291)
292
293create table [#SYS_synonyms] (
294[purpose] nvarchar(10) not null
295,[server] nvarchar(128) not null
296,[db] nvarchar(128) not null
297,[id] int not null
298,[schema] nvarchar(128) not null
299,[name] nvarchar(128) not null
300,[base object name] nvarchar(2000)
301,[schema.object] as ([schema] + '.' + [name]) persisted not null
302,[purpose.id] as concat(purpose, ':', [id]) persisted not null
303)
304
305create table [#SYS_sequences] (
306[purpose] nvarchar(10) not null
307,[server] nvarchar(128) not null
308,[db] nvarchar(128) not null
309,[id] int not null
310,[schema] nvarchar(128) not null
311,[name] nvarchar(128) not null
312,[type] nvarchar(128)
313,[start value] bigint
314,[increment] bigint
315,[minimum value] bigint
316,[maximum value] bigint
317,[is cycling] bit
318,[is cached] bit
319,[cache size] int
320,[last used value] bigint
321,[schema.object] as ([schema] + '.' + [name]) persisted not null
322,[purpose.id] as concat(purpose, ':', [id]) persisted not null
323)
324
325create table [#SYS_partition_schemes] (
326[purpose] nvarchar(10) not null
327,[server] nvarchar(128) not null
328,[db] nvarchar(128) not null
329,[name] nvarchar(128) not null
330,[function id] int not null
331,[data space id] int not null
332,[definition] nvarchar(max) not null
333,[definition checksum] as checksum(upper(replace(replace(replace(replace([definition],char(32),''),char(9),''),char(10),''),char(13),''))) persisted not null
334,[purpose.name] as concat(purpose, ':', [name]) persisted not null
335)
336
337create table [#SYS_partition_functions] (
338[purpose] nvarchar(10) not null
339,[server] nvarchar(128) not null
340,[db] nvarchar(128) not null
341,[id] int not null
342,[name] nvarchar(128) not null
343,[data space id] int not null
344,[definition] nvarchar(max) not null
345,[definition checksum] as checksum(upper(replace(replace(replace(replace([definition],char(32),''),char(9),''),char(10),''),char(13),''))) persisted not null
346,[purpose.name] as concat(purpose, ':', [name]) persisted not null
347)
348
349create table [#SYS_partition_alter] (
350[type] nvarchar(128) not null
351,[name] nvarchar(128) not null
352,primary key ([type], [name])
353)
354
355declare cursMD cursor for
356select [name]
357from (values
358('schemas')
359,('tables')
360,('columns')
361,('objects')
362,('types')
363,('identity_columns')
364,('computed_columns')
365,('indexes')
366,('index_columns')
367,('default_constraints')
368,('check_constraints')
369,('foreign_keys')
370,('foreign_key_columns')
371,('synonyms')
372,('sequences')
373,('sql_modules')
374,('triggers')
375,('partitions')
376,('partition_functions')
377,('partition_schemes')
378,('partition_parameters')
379,('partition_range_values')
380,('data_spaces')
381,('destination_data_spaces')
382,('filegroups')
383,('allocation_units')
384) as sysTables([name])
385
386open cursMD
387fetch next from cursMD into @sysTable
388while @@fetch_status = 0
389begin
390set @query = '
391drop table if exists ' + @metadata_db + '..SRC_' + @sysTable + '
392select *
393into ' + @metadata_db + '..SRC_' + @sysTable + '
394from openrowset(
395''SQLNCLI''
396,N''Server=' + @source_server + ';Database=' + @db + ';Trusted_Connection=yes;''
397,''select * from ' + quotename(@db) + '.sys.' + @sysTable + ' with(nolock)'')
398'
399exec(@query)
400--print concat('--Получена ', @sysTable, ' (', @@rowcount, ')')
401fetch next from cursMD into @sysTable
402end
403close cursMD
404deallocate cursMD
405
406--схемы
407set @query = '
408use ' + quotename(@db) + '
409set tran isolation level read uncommitted
410select
411@purpose
412,@server
413,db_name()
414,s.schema_id as [object id]
415,quotename(s.name)
416from sys.schemas as s
417where
418s.schema_id > 4
419and s.schema_id < 1000
420'
421insert into [#SYS_schemas] ([purpose],[server],[db],[id],[name])
422exec sp_executesql
423@query
424,N'@server nvarchar(50), @purpose nvarchar(10)'
425,@server = @@servername,@purpose = @t_target
426
427set @query = replace(@query, 'sys.', @metadata_db + '..SRC_')
428
429insert into [#SYS_schemas] ([purpose],[server],[db],[id],[name])
430exec sp_executesql
431@query
432,N'@server nvarchar(50), @purpose nvarchar(10)'
433,@server = @source_server,@purpose = @t_source
434
435--схемы секционирования
436set @query = '
437use ' + quotename(@db) + '
438set tran isolation level read uncommitted
439select
440@purpose
441,@server
442,db_name()
443,ps.name
444,pf.function_id
445,ps.data_space_id
446,''create partition scheme '' + quotename(ps.[name]) + '' as partition '' + quotename(pf.[name]) + '' to ('' + stuff(fg.[name].value(''.'', ''nvarchar(max)''), 1, 1, '''') + '')'' as [definition]
447from
448sys.partition_schemes as ps
449inner join sys.partition_functions as pf
450on pf.function_id = ps.function_id
451cross apply (
452select '','' + quotename(/*fg.name*/''default'')
453from
454sys.data_spaces ds
455inner join sys.destination_data_spaces as dds
456on dds.partition_scheme_id = ds.data_space_id
457inner join sys.filegroups as fg
458on fg.data_space_id = dds.data_space_id
459where ps.data_space_id = ds.data_space_id
460order by dds.destination_id
461for xml path(''''), type
462) as fg([name])
463'
464
465insert into [#SYS_partition_schemes] ([purpose],[server],[db],[name],[function id],[data space id],[definition])
466exec sp_executesql
467@query
468,N'@server nvarchar(50), @purpose nvarchar(10)'
469,@server = @@servername,@purpose = @t_target
470
471set @query = replace(@query, 'sys.', @metadata_db + '..SRC_')
472
473insert into [#SYS_partition_schemes] ([purpose],[server],[db],[name],[function id],[data space id],[definition])
474exec sp_executesql
475@query
476,N'@server nvarchar(50), @purpose nvarchar(10)'
477,@server = @source_server,@purpose = @t_source
478
479--функции секционирования
480set @query = '
481use ' + quotename(@db) + '
482set tran isolation level read uncommitted
483select
484@purpose
485,@server
486,db_name()
487,pf.function_id
488,pf.[name]
489,ps.data_space_id
490,''create partition function '' + quotename(pf.[name]) + '' ('' + t.[name]
491+ isnull(''('' + case
492when t.[name] in (''varchar'', ''char'', ''varbinary'', ''binary'', ''nvarchar'', ''nchar'')
493then cast(iif(t.name like ''n%'', pp.max_length / 2, pp.max_length) as nvarchar(10))
494when t.[name] in (''datetime2'', ''time2'', ''datetimeoffset'')
495then cast(pp.scale as nvarchar(10))
496when t.[name] in (''decimal'', ''numeric'')
497then cast(pp.[precision] as nvarchar(10)) + '','' + cast(pp.scale as nvarchar(10))
498else null end + '')'', '''')
499+ '') '' + ''as range '' + iif(pf.boundary_value_on_right = 1, ''right'', ''left'') + '' for values (''
500+ stuff(rg.[value].value(''.'', ''nvarchar(max)''), 1, 1, '''')
501+ '')'' as [definition]
502from
503sys.partition_functions as pf
504inner join sys.partition_schemes as ps
505on pf.function_id = ps.function_id
506inner join sys.partition_parameters as pp
507on pp.function_id = pf.function_id
508inner join sys.types as t
509on t.user_type_id = pp.user_type_id
510cross apply (
511select
512'',''
513+ case
514when sql_variant_property(r.[value], ''basetype'') in (''char'', ''varchar'', ''nchar'', ''nvarchar'', ''uniqueidentifier'')
515then quotename(cast(r.[value] as nvarchar(4000)), '''''''')
516when sql_variant_property(r.[value], ''basetype'') in (''date'', ''datetime'', ''smalldatetime'', ''datetime2'', ''datetimeoffset'')
517then quotename(format(cast(r.[value] as datetime2), ''yyyy-MM-ddTHH:mm:ss.fffffff K''), '''''''')
518when sql_variant_property(r.[value], ''basetype'') = ''time''
519then quotename(format(cast(r.[value] as time), ''hh\:mm\:ss\.fffffff''),'''''''')
520when sql_variant_property(r.[value], ''basetype'') in (''binary'', ''varbinary'')
521then convert(nvarchar(4000), r.[value], 1)
522else cast(r.[value] as nvarchar(4000))
523end
524from sys.partition_range_values as r
525where pf.[function_id] = r.[function_id]
526order by r.boundary_id
527for xml path(''''), type
528) as rg([value])
529'
530
531insert into [#SYS_partition_functions] ([purpose],[server],[db],[id],[name],[data space id],[definition])
532exec sp_executesql
533@query
534,N'@server nvarchar(50), @purpose nvarchar(10)'
535,@server = @@servername,@purpose = @t_target
536
537set @query = replace(@query, 'sys.', @metadata_db + '..SRC_')
538
539insert into [#SYS_partition_functions] ([purpose],[server],[db],[id],[name],[data space id],[definition])
540exec sp_executesql
541@query
542,N'@server nvarchar(50), @purpose nvarchar(10)'
543,@server = @source_server,@purpose = @t_source
544
545--таблицы
546set @query = '
547use ' + quotename(@db) + '
548set tran isolation level read uncommitted
549select
550@purpose
551,@server
552,db_name()
553,t.object_id as [table id]
554,quotename(s.name)
555,quotename(t.name)
556,t.is_filetable
557,t.is_memory_optimized
558,concat(t.durability,'' '',quotename(t.durability_desc))
559,t.is_external
560,t.is_node
561,t.is_edge
562,0 --objectproperty(t.object_id,''isencrypted'')
563,0 --objectproperty(t.object_id,''tableisfake'')
564,0 --objectproperty(t.object_id,''tabletemporaltype'')
565,t.lock_escalation_desc
566from
567sys.tables as t
568inner join sys.schemas as s
569on s.schema_id = t.schema_id
570' + iif(@exclude_tables <> '', 'where not (' + @exclude_tables + ')', '')
571
572insert into [#SYS_tables] ([purpose],[server],[db],[id],[schema],[name],[is filetable],[is in-memory],[durability],[is external],[is node],[is edge],[is encrypted],[is fake],[is temporal],[lock escalation])
573exec sp_executesql
574@query
575,N'@server nvarchar(50), @purpose nvarchar(10)'
576,@server = @@servername,@purpose = @t_target
577
578set @query = replace(@query, 'sys.', @metadata_db + '..SRC_')
579
580insert into [#SYS_tables] ([purpose],[server],[db],[id],[schema],[name],[is filetable],[is in-memory],[durability],[is external],[is node],[is edge],[is encrypted],[is fake],[is temporal],[lock escalation])
581exec sp_executesql
582@query
583,N'@server nvarchar(50), @purpose nvarchar(10)'
584,@server = @source_server,@purpose = @t_source
585
586--колонки
587set @query = '
588use ' + quotename(@db) + '
589set tran isolation level read uncommitted
590select
591@purpose
592,@server
593,db_name()
594,c.object_id as [table id]
595,quotename(c.name)
596,row_number() over(partition by c.object_id order by c.column_id) as [ordinal position] --,columnproperty(c.object_id, c.name, ''ordinal'') as [ordinal position]
597,c.is_nullable
598,c.is_rowguidcol
599,c.is_identity
600,c.is_filestream
601,c.is_xml_document
602,c.is_sparse
603,c.is_column_set
604,c.is_hidden
605,c.is_masked
606,cast(ic.seed_value as bigint)
607,cast(ic.increment_value as bigint)
608,cast(ic.last_value as bigint)
609,c.is_computed
610,isnull(cc.[definition],'''')
611,cc.is_persisted
612,c.collation_name
613,t.name
614,isnull(''('' + case
615when c.is_computed = 1
616then null
617when t.[name] in (''varchar'', ''char'', ''varbinary'', ''binary'', ''nvarchar'', ''nchar'')
618then iif(c.max_length = -1, ''max'', cast(iif(t.name like ''n%'', c.max_length / 2, c.max_length) as nvarchar(10)))
619when t.[name] in (''datetime2'', ''time2'', ''datetimeoffset'')
620then cast(c.scale as nvarchar(10))
621when t.[name] in (''decimal'', ''numeric'')
622then cast(c.[precision] as nvarchar(10)) + '','' + cast(c.scale as nvarchar(10))
623else null end + '')'','''')
624,''('' + case
625when t.[name] in (''image'',''varbinary'',''binary''/*,timestamp*/) then ''0x0''
626when t.[name] in (''uniqueidentifier'') then ''''''00000000-0000-0000-0000-000000000000''''''
627when t.[name] in (''text'',''ntext'',''varchar'',''char'',''nvarchar'',''nchar'',''xml'') then ''''''''''''
628when t.[name] in (''tinyint'',''smallint'',''int'',''real'',''money'',''float'',''bit'',''decimal'',''numeric'',''smallmoney'',''bigint'') then ''0''
629when t.[name] in (''time'',''date'',''datetime2'',''datetimeoffset'',''smalldatetime'',''datetime'') then ''''''' + @min_year + '-01-01''''''
630else '''''''''''' end + '')''
631from
632sys.columns as c
633inner join sys.objects as o
634on c.object_id = o.object_id
635and o.is_ms_shipped = 0
636inner join sys.types as t
637on c.user_type_id = t.user_type_id
638left join sys.identity_columns as ic
639on c.[object_id] = ic.[object_id]
640and c.column_id = ic.column_id
641left join sys.computed_columns as cc
642on c.[object_id] = cc.[object_id]
643and c.column_id = cc.column_id
644'
645
646insert into [#SYS_columns] ([purpose],[server],[db],[table id],[name],[ordinal position],[is nullable],[is rowguidcol],[is identity],[is filestream],[is xml_document],[is sparse],[is column_set],[is hidden],[is masked],[seed value],[increment value],[last value],[is computed],[definition for computed],[is persisted],collation,[type name],[type size],[default for type])
647exec sp_executesql
648@query
649,N'@server nvarchar(50), @purpose nvarchar(10)'
650,@server = @@servername,@purpose = @t_target
651
652set @query = replace(@query, 'sys.', @metadata_db + '..SRC_')
653
654insert into [#SYS_columns] ([purpose],[server],[db],[table id],[name],[ordinal position],[is nullable],[is rowguidcol],[is identity],[is filestream],[is xml_document],[is sparse],[is column_set],[is hidden],[is masked],[seed value],[increment value],[last value],[is computed],[definition for computed],[is persisted],collation,[type name],[type size],[default for type])
655exec sp_executesql
656@query
657,N'@server nvarchar(50), @purpose nvarchar(10)'
658,@server = @source_server, @purpose = @t_source
659
660--индексы
661set @query = '
662use ' + quotename(@db) + '
663set tran isolation level read uncommitted
664select
665@purpose
666,@server
667,db_name()
668,i.object_id
669,quotename(i.name)
670,stuff(ic.[key].value(''/x[1]'',''nvarchar(max)''),1,1,'''')
671,isnull(stuff(ic2.[incl].value(''/x[1]'',''nvarchar(max)''),1,1,''''),'''')
672,lower(i.type_desc)
673,i.ignore_dup_key
674,i.is_unique
675,i.is_padded
676,i.is_disabled
677,i.is_hypothetical
678,iif(i.fill_factor = 0, 100, i.fill_factor)
679,i.allow_row_locks
680,i.allow_page_locks
681,i.optimize_for_sequential_key
682,i.has_filter
683,isnull(i.filter_definition,'''')
684,i.is_primary_key
685,i.is_unique_constraint
686,au.[rowcount]
687,au.[data_size]
688,i.data_space_id
689,ps.[partition scheme]
690,ps.[partition column]
691from
692sys.indexes as i
693inner join sys.objects as o
694on i.object_id = o.object_id
695and o.is_ms_shipped = 0
696cross apply (
697select
698'','' + quotename(c.name) + iif(ic.is_descending_key = 0, '' asc'', '' desc'')
699from
700sys.index_columns as ic
701inner join sys.columns as c
702on c.object_id = ic.object_id
703and ic.column_id = c.column_id
704where
705ic.object_id = i.object_id
706and ic.index_id = i.index_id
707and ic.is_included_column = 0
708order by
709ic.key_ordinal
710for xml path(''''),root(''x''),type
711) as ic([key])
712outer apply (
713select
714'','' + quotename(c.name)
715from
716sys.index_columns as ic
717inner join sys.columns as c
718on c.object_id = ic.object_id
719and ic.column_id = c.column_id
720where
721ic.object_id = i.object_id
722and ic.index_id = i.index_id
723and ic.is_included_column = 1
724order by
725ic.key_ordinal
726for xml path(''''),root(''x''),type
727) as ic2(incl)
728outer apply (
729select
730ps.[name] as [partition scheme]
731,c.[name] as [partition column]
732from
733sys.tables as t
734inner join sys.index_columns as ic
735on ic.[object_id] = i.[object_id]
736and ic.index_id = i.index_id
737and ic.partition_ordinal >= 1
738inner join sys.partition_schemes as ps
739on ps.data_space_id = i.data_space_id
740inner join sys.columns as c
741on t.[object_id] = c.[object_id]
742and ic.column_id = c.column_id
743where t.[object_id] = i.[object_id]
744) as ps
745left join (
746select
747p.object_id
748,p.index_id
749,sum(p.[rows]) as [rowcount]
750,sum(a.data_pages) * 8 as [data_size]
751from
752sys.partitions as p
753inner join sys.allocation_units as a
754on p.partition_id = a.container_id
755group by
756p.object_id
757,p.index_id
758) as au
759on au.object_id = i.object_id
760and au.index_id = i.index_id
761' + iif(@exclude_indexes <> '', 'where not (' + @exclude_indexes + ')', '')
762
763insert into [#SYS_indexes] ([purpose],[server],[db],[table id],[name],[key column names],[included column names],[index type],[ignore dup key],[is unique],[is padded],[is disabled],[is hypothetical],[fill factor],[allow row locks],[allow page locks],[optimize for sequential key],[has filter],[filter definition],[is primary key],[is unique constraint],[rowcount],[data_size],[data space id],[partition scheme],[partition column])
764exec sp_executesql
765@query
766,N'@server nvarchar(50), @purpose nvarchar(10)'
767,@server = @@servername,@purpose = @t_target
768
769set @query = replace(@query, 'sys.', @metadata_db + '..SRC_')
770
771insert into [#SYS_indexes] ([purpose],[server],[db],[table id],[name],[key column names],[included column names],[index type],[ignore dup key],[is unique],[is padded],[is disabled],[is hypothetical],[fill factor],[allow row locks],[allow page locks],[optimize for sequential key],[has filter],[filter definition],[is primary key],[is unique constraint],[rowcount],[data_size],[data space id],[partition scheme],[partition column])
772exec sp_executesql
773@query
774,N'@server nvarchar(50), @purpose nvarchar(10)'
775,@server = @source_server, @purpose = @t_source
776
777--ограничения
778set @query = '
779use ' + quotename(@db) + '
780set tran isolation level read uncommitted
781select
782@purpose
783,@server
784,db_name()
785,df.parent_object_id
786,quotename(df.[name])
787,quotename(c.name)
788,df.[type]
789,df.[definition]
790,''default '' + df.[definition] + '' for '' + quotename(c.name)
791from
792sys.default_constraints as df
793inner join sys.objects as o
794on o.object_id = df.parent_object_id
795inner join sys.columns as c
796on c.object_id = df.parent_object_id
797and c.column_id = df.parent_column_id
798where
799o.is_ms_shipped <> 1
800' + iif(@exclude_defaults <> '', 'and not (' + @exclude_defaults + ')', '') + '
801
802select
803@purpose
804,@server
805,db_name()
806,ch.parent_object_id
807,quotename(ch.[name])
808,''''
809,ch.[type]
810,ch.[definition]
811,''check '' + ch.[definition]
812from sys.check_constraints as ch
813
814select
815@purpose
816,@server
817,db_name()
818,fk.parent_object_id
819,quotename(fk.[name])
820,stuff(parent_fkc.[parent colunms].value(''/x[1]'',''nvarchar(max)''),1,1,'''')
821,fk.[type]
822,''''
823,'' foreign key ('' + stuff(parent_fkc.[parent colunms].value(''/x[1]'',''nvarchar(max)''),1,1,'''') + '') references '' + quotename(s.name) + ''.'' + quotename(t.name) collate Cyrillic_General_100_CI_AS
824+ '' ('' + stuff(fkc.[columns].value(''/x[1]'',''nvarchar(max)''),1,1,'''') + '') on update '' + lower(replace(fk.update_referential_action_desc,''_'','' '')) + '' on delete '' + lower(replace(fk.delete_referential_action_desc,''_'','' ''))
825from
826sys.foreign_keys as fk
827inner join sys.tables as t
828on t.object_id = fk.referenced_object_id
829inner join sys.schemas as s
830on s.schema_id = t.schema_id
831cross apply (
832select
833'','' + quotename(c.name)
834from
835sys.foreign_key_columns as fkc
836inner join sys.columns as c
837on c.object_id = fk.parent_object_id
838and c.column_id = fkc.parent_column_id
839where fkc.constraint_object_id = fk.object_id
840order by fkc.constraint_column_id
841for xml path(''''),root(''x''),type
842) parent_fkc([parent colunms])
843cross apply (
844select
845'','' + quotename(c.name)
846from
847sys.foreign_key_columns as fkc
848inner join sys.columns as c
849on c.object_id = fk.referenced_object_id
850and c.column_id = fkc.referenced_column_id
851where fkc.constraint_object_id = fk.object_id
852order by fkc.constraint_column_id
853for xml path(''''),root(''x''),type
854) fkc([columns])
855'
856
857insert into [#SYS_constraints] ([purpose],[server],[db],[table id],[name],[column names],[type],[definition],[definition_full])
858exec sp_executesql
859@query
860,N'@server nvarchar(50), @purpose nvarchar(10)'
861,@server = @@servername,@purpose = @t_target
862
863set @query = replace(@query, 'sys.', @metadata_db + '..SRC_')
864
865insert into [#SYS_constraints] ([purpose],[server],[db],[table id],[name],[column names],[type],[definition],[definition_full])
866exec sp_executesql
867@query
868,N'@server nvarchar(50), @purpose nvarchar(10)'
869,@server = @source_server, @purpose = @t_source
870
871--модули
872set @query = '
873use ' + quotename(@db) + '
874set tran isolation level read uncommitted
875select
876@purpose
877,@server
878,db_name()
879,o.object_id
880,quotename(s.name)
881,quotename(o.name)
882,o.type
883,isnull(t.is_disabled, 0) --objectproperty(o.object_id,''ExecIsTriggerDisabled'')
884,0 --objectproperty(o.object_id,''IsEncrypted'')
885,isnull(sm.is_schema_bound, 0) --objectproperty(o.object_id,''IsSchemaBound'')
886,sm.[definition] --object_definition(o.object_id)
887,lower(iif(charindex(''_'',o.type_desc) = 0, o.type_desc, right(o.type_desc, charindex(''_'',reverse(o.type_desc))-1)))
888,o.parent_object_id
889,quotename(s2.name)
890,quotename(o2.name)
891from
892sys.objects as o
893inner join sys.schemas as s
894on s.schema_id = o.schema_id
895left join sys.triggers as t
896on o.object_id = t.object_id
897left join sys.sql_modules as sm
898on sm.object_id = o.object_id
899left join sys.objects as o2
900on o.parent_object_id = o2.object_id
901left join sys.schemas as s2
902on s2.schema_id = o2.schema_id
903where
904o.type in (''FN'',''IF'',''P'',''V'',''TF'',''TR'')
905and o.is_ms_shipped = 0
906' + iif(@exclude_modules <> '', 'and not (' + @exclude_modules + ')', '')
907
908insert into [#SYS_modules] ([purpose],[server],[db],[id],[schema],[name],[object type],[is trg disabled],[is encrypted],[is binding],[definition],[type desc],[parent id],[parent schema],[parent name])
909exec sp_executesql
910@query
911,N'@server nvarchar(50), @purpose nvarchar(10)'
912,@server = @@servername,@purpose = @t_target
913
914set @query = replace(@query, 'sys.', @metadata_db + '..SRC_')
915
916insert into [#SYS_modules] ([purpose],[server],[db],[id],[schema],[name],[object type],[is trg disabled],[is encrypted],[is binding],[definition],[type desc],[parent id],[parent schema],[parent name])
917exec sp_executesql
918@query
919,N'@server nvarchar(50), @purpose nvarchar(10)'
920,@server = @source_server, @purpose = @t_source
921
922--синонимы
923set @query = '
924use ' + quotename(@db) + '
925set tran isolation level read uncommitted
926select
927@purpose
928,@server
929,db_name()
930,s.object_id
931,quotename(s2.name)
932,quotename(s.name)
933,s.base_object_name
934from
935sys.synonyms as s
936inner join sys.schemas as s2
937on s.schema_id = s2.schema_id
938'
939
940insert into [#SYS_synonyms] ([purpose],[server],[db],[id],[schema],[name],[base object name])
941exec sp_executesql
942@query
943,N'@server nvarchar(50), @purpose nvarchar(10)'
944,@server = @@servername,@purpose = @t_target
945
946set @query = replace(@query, 'sys.', @metadata_db + '..SRC_')
947
948
949insert into [#SYS_synonyms] ([purpose],[server],[db],[id],[schema],[name],[base object name])
950exec sp_executesql
951@query
952,N'@server nvarchar(50), @purpose nvarchar(10)'
953,@server = @source_server, @purpose = @t_source
954
955--последовательности
956set @query = '
957use ' + quotename(@db) + '
958set tran isolation level read uncommitted
959select
960@purpose
961,@server
962,db_name()
963,s.object_id
964,quotename(s2.name)
965,quotename(s.name)
966,iif(t.[name] in (''decimal'',''numeric''), concat(t.[name],''('',s.precision,'')''),t.[name])
967,cast(s.start_value as bigint)
968,cast(s.increment as bigint)
969,cast(s.minimum_value as bigint)
970,cast(s.maximum_value as bigint)
971,s.is_cycling
972,s.is_cached
973,s.cache_size
974,cast(s.last_used_value as bigint)
975from
976sys.sequences as s
977inner join sys.types as t
978on t.user_type_id = s.user_type_id
979inner join sys.schemas as s2
980on s.schema_id = s2.schema_id
981'
982
983insert into [#SYS_sequences] ([purpose],[server],[db],[id],[schema],[name],[type],[start value],increment,[minimum value],[maximum value],[is cycling],[is cached],[cache size],[last used value])
984exec sp_executesql
985@query
986,N'@server nvarchar(50), @purpose nvarchar(10)'
987,@server = @@servername,@purpose = @t_target
988
989set @query = replace(@query, 'sys.', @metadata_db + '..SRC_')
990
991insert into [#SYS_sequences] ([purpose],[server],[db],[id],[schema],[name],[type],[start value],increment,[minimum value],[maximum value],[is cycling],[is cached],[cache size],[last used value])
992exec sp_executesql
993@query
994,N'@server nvarchar(50), @purpose nvarchar(10)'
995,@server = @source_server, @purpose = @t_source
996
997end
998
999begin--сводная таблица
1000
1001drop table if exists [#PIVOT_TABLE]
1002
1003create table [#PIVOT_TABLE] (
1004[object desc] nvarchar(128)
1005,[parent object desc] nvarchar(128)
1006,[source server] nvarchar(128)
1007,[source db] nvarchar(128)
1008,[source parent object] nvarchar(128)
1009,[source object] nvarchar(128)
1010,[target server] nvarchar(128)
1011,[target db] nvarchar(128)
1012,[target parent object] nvarchar(128)
1013,[target object] nvarchar(128)
1014,[sql text] nvarchar(max)
1015,[action] nvarchar(10) index ix_act nonclustered
1016,[order] int
1017,[info] nvarchar(128)
1018)
1019
1020--схемы
1021insert into [#PIVOT_TABLE] ([object desc],[parent object desc],[source server],[source db],[source parent object],[source object],[target server],[target db],[target parent object],[target object],[sql text])
1022select
1023@t_schema
1024,null
1025,s.[server]
1026,s.db
1027,null
1028,s.[name]
1029,t.[server]
1030,t.db
1031,null
1032,t.[name]
1033,case
1034when s.[name] is null
1035then 'drop schema ' + t.[name]
1036when t.[name] is null
1037then 'create schema ' + s.[name]
1038else '' end
1039from
1040[#SYS_schemas] as s
1041full join [#SYS_schemas] as t
1042on s.purpose <> t.purpose
1043and s.[name] = t.[name]
1044where
1045(s.purpose = @t_source
1046or t.purpose = @t_target)
1047option (maxdop 8)
1048
1049--функции секционирования
1050insert into [#PIVOT_TABLE] ([object desc],[parent object desc],[source server],[source db],[source parent object],[source object],[target server],[target db],[target parent object],[target object],[sql text])
1051select
1052@t_partition_function
1053,null
1054,s.[server]
1055,s.db
1056,''
1057,s.[name]
1058,t.[server]
1059,t.db
1060,''
1061,t.[name]
1062,case
1063when s.[name] is null
1064then 'drop partition function ' + quotename(t.[name])
1065when t.[name] is null
1066then s.[definition]
1067else '' end
1068from
1069[#SYS_partition_functions] as s
1070full join [#SYS_partition_functions] as t
1071on s.purpose <> t.purpose
1072and t.[definition checksum] = s.[definition checksum]
1073where
1074(s.purpose = @t_source
1075or t.purpose = @t_target)
1076option (maxdop 8)
1077
1078insert into [#SYS_partition_alter] ([type], [name])
1079select distinct
1080@t_partition_function
1081,isnull(pt.[source object],pt.[target object])
1082from [#PIVOT_TABLE] as pt
1083where
1084pt.[object desc] = @t_partition_function
1085and pt.[sql text] <> ''
1086option (maxdop 8)
1087
1088--схемы секционирования
1089;with [partition_schemes] as (
1090select
1091ps.*
1092,iif(pa.[name] is not null, 1, 0) as [re-create]
1093from
1094[#SYS_partition_schemes] as ps
1095inner join [#SYS_partition_functions] as pf
1096on ps.[function id] = pf.id
1097and pf.purpose = ps.purpose
1098left join [#SYS_partition_alter] as pa
1099on pa.[name] = pf.[name]
1100and pa.[type] = @t_partition_function
1101)
1102insert into [#PIVOT_TABLE] ([object desc],[parent object desc],[source server],[source db],[source parent object],[source object],[target server],[target db],[target parent object],[target object],[sql text])
1103select
1104@t_partition_scheme
1105,null
1106,s.[server]
1107,s.db
1108,''
1109,s.[name]
1110,t.[server]
1111,t.db
1112,''
1113,t.[name]
1114,case
1115when s.[name] is null
1116then 'drop partition scheme ' + quotename(t.[name])
1117when t.[name] is null
1118then s.[definition]
1119else '' end
1120from
1121[partition_schemes] as s
1122full join [partition_schemes] as t
1123on s.purpose <> t.purpose
1124and t.[definition checksum] = s.[definition checksum]
1125and (t.[re-create] | s.[re-create] = 0)
1126where
1127(s.purpose = @t_source
1128or t.purpose = @t_target)
1129option (maxdop 8)
1130
1131insert into [#SYS_partition_alter] ([type], [name])
1132select distinct
1133@t_partition_scheme
1134,isnull(pt.[source object],pt.[target object])
1135from [#PIVOT_TABLE] as pt
1136where
1137pt.[object desc] = @t_partition_scheme
1138and pt.[sql text] <> ''
1139option (maxdop 8)
1140
1141--таблицы
1142insert into [#PIVOT_TABLE] ([object desc],[parent object desc],[source server],[source db],[source parent object],[source object],[target server],[target db],[target parent object],[target object],[sql text])
1143select
1144@t_table
1145,null
1146,s.[server]
1147,s.db
1148,null
1149,s.[schema.table]
1150,t.[server]
1151,t.db
1152,null
1153,t.[schema.table]
1154,case
1155when t.[schema.table] is null
1156then 'create table ' + s.[schema.table] + ' ( ' + stuff((
1157select
1158',' + c.[name] + ' ' + case
1159when c.[is computed] = 1
1160then ' as ' + c.[definition for computed] + iif(c.[is persisted] = 1,' persisted','')
1161when c.[is identity] = 1
1162then c.[type name] + c.[type size] + concat(' identity (',c.[seed value],',',c.[increment value],')')
1163else
1164c.[type name] + c.[type size] + ' ' + isnull(' collate ' + c.collation,'') + iif(c.[is nullable] = 0,' not','') + ' null'
1165end + @c_nl
1166from [#SYS_columns] as c
1167where
1168c.[purpose.table id] = s.[purpose.id]
1169order by c.[ordinal position]
1170for xml path(''),root('x'),type
1171).value('/x[1]','nvarchar(max)'),1,1,'') + ' )'
1172when s.[schema.table] is null
1173then 'drop table ' + t.[schema.table]
1174when s.[lock escalation] <> t.[lock escalation]
1175then 'alter table ' + t.[schema.table] + ' set (lock_escalation = ' + s.[lock escalation] + ')'
1176else '' end
1177from
1178( [#SYS_tables] as s
1179full join [#SYS_tables] as t
1180on t.purpose <> s.purpose
1181and t.[schema.table] = s.[schema.table] )
1182where
1183(s.purpose = @t_source
1184or t.purpose = @t_target)
1185option (maxdop 8)
1186
1187--колонки
1188;with [columns] as (
1189select
1190c.*
1191,t.[schema.table]
1192,concat(c.[type name],c.[type size],c.[is nullable]) as [type check]
1193,checksum(upper(replace(replace(replace(replace(c.[definition for computed],char(32),''),char(9),''),char(10),''),char(13),''))) as [computed check]
1194from
1195[#SYS_tables] as t
1196inner join [#SYS_tables] as t2
1197on t.purpose <> t2.purpose
1198and t2.[schema.table] = t.[schema.table]
1199inner join [#SYS_columns] as c
1200on c.[purpose.table id] = t.[purpose.id]
1201)
1202insert into [#PIVOT_TABLE] ([object desc],[parent object desc],[source server],[source db],[source parent object],[source object],[target server],[target db],[target parent object],[target object],[sql text], [order])
1203select
1204@t_column
1205,@t_table
1206,s.[server]
1207,s.db
1208,s.[schema.table]
1209,s.[name]
1210,t.[server]
1211,t.db
1212,t.[schema.table]
1213,t.[name]
1214,case
1215when s.[name] is null
1216then 'alter table ' + t.[schema.table] + ' drop column ' + t.[name]
1217when t.[name] is null
1218then 'alter table ' + s.[schema.table] + ' add ' + s.[name] + ' ' + case
1219when s.[is computed] = 1
1220then ' as ' + s.[definition for computed] + iif(s.[is persisted] = 1,' persisted','')
1221when s.[is identity] = 1
1222then s.[type name] + s.[type size] + concat(' identity (',s.[seed value],',',s.[increment value],')')
1223else
1224s.[type name] + s.[type size] + isnull(' collate ' + s.collation,'') + case
1225when s.[is nullable] = 1
1226then ' null'
1227when s.[is nullable] = 0 and s.[name] <> '[timestamp]'
1228then
1229' null ' + @c_nl
1230+ 'alter table ' + s.[schema.table] + ' disable trigger all' + @c_nl
1231+ 'exec ('' update ' + replace(s.[schema.table] + ' set ' + s.[name] + ' = ' + isnull(df.[definition],s.[default for type]),'''','''''') + ''')' + @c_nl
1232+ 'alter table ' + s.[schema.table] + ' alter column ' + s.[name] + ' ' + s.[type name] + s.[type size] + ' not null' +@c_nl
1233+ 'alter table ' + s.[schema.table] + ' enable trigger all'
1234else iif(s.[is nullable] = 0,' not','') + ' null' end end
1235when (s.[is identity] = 0 and t.[is identity] = 1) or (s.[is computed] = 0 and t.[is computed] = 1)
1236then
1237'alter table ' + t.[schema.table] + ' add [$temp_i_clmn] ' + s.[type name] + s.[type size] + isnull(' collate ' + s.collation,'') + ' null' + @c_nl
1238+ 'alter table ' + s.[schema.table] + ' disable trigger all' + @c_nl
1239+ 'exec ('' update ' + t.[schema.table] + ' set [$temp_i_clmn] = ' + t.[name] + ''')' + @c_nl
1240+ 'alter table ' + t.[schema.table] + ' drop column ' + t.[name] + @c_nl
1241+ 'exec sp_rename ''' + t.[schema.table] + '.[$temp_i_clmn]'',''' + parsename(s.[name],1) + ''', ''column''' + @c_nl
1242+ iif(s.[is nullable] = 0, 'alter table ' + t.[schema.table] + ' alter column ' + t.[name] + ' not null ' + @c_nl,'')
1243+ 'alter table ' + s.[schema.table] + ' enable trigger all'
1244when t.[name] <> '[timestamp]' and s.[type check] <> t.[type check]
1245then
1246iif(s.[is nullable] = 0 and t.[is nullable] = 1,'update ' + t.[schema.table] + ' set ' + t.[name] + ' = ' + isnull(df.[definition],s.[default for type]) + ' where ' + t.[name] + ' is null' + @c_nl,'')
1247+ 'alter table ' + t.[schema.table] + ' alter column ' + t.[name] + ' ' + s.[type name] + s.[type size] + ' ' + isnull(' collate ' + s.collation,'') + iif(s.[is nullable] = 0,' not','') + ' null'
1248else '' end
1249,isnull(s.[ordinal position], t.[ordinal position])
1250from
1251( [columns] as s
1252full join [columns] as t
1253on t.purpose <> s.purpose
1254and t.[schema.table] = s.[schema.table]
1255and t.[name] = s.[name]
1256and not (s.[is computed] = 1 and t.[is computed] = 0)
1257and not (s.[is identity] = 1 and t.[is identity] = 0)
1258and isnull(t.[increment value],0) = isnull(s.[increment value],0)
1259and t.[computed check] = s.[computed check] )
1260outer apply (
1261select c.[definition]
1262from [#SYS_constraints] as c
1263where
1264c.[purpose.table id] = s.[purpose.table id]
1265and c.purpose = @t_source
1266and c.[column names] = s.[name]
1267and c.[type] = 'D') as df
1268where
1269(s.purpose = @t_source
1270or t.purpose = @t_target)
1271
1272insert into [#SYS_columns_alter] ([schema.table], [name])
1273select distinct
1274isnull(pt.[source parent object],pt.[target parent object])
1275,isnull(pt.[source object],pt.[target object])
1276from [#PIVOT_TABLE] as pt
1277where
1278pt.[object desc] = @t_column
1279and pt.[sql text] <> ''
1280option (maxdop 8)
1281
1282--индексы
1283;with [indexes] as (
1284select
1285i.*
1286,t.[schema.table]
1287,upper(concat(i.[key column names], i.[included column names])) as [column check]
1288,concat(i.[allow row locks],i.[allow page locks],i.[optimize for sequential key],i.[ignore dup key]) as [options check]
1289,checksum(upper(replace(replace(replace(replace(i.[filter definition],char(32),''),char(9),''),char(10),''),char(13),''))) as [filter check]
1290,iif(ca.[count] > 0, 1, 0) | iif(pa.[name] is not null, 1, 0) as [re-create]
1291from
1292[#SYS_indexes] as i
1293inner join (
1294select
1295[schema.table]
1296,[purpose.id]
1297from [#SYS_tables] as t
1298union all
1299select
1300[schema.object]
1301,[purpose.id]
1302from [#SYS_modules] as t
1303where [object type] = 'V'
1304) as t
1305on i.[purpose.table id] = t.[purpose.id]
1306left join [#SYS_partition_alter] as pa
1307on i.[partition scheme] = pa.[name]
1308and pa.[type] = @t_partition_scheme
1309outer apply (
1310select count(*) as [count]
1311from [#SYS_columns_alter] as ca
1312where
1313ca.[schema.table] = t.[schema.table]
1314and (charindex(ca.[name],i.[key column names]) > 0 or charindex(ca.[name],i.[included column names]) > 0)
1315) as ca
1316where i.[index type] <> 'heap'
1317)
1318insert into [#PIVOT_TABLE] ([object desc],[parent object desc],[source server],[source db],[source parent object],[source object],[target server],[target db],[target parent object],[target object],[sql text],[info])
1319select
1320@t_index
1321,@t_table
1322,s.[server]
1323,s.db
1324,s.[schema.table]
1325,s.[name]
1326,t.[server]
1327,t.db
1328,t.[schema.table]
1329,t.[name]
1330,case
1331when t.[name] is null
1332then
1333iif(s.[is primary key] | s.[is unique constraint] = 1,
1334'alter table ' + s.[schema.table] + ' add constraint ' + s.[name] + iif(s.[is primary key] = 1, ' primary key ', ' unique ') + s.[index type] + ' ( ' + s.[key column names] + ' ) ',
1335'create ' + iif(s.[is unique] = 1,' unique ', '') + s.[index type] + ' index ' + s.[name] + ' on ' + s.[schema.table] + ' ( ' + s.[key column names] + ' ) '
1336+ iif(s.[included column names] = '', '', concat(' include (',s.[included column names],') '))
1337+ iif(s.[has filter] = 1,' where ' + s.[filter definition],''))
1338+ ' with (
1339fillfactor = ' + cast(s.[fill factor] as nvarchar(3)) + '
1340,allow_page_locks = ' + iif(s.[allow page locks] = 1, 'on', 'off') + '
1341,allow_row_locks = ' + iif(s.[allow row locks] = 1, 'on', 'off') + '
1342,ignore_dup_key = ' + iif(s.[ignore dup key] = 1, 'on', 'off') + '
1343,optimize_for_sequential_key = ' + iif(s.[optimize for sequential key] = 1, 'on', 'off') + ' ) '
1344+ ' on ' + iif(s.[partition scheme] is null, quotename(@target_filegroup), quotename(s.[partition scheme]) + '('+ quotename(s.[partition column]) + ')')
1345when s.[schema.table] is null
1346then
1347iif(t.[is primary key] | t.[is unique constraint] = 1,
1348'alter table ' + t.[schema.table] + ' drop constraint ' + t.[name] + @c_nl,
1349'drop index ' + t.[name] + ' on ' + t.[schema.table])
1350when t.[options check] <> s.[options check]
1351then 'alter index ' + t.[name] + ' on ' + t.[schema.table] + ' set (
1352optimize_for_sequential_key = ' + iif(s.[optimize for sequential key] = 1, 'on', 'off') +
1353iif(s.[is primary key] | s.[is unique constraint] = 1, '', ',ignore_dup_key = ' + iif(s.[ignore dup key] = 1, 'on', 'off')) + '
1354,allow_page_locks = ' + iif(s.[allow page locks] = 1, 'on', 'off') + '
1355,allow_row_locks = ' + iif(s.[allow row locks] = 1, 'on', 'off') + ' )'
1356else '' end
1357+ iif(s.[is disabled] = 1 and t.[is disabled] = 0, @c_nl + 'alter index ' + s.[name] + ' on ' + s.[schema.table] + ' disable', '')
1358,concat(isnull(s.[rowcount], t.[rowcount]), ' rows ≥', isnull(s.[data_size], t.[data_size]), ' KB')
1359from
1360[indexes] as s
1361full join [indexes] as t
1362on t.purpose <> s.purpose
1363and t.[schema.table] = s.[schema.table]
1364--and t.[name] = s.[name]
1365and t.[column check] = s.[column check]
1366and t.[is unique] = s.[is unique]
1367and t.[index type] = s.[index type]
1368--and t.[has filter] = s.[has filter]
1369and t.[filter check] = s.[filter check]
1370and (t.[re-create] | s.[re-create] = 0)
1371where
1372(s.purpose = @t_source
1373or t.purpose = @t_target)
1374option (maxdop 8)
1375
1376--ограничения
1377;with [constraints] as (
1378select
1379t.[schema.table]
1380,c.*
1381,iif(ca.[count] > 0, 1, 0) as [re-create]
1382from
1383[#SYS_tables] as t
1384inner join [#SYS_constraints] as c
1385on c.[purpose.table id] = t.[purpose.id]
1386outer apply (
1387select count(*) as [count]
1388from [#SYS_columns_alter] as ca
1389where
1390ca.[schema.table] = t.[schema.table]
1391and charindex(ca.[name],c.[column names]) > 0
1392) as ca
1393)
1394insert into [#PIVOT_TABLE] ([object desc],[parent object desc],[source server],[source db],[source parent object],[source object],[target server],[target db],[target parent object],[target object],[sql text])
1395select
1396@t_constraint
1397,@t_table
1398,s.[server]
1399,s.db
1400,s.[schema.table]
1401,s.[name]
1402,t.[server]
1403,t.db
1404,t.[schema.table]
1405,t.[name]
1406,case
1407when s.[name] is null
1408then 'alter table ' + t.[schema.table] + ' drop constraint ' + t.[name]
1409when t.[name] is null
1410then 'alter table ' + s.[schema.table] + ' with nocheck add ' + s.[definition_full]
1411else '' end
1412from
1413[constraints] as s
1414full join [constraints] as t
1415on t.purpose <> s.purpose
1416and t.[schema.table] = s.[schema.table]
1417and t.[definition_full] = s.[definition_full]
1418and (t.[re-create] | s.[re-create] = 0)
1419where
1420(s.purpose = @t_source
1421or t.purpose = @t_target)
1422option (maxdop 8)
1423
1424--модули
1425;with [modules] as (
1426select
1427m.*
1428,checksum(upper(replace(replace(replace(replace(m.[definition],char(32),''),char(9),''),char(10),''),char(13),''))) as [object check]
1429from [#SYS_modules] as m
1430where m.[is encrypted] = 0
1431)
1432insert into [#PIVOT_TABLE] ([object desc],[parent object desc],[source server],[source db],[source parent object],[source object],[target server],[target db],[target parent object],[target object],[sql text])
1433select
1434isnull(s.[type desc], t.[type desc])
1435,null
1436,s.[server]
1437,s.db
1438,null
1439,s.[schema.object]
1440,t.[server]
1441,t.db
1442,null
1443,t.[schema.object]
1444,case
1445when s.[schema.object] is not null and t.[schema.object] is null
1446then s.[definition]
1447when s.[schema.object] is null and t.[schema.object] is not null
1448then 'drop ' + t.[type desc] + t.[schema.object]
1449else '' end
1450+ iif(s.[object type] = 'TR' and (t.[schema.object] is null or s.[is trg disabled] <> t.[is trg disabled])
1451,iif(s.[is trg disabled] = 1
1452,@marker + 'disable trigger ' + s.[schema.object] + ' on ' + s.[parent schema.object] + @marker
1453,@marker + 'enable trigger ' + s.[schema.object] + ' on ' + s.[parent schema.object] + @marker)
1454,'')
1455from
1456[modules] as s
1457full join [modules] as t
1458on t.purpose <> s.purpose
1459and t.[object check] = s.[object check]
1460where
1461(s.purpose = @t_source
1462or t.purpose = @t_target)
1463option (maxdop 8)
1464
1465--синонимы
1466;with [synonyms] as (
1467select s.*
1468from [#SYS_synonyms] as s
1469)
1470insert into [#PIVOT_TABLE] ([object desc],[parent object desc],[source server],[source db],[source parent object],[source object],[target server],[target db],[target parent object],[target object],[sql text])
1471select
1472@t_synonym
1473,null
1474,s.[server]
1475,s.db
1476,null
1477,s.[schema.object]
1478,t.[server]
1479,t.db
1480,null
1481,t.[schema.object]
1482,case
1483when s.[schema.object] is not null and t.[schema.object] is null
1484then 'create synonym ' + s.[schema.object] + ' for ' + s.[base object name]
1485when s.[schema.object] is null and t.[schema.object] is not null
1486then 'drop synonym ' + t.[schema.object]
1487else '' end
1488from
1489[synonyms] as s
1490full join [synonyms] as t
1491on t.purpose <> s.purpose
1492and t.[schema.object] = s.[schema.object]
1493and t.[base object name] = s.[base object name]
1494where
1495(s.purpose = @t_source
1496or t.purpose = @t_target)
1497option (maxdop 8)
1498
1499--последовательности
1500;with [sequences] as (
1501select
1502s.*
1503,concat(s.[start value],s.increment,s.[minimum value],s.[maximum value],s.[is cycling],s.[is cached],s.[cache size]) as [options check]
1504from [#SYS_sequences] as s
1505)
1506insert into [#PIVOT_TABLE] ([object desc],[parent object desc],[source server],[source db],[source parent object],[source object],[target server],[target db],[target parent object],[target object],[sql text])
1507select
1508@t_sequence
1509,null
1510,s.[server]
1511,s.db
1512,null
1513,s.[schema.object]
1514,t.[server]
1515,t.db
1516,null
1517,t.[schema.object]
1518,case
1519when s.[schema.object] is not null and t.[schema.object] is null
1520then concat('create sequence ',s.[schema.object],' as ',s.[type],' start with ',s.[start value],' increment by ',s.increment,' minvalue ',s.[minimum value],' maxvalue '
1521,s.[maximum value],iif(s.[is cycling] = 1,'','no'),' cycle ',iif(s.[cache size] is null,' no cache',concat(' cache ',s.[cache size])))
1522when s.[schema.object] is null and t.[schema.object] is not null
1523then 'drop sequence ' + t.[schema.object]
1524else '' end
1525from
1526[sequences] as s
1527full join [sequences] as t
1528on t.purpose <> s.purpose
1529and t.[schema.object] = s.[schema.object]
1530and s.[options check] = t.[options check]
1531where
1532(s.purpose = @t_source
1533or t.purpose = @t_target)
1534
1535update [#PIVOT_TABLE] set
1536[action] = case
1537when [source object] is not null and [target object] is null and [sql text] <> ''
1538then @t_create
1539when [source object] is null and [target object] is not null and [sql text] <> ''
1540then @t_drop
1541when [source object] is not null and [target object] is not null and [sql text] <> ''
1542then @t_alter
1543else '' end
1544end
1545
1546insert into [#SCRIPT_TABLE] (db, current_step, step_desc, sql_text, object_desc)
1547select
1548@db
1549,row_number() over(order by
1550case
1551when pt.[object desc] in (@t_function, @t_procedure, @t_trigger) and pt.[action] = @t_drop then 1
1552when pt.[object desc] = @t_constraint and pt.[action] = @t_drop then 2
1553when pt.[object desc] = @t_index and pt.[action] = @t_drop then 3
1554when pt.[object desc] = @t_view and pt.[action] = @t_drop then 4
1555when pt.[object desc] = @t_column and pt.[action] = @t_drop then 5
1556when pt.[object desc] = @t_table and pt.[action] = @t_drop then 6
1557when pt.[object desc] = @t_partition_scheme and pt.[action] = @t_drop then 7
1558when pt.[object desc] = @t_partition_function and pt.[action] = @t_drop then 8
1559when pt.[object desc] = @t_schema and pt.[action] = @t_create then 9
1560when pt.[object desc] = @t_partition_function and pt.[action] = @t_create then 10
1561when pt.[object desc] = @t_partition_scheme and pt.[action] = @t_create then 11
1562when pt.[object desc] in (@t_column, @t_table, @t_constraint) then 12
1563when pt.[object desc] = @t_view and pt.[action] = @t_alter then 13
1564when pt.[object desc] = @t_view and pt.[action] = @t_create then 14
1565when pt.[object desc] = @t_index and pt.[action] = @t_alter then 15
1566when pt.[object desc] = @t_index and pt.[action] = @t_create then 16
1567when pt.[object desc] in (@t_function, @t_procedure, @t_trigger) and pt.[action] = @t_alter then 17
1568when pt.[object desc] in (@t_function, @t_procedure, @t_trigger) and pt.[action] = @t_create then 18
1569when pt.[object desc] = @t_synonym and pt.[action] = @t_drop then 19
1570when pt.[object desc] = @t_synonym and pt.[action] = @t_create then 20
1571when pt.[object desc] = @t_sequence and pt.[action] = @t_drop then 21
1572when pt.[object desc] = @t_sequence and pt.[action] = @t_create then 22
1573when pt.[object desc] = @t_schema and pt.[action] = @t_drop then 23
1574else 100 end
1575,isnull(isnull(pt.[source parent object],pt.[source object]),isnull(pt.[target parent object],pt.[target object]))
1576,case
1577when pt.[object desc] = @t_column and pt.[action] = @t_alter then 1
1578when pt.[object desc] = @t_column and pt.[action] = @t_create then 2
1579when pt.[object desc] = @t_table and pt.[action] = @t_alter then 3
1580when pt.[object desc] = @t_table and pt.[action] = @t_create then 4
1581when pt.[object desc] = @t_constraint and pt.[action] = @t_create then 5
1582else 100 end
1583,pt.[order]
1584) as current_step
1585,pt.[action] + ' ' + pt.[object desc] + ': ' + isnull(isnull(pt.[target parent object] + '.' + pt.[target object],pt.[target object]),isnull(pt.[source parent object] + '.' + pt.[source object],pt.[source object])) as step_desc
1586,pt.[sql text] as sql_text
1587,pt.[object desc]
1588from [#PIVOT_TABLE] as pt
1589where
1590pt.[action] <> ''
1591--ФИЛЬТР
1592option (maxdop 8)
1593
1594fetch next from cursDB into @source_server, @db, @target_filegroup
1595end
1596close cursDB
1597deallocate cursDB
1598
1599
1600
1601if not exists (select * from #SCRIPT_TABLE)
1602print 'НЕТ ОБЪЕКТОВ ДЛЯ ОБНОВЛЕНИЯ !'
1603else if @ops = 0
1604begin--только генерация скрипта
1605
1606exec ('
1607create or alter proc #PrintingLongText
1608@text nvarchar(max)
1609as
1610set nocount on
1611declare
1612@pos int
1613
1614set @text = replace(replace(@text, char(13), char(10)), char(10) + char(10), char(10))
1615
1616while (1=1)
1617begin
1618set @pos = charindex(char(10), @text)
1619
1620if (@pos = 0)
1621begin
1622print @text
1623break
1624end
1625else if (@pos > 4000)
1626begin
1627set @text = stuff(@text, charindex('','', @text, 3900), 1, '','' + char(10))
1628continue
1629end
1630
1631print left(@text, @pos - 1)
1632
1633set @text = substring(@text, @pos + 1, len(@text))
1634end
1635')
1636
1637print '--СКРИПТ СОЗДАН: ' + format(getdate(), 'dd MMMM yyyy HH:mm')
1638print 'set nocount on'
1639print 'if left(@@servername, 12) <> ''' + left(@@servername, 12) + ''' throw 50000, ''СКРИПТ ПРЕДНАЗНАЧЕН ДЛЯ ДРУГОГО СЕРВЕРА !'', 1'
1640
1641select @message = string_agg('--' + upper(db) + ' нет объектов для обновления', @c_nl) within group (order by l.db)
1642from #db_list as l
1643where
1644not exists (select * from #SCRIPT_TABLE as s where l.db = s.db)
1645and @@servername like '%' + l.trg_srv + '%'
1646
1647if @message is not null
1648print @message
1649
1650print 'if object_id(''tempdb..#toApply'',''U'') is null select current_step, db, cast('''' as nvarchar(max)) as result into #toApply from (values (null,null,null)'
1651print ''
1652print '--↓↓↓ УДАЛИТЬ ИЛИ ЗАКОММЕНТИРОВАТЬ НЕНУЖНЫЕ СТРОКИ НИЖЕ ↓↓↓'
1653
1654declare cursRW cursor for
1655select
1656current_step
1657,db
1658,step_desc
1659from #SCRIPT_TABLE
1660order by
1661db
1662,object_desc
1663,substring(step_desc, charindex(':', step_desc) + 1, len(step_desc))
1664,current_step
1665open cursRW
1666fetch next from cursRW into @current_step, @db, @step_desc
1667while @@fetch_status = 0
1668begin
1669set @step_desc = formatmessage('%-20s %s', trim(substring(@step_desc, 1, charindex(':', @step_desc))), trim(substring(@step_desc, charindex(':', @step_desc) + 1, len(@step_desc))))
1670
1671print formatmessage(',(%-4s,%-25s,%s)', @current_step, quotename(@db,''''), quotename(@step_desc,''''))
1672
1673fetch next from cursRW into @current_step, @db, @step_desc
1674end
1675close cursRW
1676deallocate cursRW
1677
1678print '--↑↑↑ УДАЛИТЬ ИЛИ ЗАКОММЕНТИРОВАТЬ НЕНУЖНЫЕ СТРОКИ ВЫШЕ ↑↑↑
1679
1680) as t(current_step, db, step_desc)
1681else
1682begin
1683select * from #toApply where len([result]) > 5 order by db, current_step
1684
1685;throw 50000, ''СКРИПТ УЖЕ ЗАПУСКАЛСЯ, СГЕНЕРИРУЙТЕ НОВЫЙ !'', 1
1686end
1687
1688declare
1689@result int
1690,@message nvarchar(max)
1691
1692exec @result = sys.sp_getapplock
1693@Resource = ''' + @applock_const + '''
1694,@LockMode = ''exclusive''
1695,@LockOwner = ''session''
1696,@LockTimeout = 0
1697,@DbPrincipal = ''' + @user + '''
1698
1699if @result < 0
1700begin
1701select @message = string_agg(request_session_id, '','')
1702from sys.dm_tran_locks (nolock)
1703where
1704resource_type = ''APPLICATION''
1705and request_owner_type = ''SESSION''
1706and resource_description like ''%' + @applock_const + '%''
1707
1708set @message = concat(''ЗАКРОЙТЕ СЕССИИ: '', @message, '' !'')
1709
1710;throw 50000, @message, 1
1711end
1712'
1713
1714declare cursPR cursor for
1715select
1716db
1717,current_step
1718,step_desc
1719,sql_text
1720from [#SCRIPT_TABLE]
1721order by
1722db
1723,current_step
1724
1725open cursPR
1726fetch next from cursPR into @db, @current_step, @step_desc, @sql_text
1727
1728while (@@fetch_status = 0)
1729begin
1730print '--ДЕЙСТВИЕ: ' + upper(@step_desc)
1731print 'if exists (select 1 from #toApply where db = ''' + @db + ''' and current_step = ' + @current_step + ' and result = '''') '
1732print 'begin'
1733print 'use ' + quotename(@db)
1734print 'begin try'
1735print 'exec ('''
1736
1737if @step_desc like 'create trigger%'
1738begin
1739set @sql_text2 = replace(substring(@sql_text, charindex(@marker, @sql_text), charindex(@marker, @sql_text, charindex(@marker, @sql_text) +3) - charindex(@marker, @sql_text) + len(@marker)), @marker, '')
1740set @sql_text = stuff(@sql_text, charindex(@marker, @sql_text), charindex(@marker, @sql_text, charindex(@marker, @sql_text) +3) - charindex(@marker, @sql_text) + len(@marker), '')
1741end
1742
1743set @sql_text = replace(@sql_text,'''','''''')
1744
1745if len(@sql_text) < 4000
1746print @sql_text
1747else
1748exec #PrintingLongText @sql_text
1749
1750print ''')'
1751
1752if @step_desc like 'create trigger%'
1753begin
1754print 'exec ('''
1755print @sql_text2
1756print ''')'
1757end
1758
1759print 'update #toApply set [result] = ''OK'' where db = ''' + @db + ''' and current_step = ' + @current_step
1760print 'end try'
1761print 'begin catch'
1762print 'update #toApply set [result] = error_message() where db = ''' + @db + ''' and current_step = ' + @current_step
1763print 'end catch'
1764print 'end' + @c_nl
1765
1766fetch next from cursPR into @db, @current_step, @step_desc, @sql_text
1767end
1768
1769close cursPR
1770deallocate cursPR
1771
1772print '
1773if exists (select * from #toApply where len([result]) > 5)
1774select * from #toApply where len([result]) > 5 order by db, current_step
1775else
1776select ''СКРИПТ ВЫПОЛНИЛСЯ БЕЗ ОШИБОК !'' '
1777
1778end
1779else if @ops = 0
1780begin--выполнение синхронизации метаданных
1781
1782print 'СТАРТ ВЫПОЛНЕНИЯ !'
1783
1784set @query = '
1785drop table if exists ' + @synch_result_tbl + '
1786create table ' + @synch_result_tbl + ' (
1787[db] sysname
1788,[step] int
1789,[desc] nvarchar(max)
1790,[error] nvarchar(max)
1791,[DTM] datetime default (getdate())
1792)
1793'
1794exec(@query)
1795
1796declare curs cursor for
1797select
1798db
1799,current_step
1800,step_desc
1801,sql_text
1802from [#SCRIPT_TABLE]
1803order by
1804db
1805,current_step
1806
1807open curs
1808fetch next from curs into @db, @current_step, @step_desc, @sql_text
1809
1810while (@@fetch_status = 0)
1811begin
1812begin try
1813
1814if @step_desc like 'create trigger%'
1815begin
1816set @sql_text2 = replace(substring(@sql_text, charindex(@marker, @sql_text), charindex(@marker, @sql_text, charindex(@marker, @sql_text) +3) - charindex(@marker, @sql_text) + len(@marker)), @marker, '')
1817set @sql_text = stuff(@sql_text, charindex(@marker, @sql_text), charindex(@marker, @sql_text, charindex(@marker, @sql_text) +3) - charindex(@marker, @sql_text) + len(@marker), '')
1818set @sql_text2 = 'use ' + quotename(@db) + ' exec(''' + @sql_text2 + ''')'
1819end
1820
1821set @sql_text = 'use ' + quotename(@db) + ' exec(''' + replace(@sql_text,'''','''''') + ''')'
1822
1823exec @sql_text
1824
1825if @step_desc like 'create trigger%'
1826exec (@sql_text2)
1827
1828set @result = 0
1829end try
1830begin catch
1831set @message = error_message()
1832set @query = '
1833insert into ' + @synch_result_tbl + ' ([db], [step], [desc], [error])
1834values (''' + @db + ''',''' + @current_step + ''',''' + @step_desc + ''',''' + @message + ''')'
1835exec (@query)
1836set @result = 1
1837end catch
1838
1839set @message = format(getdate(),'[HH:mm]') + ' [' + @current_step + '/' + cast(@@cursor_rows as varchar(10)) + '] ' + iif(@result = 0, '[OK] ', '[ERROR] ') + @step_desc
1840raiserror (@message, 10, 1) with nowait
1841
1842fetch next from curs into @db, @current_step, @step_desc, @sql_text
1843end
1844
1845close curs
1846deallocate curs
1847
1848set @query = '
1849if exists (select * from ' + @synch_result_tbl + ')
1850begin
1851print ''ВЫПОЛНЕНИЕ ЗАВЕРШИЛОСЬ С ОШИБКАМИ !''
1852select
1853[db] as [База данных]
1854,[step] as [Номер шага]
1855,[desc] as [Описание]
1856,[error] as [Текст ошибки]
1857from ' + @synch_result_tbl + '
1858end
1859else
1860print ''ВЫПОЛНЕНИЕ ЗАВЕРШИЛОСЬ БЕЗ ОШИБОК !''
1861'
1862exec (@query)
1863
1864end
1865