/*
To use this script-builder:
	1.	connect to target server - location of target database

	2.	write target database name in "USE DATABASE" statement
			script-builder expects source and target database names to be identical - modify created script if this is not correct

	3.	set required variables: sourceServer and targetServer

	4.	set optional variables as desired:
		a.	tablePatternExclude: will not remove and not copy data for tables where name starts with this pattern, default='' no tables are excluded
		b.	tablePatternDoNotCopy: will remove target data but not copy source for tables where name starts with this pattern, default='' all tables copied
		c.	writeToLapampa: writes job start/end/fail to laPampa, default=0 no laPampa functions scripted
		d.	serverTest: test to ensure running on sourceServer, default=1 test for sourceServer
		e.	scriptBigCopy: generates customizable script for copying large tables in small blocks, default=0

	5.	execute script-builder

	6.	copy all resulting lines to new query window

	7.	review script before executing: modify as needed...

can execute generated script, save for later use, modify to become stored procedure, use as sqlJob step, more...

*/

-- REQUIRED "USE DATABASE statement: set databaseName - basis for generated script:
USE SL2007
GO

/* if database is   ProductCompendium
	then have to delete from COM_AppUser and COM_DbUser twice: 2nd time immediately before filling */

SET NOCOUNT ON


	-- REQUIRED variables - MUST SET THESE VARIABLSE
	DECLARE @sourceServer NVARCHAR(100) = 'PRODDB',		-- set sourceServer from \ServerObjects\LinkedServers - data source
			@targetServer NVARCHAR(100) = 'SQLMI-BAGSPEZLISTEPRD-SQLINSTANCE.75FF9425AC13.DATABASE.WINDOWS.NET'		-- target server - where the copy MUST run



	-- optional variables - use carefully
	DECLARE @tablePatternExclude NVARCHAR(100) = NULL,		-- set tableName-Pattern NOT to delete and NOT to copy data - use VERY CAREFULLY!
			@tablePatternDoNotCopy NVARCHAR(100) = NULL,	-- set tableName-Pattern to delete but NOT copy data - use VERY CAREFULLY!
			@writeToLapampa BIT = 0,						-- if true will include logging in LaPampa
			@serverTest BIT = 1,							-- if true validates server
			@scriptBigCopy BIT = 01,							-- if true writes sql to copy big tables in small blocks
			@jobDbLocal BIT = 1								-- if false adds 'PRODUCTION_DATA' as linked server for executing job procs




	-- scripting variables - DO NOT CHANGE
	DECLARE @databaseName NVARCHAR(100) = DB_NAME(),	-- gets database name from "USE DATABASE" statement
			@s CHAR(4) = '    ',						-- spacer for indents (formatting)
			@jobSrvr NVARCHAR(100)						-- location of job db 
				= CASE WHEN (@jobDbLocal = 1) THEN N'' ELSE N'' END

	-- enclose dbName in []
	SET @databaseName = '[' + LTRIM(RTRIM(REPLACE(REPLACE(@databaseName, '[', ''), ']', ''))) + ']'

	-- table to hold all sql statements
	DECLARE @tbl TABLE (Tbl_PK INT IDENTITY (1, 1) NOT NULL, SqlString NVARCHAR(MAX) NOT NULL, NoTab BIT NULL)

	-- add USE DATABASE to sqlTable
	INSERT INTO @tbl (SqlString, NoTab) SELECT 'USE ' + @databaseName, 1
	INSERT INTO @tbl (SqlString, NoTab) SELECT 'GO', 1


/*
-------------------------------------------------------------------------------------------------------------------------------------
building stop/start temporal tables here
*/
	-- table for all temporal table details
	DECLARE @histTbl TABLE (DataTable NVARCHAR(256) NOT NULL, HistoryTable NVARCHAR(256) NOT NULL,
							SysVerCMD NVARCHAR(256) NOT NULL, CMD VARCHAR(10), SortNr INT NOT NULL,
							CmdNr INT, PRIMARY KEY (DataTable, SortNr, CmdNr))
	INSERT INTO @histTbl (DataTable, SortNr, HistoryTable, SysVerCMD, CMD, CmdNr)
	SELECT
		schema_name(t.schema_id) + '.' + t.name AS DataTable, sv.SortNr,
		schema_name(h.schema_id) + '.' + h.name AS HistoryTable,
		'ALTER TABLE ' + schema_name(t.schema_id) + '.' + t.name
		 + CASE WHEN (CmdNr = 1) THEN ' SET ( SYSTEM_VERSIONING = ' + sv.SysVer
			+ CASE WHEN (sv.SysVer = 'OFF') THEN '' ELSE ' ( HISTORY_TABLE = ' + schema_name(h.schema_id) + '.' + h.name + ' )' END + ' )'
			ELSE CASE WHEN (sv.SysVer = 'OFF') THEN ' DROP PERIOD FOR SYSTEM_TIME' ELSE ' ADD PERIOD FOR SYSTEM_TIME (ValidFromDt, ValidToDt)' END  END + ';' AS SysVerCMD,
		sv.SysVer AS CMD, CmdNr
	FROM sys.tables t
	LEFT OUTER JOIN sys.tables h ON t.history_table_id = h.object_id
	CROSS JOIN ( SELECT 'OFF' AS SysVer, 1 AS SortNr UNION SELECT 'ON' AS SysVer, 2 AS SortNr ) sv
	CROSS JOIN ( SELECT 1 AS CmdNr UNION SELECT 2 AS CmdNr ) sn
	WHERE t.temporal_type = 2

	-- temporal tables
	IF EXISTS ( SELECT * FROM @histTbl )
	  BEGIN
		INSERT INTO @tbl (SqlString) SELECT ''
		-- start separate section for temporal tables
		INSERT INTO @tbl (SqlString) SELECT '/* special section for TEMPORAL TABLES'
		-- stop temporal tables: SET SYSTEM_VERSIONING = OFF
		INSERT INTO @tbl (SqlString) SELECT '-- stop temporal tables: SET SYSTEM_VERSIONING = OFF'
		INSERT INTO @tbl (SqlString)
			SELECT SysVerCMD FROM @histTbl WHERE CMD = 'OFF'
			ORDER BY DataTable, CmdNr			
		-- close special section for temporal tables
		INSERT INTO @tbl (SqlString) SELECT 'GO'
		INSERT INTO @tbl (SqlString) SELECT '*/'
		INSERT INTO @tbl (SqlString) SELECT ''
	  END

/*
building stop/start temporal tables here
-------------------------------------------------------------------------------------------------------------------------------------
*/


	-- BEGIN
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString, NoTab) SELECT '  BEGIN', 1

	-- set nocount ON
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT 'SET NOCOUNT ON'
	INSERT INTO @tbl (SqlString) SELECT 'SET QUOTED_IDENTIFIER ON'
	
	-- job vars
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT '-- script vars'
	INSERT INTO @tbl (SqlString) SELECT 'DECLARE @min INT, @max INT, @step INT'


	IF (@scriptBigCopy = 1)
	  BEGIN
		INSERT INTO @tbl (SqlString) SELECT ''
		INSERT INTO @tbl (SqlString) SELECT ''
		INSERT INTO @tbl (SqlString) SELECT '-- copy very large table in small blocks...'
		INSERT INTO @tbl (SqlString) SELECT '/*'
		INSERT INTO @tbl (SqlString) SELECT @s + 'SET IDENTITY_INSERT [] ON'
		INSERT INTO @tbl (SqlString) SELECT @s + '-- get min/max/step values'
		INSERT INTO @tbl (SqlString) SELECT @s + 'SET @min = ( SELECT MIN([PK]) FROM  )'
		INSERT INTO @tbl (SqlString) SELECT @s + 'SET @max = ( SELECT MAX([PK]) FROM  )'
		INSERT INTO @tbl (SqlString) SELECT @s + 'SET @step = 2500'
		INSERT INTO @tbl (SqlString) SELECT @s + '-- for each min: insert records'
		INSERT INTO @tbl (SqlString) SELECT @s + 'WHILE @min <= @max'
		INSERT INTO @tbl (SqlString) SELECT @s + '  BEGIN'
		INSERT INTO @tbl (SqlString) SELECT @s + @s + 'INSERT INTO '
		INSERT INTO @tbl (SqlString) SELECT @s + @s + '()'
		INSERT INTO @tbl (SqlString) SELECT @s + @s + 'SELECT '
		INSERT INTO @tbl (SqlString) SELECT @s + @s + 'FROM '
		INSERT INTO @tbl (SqlString) SELECT @s + @s + 'WHERE [PK] BETWEEN @min AND @min + @step - 1'
		INSERT INTO @tbl (SqlString) SELECT @s + @s + '-- set next min'
		INSERT INTO @tbl (SqlString) SELECT @s + @s + 'SET @min = @min + @step'
		INSERT INTO @tbl (SqlString) SELECT @s + '  END'
		INSERT INTO @tbl (SqlString) SELECT @s + 'SET IDENTITY_INSERT [] OFF'
		INSERT INTO @tbl (SqlString) SELECT '*/'
	  END

	-- log job start
	IF (@writeToLapampa = 1)
	  BEGIN
		DECLARE @srcSrvr NVARCHAR(100) = @sourceServer--CASE WHEN (LEFT(@sourceServer, 
		DECLARE @trgtSrvr NVARCHAR(100) = @targetServer
		DECLARE @jobName NVARCHAR(100) = REPLACE(REPLACE(@databaseName, '[', ''), ']', '') + '__copy' + '_from__' + @srcSrvr + '__to__IntDB'-- + @trgtSrvr
		INSERT INTO @tbl (SqlString) SELECT ''
		INSERT INTO @tbl (SqlString) SELECT '-- laPampa JobName'
		INSERT INTO @tbl (SqlString) SELECT 'DECLARE @jobName NVARCHAR(100) = ''' + @jobName + ''''
		INSERT INTO @tbl (SqlString) SELECT ''
		INSERT INTO @tbl (SqlString) SELECT '-- log job start'
		INSERT INTO @tbl (SqlString) SELECT 'EXECUTE ' + @jobSrvr + 'JOB.dbo.sp_job_start @jobName, null, null, ''Started'''
	  END

	-- BEGIN TRY
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT 'BEGIN TRY'
	-- ensure running on specified server
	IF (@serverTest = 1)
	  BEGIN
		INSERT INTO @tbl (SqlString) SELECT ''
		INSERT INTO @tbl (SqlString) SELECT @s + '-- ensure run from ' + @targetServer
		INSERT INTO @tbl (SqlString) SELECT @s + 'IF NOT (@@SERVERNAME = ''' + @targetServer + ''')'
		INSERT INTO @tbl (SqlString) SELECT @s + @s + 'RAISERROR (''DATABASE SERVER NOT VALID! CANNOT RUN ON %s !!'', 16, 1, @@SERVERNAME)'
	  END

	-- ensure running on specified database
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT @s + '-- ensure run on database ' + @databaseName
	INSERT INTO @tbl (SqlString) SELECT @s + 'IF NOT (DB_NAME() = ''' + REPLACE(REPLACE(@databaseName, '[', ''), ']', '') + ''')'
	INSERT INTO @tbl (SqlString) SELECT @s + '  BEGIN'
	INSERT INTO @tbl (SqlString) SELECT @s + @s + 'DECLARE @db NVARCHAR(128) = DB_NAME()'
	INSERT INTO @tbl (SqlString) SELECT @s + @s + 'RAISERROR (''DATABASE NOT VALID! CANNOT RUN ON %s !!'', 16, 1, @db)'
	INSERT INTO @tbl (SqlString) SELECT @s + '  END'


	-- prep for data copy: disable triggers and constraints, stop temporal tables
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT @s + '-- prep for data copy: disable triggers and/or constraints here...'


	-- table to hold all PK-FK relations EXCEPT self-refernecing relations
	DECLARE @tableList TABLE (tl_PK INT IDENTITY(1, 1) NOT NULL, PkTable NVARCHAR(100), PkTableId INT, FkTable NVARCHAR(100), FkTableId INT)
		INSERT INTO @tableList
			(PkTable, PkTableId, FkTable, FkTableId)
			SELECT
				ISNULL(p.name, '')			AS PkTable,
				ISNULL(p.object_id, 0)		AS PkTableId,
				r.name						AS FkTable,
				r.object_id					AS FkTableId
			FROM sys.tables r
			LEFT OUTER JOIN sys.foreign_keys f
				ON r.object_id = f.parent_object_id
			LEFT OUTER JOIN sys.tables p
				ON  f.referenced_object_id = p.object_id
				AND (NOT ISNULL(p.object_id, 0) = r.object_id)

	-- table to hold all table names with relations hierarchy
	DECLARE @tableMap TABLE (tm_PK INT IDENTITY(1, 1) NOT NULL, TblSchema NVARCHAR(100), TableName NVARCHAR(200), TableId INT, RelationLevel INT, IsPK BIT, HasCLR BIT)
		INSERT INTO @tableMap
			(TblSchema, TableName, TableId, RelationLevel, IsPK, HasCLR)
			SELECT
				'['+ SCHEMA_NAME(t.schema_id) + ']' AS TblSchema,
				t.name AS TableName,
				object_id		AS TableId,
				0				AS RelationLevel,
				CASE WHEN name IN ( SELECT PkTable FROM @tableList ) THEN 1 ELSE 0 END
								AS IsPK,
				CASE
					WHEN EXISTS ( SELECT system_type_id FROM sys.columns c WHERE c.object_id = t.object_id AND system_type_id IN (240, 241) ) -- 240=CLR DataType, 241=XML
						THEN 1
					ELSE 0
				END				AS HasCLR
			FROM sys.tables t
			WHERE NOT (name IN ('sysdiagrams'))
			  AND NOT (name LIKE ISNULL(@tablePatternExclude, '#!#') + '%')

	-- varibles for processing
	DECLARE @relLevel INT = 0, @hasRels BIT = 1

	-- loop through all tables until no more relations are found OR reach max loop (to avoid endless looping)
	WHILE @hasRels = 1 AND @relLevel < 100
	  BEGIN
		-- update table map with all relations that exist at current level
		UPDATE @tableMap
			SET RelationLevel = RelationLevel + 1
			-- where table with FK is on or below current level
			WHERE TableId IN ( SELECT FkTableId FROM @tableMap tm
								INNER JOIN @tableList tl ON tm.TableId = tl.FkTableId
								WHERE RelationLevel <= @relLevel)
			  -- table with PK is on current level
			  AND TableId IN ( SELECT PkTableId FROM @tableMap tm
								INNER JOIN @tableList tl ON tm.TableId = tl.FkTableId
								WHERE RelationLevel = @relLevel)
		-- if no records found for current level then set exit variable
		IF @@ROWCOUNT = 0
		  BEGIN
			-- relations found at current level = FALSE
			SET @hasRels = 0
		  END

		-- move to next level
		SET @relLevel = @relLevel + 1
	  END

	-- table to hold all where clauses for referential integrety
	DECLARE @tableFKs TABLE (TableName NVARCHAR(100), FkNr INT, SqlText NVARCHAR(1000))
	INSERT INTO @tableFKs (TableName, FkNr, SqlText)
		SELECT FkTbl AS TableName, FkNr, Whr AS SqlText
		FROM
			( SELECT
					ROW_NUMBER() OVER(PARTITION BY ft.name ORDER BY fk.parent_column_id) AS FkNr,
					f.name			AS FkConstraint,
					CASE WHEN ((ROW_NUMBER() OVER(PARTITION BY ft.name ORDER BY fk.parent_column_id)) = 1) THEN 'WHERE ' ELSE '  AND ' END
					 + '[' + fc.name + '] IN ( SELECT [' + pc.name + '] FROM [' + ps.name + '].[' + pt.name + '] )'
									AS Whr,
					ft.name			AS FkTbl,
					fc.name			AS FkCol,
					fc.column_id	AS FkColId,
					pt.name			AS PkTbl,
					pc.name			AS PkCol,
					pc.column_id	AS PkColId
				FROM sys.tables ft
				INNER JOIN sys.foreign_key_columns fk
					ON ft.object_id = fk.parent_object_id
				INNER JOIN sys.foreign_keys f
					ON fk.constraint_object_id = f.object_id
				INNER JOIN sys.columns fc
					ON  fk.parent_object_id = fc.object_id
					AND fk.parent_column_id = fc.column_id
					AND fc.is_nullable = 0
				INNER JOIN sys.tables pt
					ON  fk.referenced_object_id = pt.object_id
					AND NOT (ft.name = pt.name) -- remove self-referencing foreign-keys
				INNER JOIN sys.schemas ps
					ON pt.schema_id = ps.schema_id
				INNER JOIN sys.columns pc
					ON  fk.referenced_object_id = pc.object_id
					AND fk.referenced_column_id = pc.column_id
			) fk

	-- start delete section
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT @s + '-- remove data from all tables'

	-- script all truncates
	INSERT INTO @tbl (SqlString)
		SELECT @s + SqlStr
		FROM
			(
				-- truncates...
				SELECT
					'TRUNCATE TABLE ' + tm.TblSchema + '.[' + TableName + ']'
											AS SqlStr,
					TableName				AS TableName,
					RelationLevel			AS RelationLevel,
					1						AS SqlOrder
				FROM @tableMap tm
				LEFT OUTER JOIN
					(
						SELECT
							object_id		AS TableId,
							MAX(CAST(is_identity AS INT))
											AS HasIdent
						FROM sys.columns
						GROUP BY object_id
					) ci
					ON tm.TableId = ci.TableId
				WHERE ISNULL(IsPK, 0) = 0
				-- truncates...
			) delSql
		ORDER BY RelationLevel ASC, TableName, SqlOrder

	-- script all deletes - with dbcc checkident when needed
	INSERT INTO @tbl (SqlString)
		SELECT @s + SqlStr
		FROM
			(
				-- delete from...
				SELECT
					'DELETE FROM ' + tm.TblSchema + '.[' + TableName + ']'
											AS SqlStr,
					'[' + TableName + ']'	AS TableName,
					RelationLevel			AS RelationLevel,
					2						AS SqlOrder
				FROM @tableMap tm
				LEFT OUTER JOIN
					(
						SELECT
							object_id		AS TableId,
							MAX(CAST(is_identity AS INT))
											AS HasIdent
						FROM sys.columns
						GROUP BY object_id
					) ci
					ON tm.TableId = ci.TableId
				WHERE ISNULL(IsPK, 0) = 1
				-- delete from...
			  UNION ALL
				-- dbcc checkident...
				SELECT
					CASE
						WHEN (ISNULL(HasIdent, 0) = 1 AND ISNULL(IsPK, 0) = 1)
							THEN 'DBCC CHECKIDENT (''' + TblSchema + '.' + TableName + ''', RESEED, 0) WITH NO_INFOMSGS'
						ELSE '-- Delete this line before executing script! --'
					END						AS SqlStr,
					'[' + TableName + ']'	AS TableName,
					RelationLevel			AS RelationLevel,
					3						AS SqlOrder
				FROM @tableMap tm
				LEFT OUTER JOIN
					(
						SELECT
							object_id		AS TableId,
							MAX(CAST(is_identity AS INT))
											AS HasIdent
						FROM sys.columns
						GROUP BY object_id
					) ci
					ON tm.TableId = ci.TableId
				WHERE ISNULL(IsPK, 0) = 1
				-- dbcc checkident...
			  UNION ALL
				-- blank line...
				SELECT
					''						AS SqlStr,
					'[' + TableName + ']'	AS TableName,
					RelationLevel			AS RelationLevel,
					1						AS SqlOrder
				FROM @tableMap tm
				WHERE ISNULL(IsPK, 0) = 1
				-- blank line...
			) delSql
		ORDER BY RelationLevel ASC, TableName, SqlOrder

	-- end delete section
	INSERT INTO @tbl (SqlString) SELECT @s + '-- remove data from all tables'


	-- start insert section
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT @s + '-- fill all tables from ' + @sourceServer


	-- vars for insert into table...
	DECLARE @tblSchema NVARCHAR(100), @tblName NVARCHAR(100), @colList NVARCHAR(MAX), @hasIdent BIT, @hasCLR BIT
	DECLARE @cur CURSOR


	-- insert into tables...
	DECLARE @curCount INT = 0
	SET @cur = CURSOR FAST_FORWARD FOR
		SELECT
			TblSchema, TblName, LEFT(ColumnList, LEN(ColumnList) -1) AS ColumnList, HasIdent, HasCLR
		FROM
			( SELECT TblSchema, '[' + t.name + ']' AS TblName, tm.RelationLevel AS TableOrder,
					( SELECT '[' + name + '],' 'data()' FROM sys.columns c
						WHERE t.object_id = c.object_id AND NOT (c.is_computed = 1) AND NOT (c.system_type_id = 189) /*not timestamp*/
						ORDER BY column_id FOR XML PATH('') ) AS ColumnList,
					ISNULL(( SELECT MAX(CAST(is_identity AS INT)) FROM sys.columns ci WHERE t.object_id = ci.object_id ), 0) AS HasIdent,
					ISNULL(HasCLR, 0) AS HasCLR
				FROM @tableMap tm
				INNER JOIN sys.tables t ON tm.TableId = t.object_id ) tc
		WHERE NOT (REPLACE(TblName, '[', '') LIKE (ISNULL(@tablePatternDoNotCopy, '#!#') + '%'))
		ORDER BY TableOrder DESC, TblName
	OPEN @cur
	FETCH NEXT FROM @cur INTO @tblSchema, @tblName, @colList, @hasIdent, @hasCLR
	WHILE @@FETCH_STATUS = 0
	  BEGIN
		-- increment cursor loop counter
		SET @curCount = @curCount + 1

		-- two blank lines between tables - except for first time
		IF (NOT (@curCount = 1))
		  BEGIN
			INSERT INTO @tbl (SqlString) SELECT ''
			INSERT INTO @tbl (SqlString) SELECT ''
		  END

		-- set table name
		INSERT INTO @tbl (SqlString) SELECT @s + '-- ' + @tblName
		-- set insIdent on
		IF @hasIdent = 1
		  BEGIN
			INSERT INTO @tbl (SqlString)
				SELECT @s + 'SET IDENTITY_INSERT ' + @tblSchema + '.' + @tblName + ' ON'
		  END

		-- set insert into table
		INSERT INTO @tbl (SqlString)
			SELECT @s + 'INSERT INTO ' + @tblSchema + '.' + @tblName

		-- set columns to insert
		INSERT INTO @tbl (SqlString)
			SELECT @s + @s + '(' + @colList + ')'

		-- set columns for select
		INSERT INTO @tbl (SqlString)
			SELECT @s + @s + 'SELECT ' + @colList

		-- if not HasCLR then use normal FROM statement else use pass-through query
		IF @hasCLR = 0
		  BEGIN
			-- does NOT use CLR type
			-- set From statement
			INSERT INTO @tbl (SqlString)
				SELECT @s + @s + 'FROM ' + @sourceServer + '.' + @databaseName + '.' + @tblSchema + '.' + @tblName
		  END
		ELSE
		  BEGIN
			-- uses CLR type
			-- set pass-through From statement
			INSERT INTO @tbl (SqlString)
				SELECT @s + @s + 'FROM OPENQUERY(' + @sourceServer + ', ''SELECT ' + @colList + ' FROM ' + @databaseName + '.' + @tblSchema + '.' + @tblName + ''')'
		  END

		-- has foreign-key
		IF EXISTS ( SELECT * FROM @tableFKs WHERE LTRIM(RTRIM(REPLACE(REPLACE(TableName, '[', ''), ']', ''))) =LTRIM(RTRIM(REPLACE(REPLACE( @tblName, '[', ''), ']', ''))) )
		  BEGIN
			INSERT INTO @tbl (SqlString)
				SELECT @s + @s + SqlText FROM @tableFKs
				WHERE LTRIM(RTRIM(REPLACE(REPLACE(TableName, '[', ''), ']', ''))) = LTRIM(RTRIM(REPLACE(REPLACE(@tblName, '[', ''), ']', '')))
				ORDER BY FkNr ASC
		  END

		-- set insIdent off
		IF @hasIdent = 1
		  BEGIN
			INSERT INTO @tbl (SqlString)
				SELECT @s + 'SET IDENTITY_INSERT ' + @tblSchema + '.' + @tblName + ' OFF'
		  END

		FETCH NEXT FROM @cur INTO @tblSchema, @tblName, @colList, @hasIdent, @hasCLR
	  END
	CLOSE @cur
	DEALLOCATE @cur


	-- end insert section
	INSERT INTO @tbl (SqlString) SELECT @s + '-- fill all tables from ' + @sourceServer


	-- cleanup for data copy: enable triggers and constraints, stop temporal tables
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT @s + '-- cleanup after data copy: enable triggers, constraints and/or temporal tables here...'

	-- temporal tables
	IF EXISTS ( SELECT * FROM @histTbl )
	  BEGIN
		-- spacing
		INSERT INTO @tbl (SqlString) SELECT ''
		INSERT INTO @tbl (SqlString) SELECT ''
		-- start temporal tables: SET SYSTEM_VERSIONING = ON
		INSERT INTO @tbl (SqlString) SELECT '-- start temporal tables: SET SYSTEM_VERSIONING = ON, ADD PERIOD FOR SYSTEM_TIME'
		INSERT INTO @tbl (SqlString)
			SELECT SysVerCMD FROM @histTbl WHERE CMD = 'ON'
			ORDER BY DataTable, CmdNr DESC
		-- set GO
		INSERT INTO @tbl (SqlString) SELECT 'GO'
	  END


	-- log job end - successful
	IF (@writeToLapampa = 1)
	  BEGIN
		INSERT INTO @tbl (SqlString) SELECT ''
		INSERT INTO @tbl (SqlString) SELECT ''
		INSERT INTO @tbl (SqlString) SELECT '    -- log job end - successful'
		INSERT INTO @tbl (SqlString) SELECT '    EXECUTE ' + @jobSrvr + 'JOB.dbo.sp_job_end @jobName, ''Finished successfully'''
	  END

	-- add END TRY, BEGIN/END CATCH & RetrhowError statements
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT 'END TRY'
	-- END TRY


	-- BEGIN CATCH
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT 'BEGIN CATCH'

	-- rethrow error
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT @s + '-- rethrow error'
	INSERT INTO @tbl (SqlString) SELECT @s + 'EXECUTE [master].dbo.sp_RethrowError'


	-- log error in laPampa
	IF (@writeToLapampa = 1)
	  BEGIN
		INSERT INTO @tbl (SqlString) SELECT ''
		INSERT INTO @tbl (SqlString) SELECT @s + '-- -- get error message'
		INSERT INTO @tbl (SqlString) SELECT @s + 'DECLARE @err VARCHAR(2000) = CAST(ERROR_MESSAGE() AS VARCHAR(2000))'
		INSERT INTO @tbl (SqlString) SELECT ''
		INSERT INTO @tbl (SqlString) SELECT @s + '-- -- log job failed'
		INSERT INTO @tbl (SqlString) SELECT @s + 'EXECUTE ' + @jobSrvr + 'JOB.dbo.sp_job_fail @jobName, @err'
	  END


	-- ensure identity insert is OFF for all tables
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT @s + '-- ensure that IdentityInsert is OFF for all tables'
	INSERT INTO @tbl (SqlString) SELECT @s + 'DECLARE @cur CURSOR, @sql NVARCHAR(100)'
	INSERT INTO @tbl (SqlString) SELECT @s + 'SET @cur = CURSOR FAST_FORWARD FOR'
	INSERT INTO @tbl (SqlString) SELECT @s + @s + 'SELECT ''SET IDENTITY_INSERT ['' + name + ''] OFF'''
	INSERT INTO @tbl (SqlString) SELECT @s + 'FROM sys.tables'
	INSERT INTO @tbl (SqlString) SELECT @s + 'WHERE OBJECTPROPERTY (OBJECT_ID(name),''TableHasIdentity'') = 1'
	INSERT INTO @tbl (SqlString) SELECT @s + 'OPEN @cur'
	INSERT INTO @tbl (SqlString) SELECT @s + 'FETCH NEXT FROM @cur INTO @sql'
	INSERT INTO @tbl (SqlString) SELECT @s + 'WHILE @@FETCH_STATUS = 0'
	INSERT INTO @tbl (SqlString) SELECT @s + '  BEGIN'
	INSERT INTO @tbl (SqlString) SELECT @s + @s + 'EXECUTE (@sql)'
	INSERT INTO @tbl (SqlString) SELECT @s + @s + 'FETCH NEXT FROM @cur INTO @sql'
	INSERT INTO @tbl (SqlString) SELECT @s + '  END'
	INSERT INTO @tbl (SqlString) SELECT @s + 'CLOSE @cur'
	INSERT INTO @tbl (SqlString) SELECT @s + 'DEALLOCATE @cur'


	-- cleanup for data copy: enable triggers and constraints, start temporal tables
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT @s + '-- cleanup after error: enable triggers, constraints and/or temporal tables here...'

	-- temporal tables
	IF EXISTS ( SELECT * FROM @histTbl )
	  BEGIN
		-- start temporal tables: SET SYSTEM_VERSIONING = ON
		INSERT INTO @tbl (SqlString) SELECT '-- start temporal tables: SET SYSTEM_VERSIONING = ON, ADD PERIOD FOR SYSTEM_TIME'
		INSERT INTO @tbl (SqlString)
			SELECT SysVerCMD FROM @histTbl WHERE CMD = 'ON'
			ORDER BY DataTable, CmdNr DESC
	  END


	-- end catch
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString) SELECT 'END CATCH'
	-- END CATCH

	-- END / GO
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString, NoTab) SELECT '  END', 1
	INSERT INTO @tbl (SqlString, NoTab) SELECT 'GO', 1


	-- temporal tables
	IF EXISTS ( SELECT * FROM @histTbl )
	  BEGIN
		INSERT INTO @tbl (SqlString) SELECT ''
		-- start separate section for temporal tables
		INSERT INTO @tbl (SqlString) SELECT '/* special section for TEMPORAL TABLES'
		-- start temporal tables: SET SYSTEM_VERSIONING = ON, ADD PERIOD FOR SYSTEM_TIME
		INSERT INTO @tbl (SqlString) SELECT '-- start temporal tables: SET SYSTEM_VERSIONING = ON, ADD PERIOD FOR SYSTEM_TIME'
		INSERT INTO @tbl (SqlString)
			SELECT SysVerCMD FROM @histTbl WHERE CMD = 'ON'
			ORDER BY DataTable, CmdNr DESC
		-- close special section for temporal tables
		INSERT INTO @tbl (SqlString) SELECT 'GO'
		INSERT INTO @tbl (SqlString) SELECT '*/'
		INSERT INTO @tbl (SqlString) SELECT ''
	  END


	-- lines for file save
	INSERT INTO @tbl (SqlString) SELECT ''
	INSERT INTO @tbl (SqlString, NoTab) SELECT '/*', 1
	INSERT INTO @tbl (SqlString, NoTab) SELECT 'DataCopy__' + REPLACE(REPLACE(@databaseName, '[', ''), ']', '') + '__from__' + @sourceServer, 1
	INSERT INTO @tbl (SqlString, NoTab) SELECT '*/', 1
	INSERT INTO @tbl (SqlString) SELECT ''


	-- remove lines to be deleted
	DELETE FROM @tbl WHERE SqlString = 'Delete this line before executing script!'

	-- return all SQL strings
	SELECT RTRIM(CASE WHEN (ISNULL(NoTab, 0) = 0) THEN '    ' ELSE '' END + SqlString) FROM @tbl
		WHERE NOT (SqlString LIKE '%-- Delete this line%')
		ORDER BY Tbl_PK

