CiAgICA8IS0tIExpbmtlZEluIC0tPgogICAgPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPgogICAgICAgIF9saW5rZWRpbl9wYXJ0bmVyX2lkID0gIjEyMzUwNzMiOwogICAgICAgIHdpbmRvdy5fbGlua2VkaW5fZGF0YV9wYXJ0bmVyX2lkcyA9IHdpbmRvdy5fbGlua2VkaW5fZGF0YV9wYXJ0bmVyX2lkcyB8fCBbXTsKICAgICAgICB3aW5kb3cuX2xpbmtlZGluX2RhdGFfcGFydG5lcl9pZHMucHVzaChfbGlua2VkaW5fcGFydG5lcl9pZCk7CiAgICA8L3NjcmlwdD48c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+CiAgICAgICAgKGZ1bmN0aW9uKCl7dmFyIHMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgic2NyaXB0IilbMF07CiAgICAgICAgICAgIHZhciBiID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7CiAgICAgICAgICAgIGIudHlwZSA9ICJ0ZXh0L2phdmFzY3JpcHQiO2IuYXN5bmMgPSB0cnVlOwogICAgICAgICAgICBiLnNyYyA9ICJodHRwczovL3NuYXAubGljZG4uY29tL2xpLmxtcy1hbmFseXRpY3MvaW5zaWdodC5taW4uanMiOwogICAgICAgICAgICBzLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGIsIHMpO30pKCk7CiAgICA8L3NjcmlwdD4KICAgIDxub3NjcmlwdD4KICAgICAgICA8aW1nIGhlaWdodD0iMSIgd2lkdGg9IjEiIHN0eWxlPSJkaXNwbGF5Om5vbmU7IiBhbHQ9IiIgc3JjPSJodHRwczovL3B4LmFkcy5saW5rZWRpbi5jb20vY29sbGVjdC8/cGlkPTEyMzUwNzMmZm10PWdpZiIgLz4KICAgIDwvbm9zY3JpcHQ+CiAgICA8IS0tIEVuZCBMaW5rZWRJbiAtLT4KICAgIA==
Generic filters
Exact matches only
Search in title
Search in excerpt
Search in content

Kopieren mit Prozeduren

Bei einer Ablösung des ERP-Systems oder bei einer Übertragung von Daten einer produktiven Datenbank auf eine Testdatenbank kann es notwendig sein, dass viele Tabellen, Prozeduren, Berechtigungen und Synonyme von einer Datenbank in eine andere übertragen werden müssen. Dieser Blog beschreibt, wie man diese Übertragung mit Hilfe von Prozeduren schnell und unkompliziert gestaltet.

Häufig werden Daten aus Vorsystemen in eine SQL-Server-Datenbank importiert, die als Grundlage für das Modellieren in DeltaMaster dient. Ändert sich das Vorsystem, steht man vor der Aufgabe, die Importdatenbank und Importprozesse auf der SQL-Server-Datenbank anzupassen. Manchmal sind die neuen, zu importierenden Tabellen dabei so stark verändert, dass es unverhältnismäßig wäre, sie anzupassen. In diesem Fall wird man eine neue Importdatenbank aufsetzen müssen.

Die neuen Importtabellen werden zum Beispiel per SSIS in die neue Datenbank importiert. Diese Methodik haben wir unter anderem in einem Beitrag über die dynamische Replikation von Datenbankobjekten beschrieben. Oft gibt es aber zusätzlich zu den importierten Tabellen manuelle Eingabetabellen, welche für das Modell erforderlich sind, aber nicht aus dem Vorsystem importiert werden können. Das können beispielsweise Mapping-Tabellen sein. Entweder belässt man sie auf der alten Importdatenbank und nutzt diese als „Eingabedatenbank“ weiter oder man muss diese Tabellen inklusive der erforderlichen Eingabeprozeduren und Berechtigungen auf die neue Datenbank übertragen. Letzteres kann mit folgenden Prozeduren ausgeführt werden:

  • P_APP_Update_Entry_Tables
  • P_APP_Copy_Procedures
  • P_APP_Copy_Permissions

Nachfolgend beschreiben wir die drei Varianten kurz. Die Prozeduren selbst sind im Anhang angefügt. Die aufgeführten Prozeduren verwenden die Funktion F_BC_Clean_ObjName(). Wenn auf der Datenbank, auf der die jeweilige Prozedur ausgeführt werden soll, kein Delta-Master ETL Modell existiert, ist diese Funktion möglicherweise noch nicht vorhanden. Sollte das der Fall sein, muss diese Funktion auf den entsprechenden Datenbanken zunächst erstellt werden. Sie ist deshalb ebenfalls im Anhang zu finden.

P_APP_Copy_Entry_Tables

Ausgehend davon, dass Eingabetabellen immer mit dem Präfix „T_S“ beginnen, sucht die Prozedur P_APP_Copy_Entry_Tables nach Tabellen, welche mit „T_S“ in der Quelldatenbank beginnen und ersetzt oder erstellt diese in der Zieldatenbank. Sie kann auch dafür verwendet werden, Eingabetabellen von einer produktiven Datenbank auf eine Testumgebung zu kopieren, um die Eingaben nicht doppelt vornehmen zu müssen und die Eingabetabellen trotzdem mit aktuellem Inhalt auf der Testdatenbank verfügbar zu haben.

Die gefundenen Tabellen werden jeweils gelöscht und danach neu erstellt und befüllt. Damit ist gewährleistet, dass Änderungen an der Struktur der jeweiligen Tabellen automatisch mit übernommen werden.
Zum Löschen der Tabellen wird der SQL-Befehl „DROP <table> IF EXISTS“ verwendet. Diese Syntax ist ab SQL-Server 2016 verfügbar.

Soll die Prozedur auf Datenbanken mit niedrigerer Version eingesetzt werden, ist die Zeile

SET @SQL = 'DROP TABLE IF EXISTS ' + @TargetDB + '.' + @TargetSchema + '.' + @tabname

durch

SET @SQL = 'IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_CATALOG = ''' + @TargetDB + ''' AND TABLE_SCHEMA = ''' + @TargetSchema + ''' AND TABLE_NAME = ''' + @tabname + ''')
DROP TABLE ' + @TargetDB + '.' + @TargetSchema + '.' + @tabname 

zu ersetzen.

Innerhalb der Prozedur wird geprüft, ob die Parameter Ziel- und Quelldatenbank nicht leer sind und das angegebene Datenbankschema auf der Zieldatenbank existiert.

P_APP_Copy_Procedures

Die Prozedur erstellt die für die Eingabetabellen erforderlichen P_Insert-, P_Update- und P_Delete-Prozeduren auf der Zieldatenbank, wenn diese dort nicht existieren. Dafür werden die entsprechenden Prozeduren aus einer Quelldatenbank gelesen und nach Prüfung, ob diese auf der Zieldatenbank noch nicht existieren, auf der Zieldatenbank erstellt. Vorhandene Prozeduren werden nicht überschrieben.

Innerhalb der Prozedur wird geprüft, ob der Parameter Quelldatenbank nicht leer ist und das angegebene Datenbankschema auf der Zieldatenbank existiert.

Es ist wichtig zu wissen, dass Prozeduren nicht datenbankübergreifend erstellt werden können. Daher ist die Zieldatenbank kein Parameter der Prozedur und die Prozedur muss auf der Zieldatenbank ausgeführt werden.

P_APP_Copy_Permissions

Für das Ausführen der P_Insert-, P_Update- und P_Delete- Prozeduren sind Berechtigungen für die Anwender nötig, welche die Eingaben ausführen sollen. Diese Berechtigungen können ebenfalls mit einer Prozedur von der Quelldatenbank zur Zieldatenbank kopiert werden.

Innerhalb der Prozedur wird geprüft, ob die Parameter Ziel- und Quelldatenbank nicht leer sind und das angegebene Datenbankschema auf der Zieldatenbank existiert.

Das SQL-Statement, welches zum Ermitteln der Berechtigungen verwendet wird, soll hier näher erläutert werden.

SELECT 
	o.name as objectname,
	USER_NAME(p.grantee_principal_id),
	p.permission_name   
FROM .sys.database_permissions p (NOLOCK)
INNER JOIN .sys.objects o (NOLOCK)
	ON p.major_id = o.object_id
INNER JOIN .sys.schemas s
	ON o.schema_id = s.schema_id
WHERE p.class = 1									
AND s.name = 	
AND o.type in ('P','U','V')
AND (o.name LIKE '%V_S%' OR o.name LIKE '%T_S%')	
AND o.name NOT LIKE '%Model%'
AND o.name NOT LIKE '%SYS%'
AND o.name NOT LIKE 'T_S_TRL%'
AND o.name NOT LIKE 'V_S_CPA%'
AND EXISTS(SELECT * FROM .sys.objects (NOLOCK) sso WHERE sso.name = o.name)
AND EXISTS(SELECT * FROM .sys.database_principals dbp WHERE dbp.name = USER_NAME(p.grantee_principal_id))
AND USER_NAME(grantee_principal_id) <> SYSTEM_USER	
ORDER BY o.name, USER_NAME(p.grantee_principal_id), p.permission_name

Es werden der Objektname, der Name des berechtigten Benutzers oder der berechtigten Rolle sowie die Art der Berechtigung aus der Quelldatenbank mit dem SELECT-Statement ermittelt.

Dabei werden in der WHERE-Bedingung nur Objekte (p.class = 1) der Objekttypen Prozedur, Tabelle oder Sicht berücksichtigt (o.type in ('P','U','V')), welche ein „V_S“ oder „T_S“,  im Namen enthalten (o.name LIKE '%V_S%' OR o.name LIKE '%T_S%').

Die Berechtigungen nur für die mit der Prozedur „P_APP_Copy_Procedures“ zuvor erstellten Prozeduren zu ermitteln und zu setzen ist oft nicht ausreichend – meist müssen auch Berechtigungen für die mit diesen Prozeduren verknüpften Sichten und Tabellen gesetzt werden. Daher werden auch die entsprechenden Berechtigungen der Sichten und Tabellen mit ermittelt.

Es werden nur Objekte selektiert, welche nicht „SYS“, „Model“, „T_S_TRL“ oder „V_S_CPA%“ im Namen enthalten, da diese von DeltaMaster ETL erstellt und berechtigt werden.

Der eigene User wird ebenfalls ausgeschlossen (USER_NAME(grantee_principal_id) <> SYSTEM_USER), da davon auszugehen ist, dass man selbst die erforderlichen Berechtigungen besitzt. Ebenfalls wird geprüft, ob das zu berechtigende Objekt auf der Zieldatenbank existiert (EXISTS(SELECT * FROM .sys.objects (NOLOCK) sso WHERE sso.name = o.name)) sowie ob der zu berechtigende Anwender oder die zu berechtigende Rolle auf der Zieldatenbank vorhanden ist (EXISTS(SELECT * FROM .sys.database_principals dbp WHERE dbp.name = USER_NAME(p.grantee_principal_id))).

Es ist nicht relevant, ob eine entsprechende Berechtigung auf der Zieldatenbank bereits existiert. Ist dies der Fall, wird die Berechtigung nicht mehrfach angelegt und es wird auch keine Fehlermeldung generiert.

Da bei diesen Selektionsbedingungen auch modellspezifische Prozeduren wie beispielsweise „P_DIM_01_01_Year_01_V_S_Periode“ mit ermittelt werden, wenn diese bereits auf der Zieldatenbank existieren, würden die Berechtigungen der Quelldatenbank für diese Objekte auf die entsprechenden Objekte der Zieldatenbank übertragen. Soll dies nicht erfolgen, ist die WHERE-Bedingung anzupassen.

Zusatzprozedur: P_APP_Copy_Synonyms

Auch Synonyme lassen sich problemlos von einer Datenbank auf eine andere kopieren.

Als kleiner Zusatz zu diesem Artikel ist eine entsprechende Prozedur angehängt. Dabei ist zu beachten, dass beim Erstellen von Synonymen keine Datenbankschemata verwendet werden. Besteht bereits ein Synonym gleichen Namens auf der Zieldatenbank, wird dieses nicht neu angelegt. Die Definition der Synonyme wird nicht verglichen. Es wird auch nicht geprüft, ob das Objekt, auf welches das Synonym referenziert, tatsächlich existiert.

Alle Prozeduren im Überblick

P_APP_Copy_Entry_Tables
CREATE PROC [dbo].[P_APP_Update_Entry_Tables] (@TargetSchema varchar(50) = 'dbo', @SourceSchema varchar(50) = 'dbo',  @TargetDB varchar(128)= NULL,  @SourceDB varchar(128) = NULL)
AS

	SET NOCOUNT ON

	DECLARE @SQL nvarchar(4000)
	DECLARE @tabname varchar(1000)
	DECLARE @ParamDef nvarchar(1000)
	DECLARE @schema_id nvarchar(20)

	IF LEN(LTRIM(RTRIM(@TargetSchema))) = 0
	SET @TargetSchema = 'dbo'

	IF LEN(LTRIM(RTRIM(@SourceSchema))) = 0
	SET @SourceSchema = 'dbo'

	SET @SQL = N'IF EXISTS(SELECT * FROM ' + @TargetDB + '.sys.schemas s WHERE s.name = ''' + @TargetSchema + ''') SET @schemaOUT = 1 ELSE SET @schemaOUT = 0'
	SET @ParamDef = N'@schemaOUT nvarchar(20) OUTPUT'

	EXEC dbo.sp_executesql @SQL, @ParamDef, @schemaOUT = @schema_id OUTPUT

	IF LEN(ISNULL(@SourceDB,'')) = 0 OR 
	LEN(ISNULL(@TargetDB,'')) = 0 OR
	@schema_id = 0
	BEGIN
		PRINT 'Update_Entry_Tables
		The procedure will search for entry tables beginning with T_S in a Source-database and replaces or create them in a Targetdatase.
		Please make sure that the specified schema exists on the target database. 
		For SQL Server 2016 and up.
	
		Parameters:
		@TargetSchema - Schema of Targetdatabse tables
		@SourceSchema - Schema of Sourcedatabase tables
		@TargetDB     - Name of Targetdatabase
		@SourceDB     - Name of Sourcedatabase
	
		Example:
		EXEC dbo.P_APP_Update_Entry_Tables @TargetDB = ''Chair_Test'', @SourceDB = ''Chair_Prod'' - Delete, create and fill all tables beginning with T_S on the Targetdata-base that are available on the Sourcedatabase. Both databases are on the same currently selected server and have the schema dbo.
	 
		'
	END
	ELSE
	BEGIN
		-- Database names in brackets
		SET @TargetDB = dbo.F_BC_Clean_ObjName(@TargetDB, 1, 0)
		SET @SourceDB = dbo.F_BC_Clean_ObjName(@SourceDB, 1, 0)
		
		-- Tabellencursor
		-- It is assumed that tables for manual entry always start with T_S_.
		-- The T_S_TRL tables are excluded, since they are created and filled by DeltaMaster ETL.

		SET @SQL = '
		DECLARE Tab_cursor CURSOR FOR
		SELECT 
			s.name
		FROM '
		+ @SourceDB + '.sys.objects s (NOLOCK)
		WHERE 
			s.type = ''U''
			AND s.name LIKE ''T_S[_]%''
			AND s.name NOT LIKE ''T_S_TRL%''
			AND s.schema_id = (SELECT sc.schema_id FROM ' + @SourceDB + '.sys.schemas sc (NOLOCK) WHERE sc.name = ''' + @SourceSchema + ''')'
	
		--PRINT @SQL

		EXEC sp_executesql @SQL

		OPEN Tab_cursor

		FETCH NEXT FROM Tab_cursor INTO @tabname
		WHILE @@FETCH_STATUS = 0
			BEGIN
				-- Delete table on Targetdatabase if exists
				-- Create and fill table from Sourcedatabase
				-- this ensures that changes to the table structure (columns) and content are fully adopted
				SET @SQL = 'DROP TABLE IF EXISTS ' + @TargetDB + '.' + @TargetSchema + '.' + @tabname
				--PRINT (@SQL)
				EXEC (@SQL)

				SET @SQL = 'SELECT * INTO ' + @TargetDB + '.' + @TargetSchema + '.' + @tabname + ' FROM ' + @SourceDB + '.' + @SourceSchema + '.' + @tabname
				--PRINT(@SQL)
				EXEC( @SQL)

			FETCH NEXT FROM Tab_cursor INTO @Tabname
			END
		CLOSE Tab_cursor
		DEALLOCATE Tab_cursor
	END
P_APP_Copy_Procedures
CREATE PROC [dbo].[P_APP_Copy_Procedures] (@TargetSchema varchar(50) = 'dbo', @SourceSchema varchar(50) = 'dbo',  @SourceDB varchar(128) = NULL)
AS

	SET NOCOUNT ON

	DECLARE @SQL nvarchar(4000)
	DECLARE @TargetDB varchar(128)
	DECLARE @text varchar(max)
	DECLARE @ParamDef nvarchar(1000)
	DECLARE @schema_id nvarchar(20)

	IF LEN(LTRIM(RTRIM(@TargetSchema))) = 0
	SET @TargetSchema = 'dbo'

	IF LEN(LTRIM(RTRIM(@SourceSchema))) = 0
	SET @SourceSchema = 'dbo'

	SET @TargetDB = dbo.F_BC_Clean_ObjName(DB_NAME(), 1, 0)

	SET @SQL = N'IF EXISTS(SELECT * FROM ' + @TargetDB + '.sys.schemas s WHERE s.name = ''' + @TargetSchema + ''') SET @schemaOUT = 1 ELSE SET @schemaOUT = 0'
	SET @ParamDef = N'@schemaOUT nvarchar(20) OUTPUT'

	EXEC dbo.sp_executesql @SQL, @ParamDef, @schemaOUT = @schema_id OUTPUT

	IF LEN(ISNULL(@SourceDB,'')) = 0 OR 
	@schema_id = 0
	BEGIN

		PRINT 'Copy_Procedures
		The procedure creates procedures for for relational input tables (P_Delete, P_Insert, P_Update) from the Sourcedatabase on the Targetdatase if they don''t exist there.
		Please make sure that the specified schema exists on the target database.
		For SQL Server 2016 and up.

		Since procedures can only be created on the current database, this proce-dure must be executed on the target database.
	
		Parameters:
		@TargetSchema - Schema of Targetdatabse tables
		@SourceSchema - Schema of Sourcedatabase tables
		@SourceDB     - Name of Sourcedatabase
	
		Example:
		EXEC dbo.P_APP_Copy_Procedures @SourceDB = ''Chair_Prod'' - Create Delta-Master Table Procs (P_Delete, P_Insert, P_Update) from the source database on the current database if they don''t already exist. Both databases are on the same currently selected server, the schema dbo is used.
	 
		'
	END
	ELSE
	BEGIN

		SET @SourceDB = dbo.F_BC_Clean_ObjName(@SourceDB, 1, 0)
	
		-- Cursor for Procs
		-- Only procedures beginning with P_Insert, P_Update, P_Delete will select-ed
		-- This selection can be changed as required for other kinds of procedures.
		-- Only procedures that do not exist on the target database are selected.

		SET @SQL = '
		DECLARE cur_proc CURSOR FOR

		SELECT
			sc.text
		FROM ' + @SourceDB + '.sys.objects so (NOLOCK)		
		INNER JOIN ' + @SourceDB + '.sys.syscomments sc (NOLOCK)	
			ON SO.object_id = SC.id
		WHERE so.type = ''P''
		and (So.name LIKE ''P_Delete%'' OR so.name LIKE ''P_Insert%'' OR so.name LIKE ''P_Update%'')
		AND so.name not LIKE ''%_Model%'' 
		AND so.name not LIKE ''%V_SYS%''  
		AND NOT EXISTS(SELECT * FROM ' + @TargetDB + '.sys.objects (NOLOCK) sso WHERE sso.type = ''P'' AND sso.name = so.name)
		AND so.schema_id = (SELECT sch.schema_id FROM ' + @SourceDB + '.sys.schemas sch WHERE sch.name = ''' + @SourceSchema + ''')'

		--PRINT @SQL

		EXEC sp_executesql @SQL

		OPEN cur_proc

		FETCH NEXT FROM cur_proc into @text

		WHILE @@FETCH_STATUS = 0 
		BEGIN
			SET @SQL = @text

			EXEC (@SQL)
			--PRINT @SQL
			FETCH NEXT FROM cur_proc into @text
		END

		CLOSE cur_proc
		DEALLOCATE cur_proc
	END
P_APP_Copy_Permissions
CREATE PROC [dbo].[P_APP_Copy_Permissions] (@TargetSchema varchar(50) = 'dbo', @SourceSchema varchar(50) = 'dbo',  @TargetDB varchar(128)= NULL,  @SourceDB varchar(128) = NULL)
AS

	SET NOCOUNT ON

	DECLARE @SQL nvarchar(4000)
	DECLARE @ParamDef nvarchar(1000)
	DECLARE @schema_id nvarchar(20)
	DECLARE @objectname varchar(250)
	DECLARE @GranteeName varchar(250)
	DECLARE @permission varchar(50)

	IF LEN(LTRIM(RTRIM(@TargetSchema))) = 0
	SET @TargetSchema = 'dbo'

	IF LEN(LTRIM(RTRIM(@SourceSchema))) = 0
	SET @SourceSchema = 'dbo'

	SET @SQL = N'IF EXISTS(SELECT * FROM ' + @TargetDB + '.sys.schemas s WHERE s.name = ''' + @TargetSchema + ''') SET @schemaOUT = 1 ELSE SET @schemaOUT = 0'
	SET @ParamDef = N'@schemaOUT nvarchar(20) OUTPUT'

	EXEC dbo.sp_executesql @SQL, @ParamDef, @schemaOUT = @schema_id OUTPUT

	IF LEN(ISNULL(@SourceDB,'')) = 0 OR 
	LEN(ISNULL(@TargetDB,'')) = 0 OR
	@schema_id = 0
	BEGIN
		PRINT 'Copy_Permissions
		The procedure looks for permissions on tables, views or procedures in the source database and creates them in the target database.
		Please make sure that the specified schema exists on the target database.
		For SQL Server 2016 and up.
	
		Parameters:
		@TargetSchema - Schema of Targetdatabse tables
		@SourceSchema - Schema of Sourcedatabase tables
		@TargetDB     - Name of Targetdatabase
		@SourceDB     - Name of Sourcedatabase
	
		Example:
		EXEC dbo.P_APP_Copy_Permissions @TargetDB = ''Chair_Test'', @SourceDB = ''Chair_Prod'' - Create permissions on objects on the target database that are available on the source database. Both databases are on the same current server, the schema dbo is used.
	 
		'
	END
	ELSE
	BEGIN
		-- Database names in brackets
		SET @TargetDB = dbo.F_BC_Clean_ObjName(@TargetDB, 1, 0)
		SET @SourceDB = dbo.F_BC_Clean_ObjName(@SourceDB, 1, 0)
		
		-- Get permissions on objects (p.class = 1) on the source database
		-- Only objects which do not contain SYS, Model, T_S_TRL or V_S_CPA in their name, as these are created and authorized by DeltaMaster ETL
		-- or which are of table, view, or procedure type ( o.type in ('P','U','V'))
		-- and which ones exist on the target database on which the permissions are to be set

		SET @SQL = 'DECLARE cur_perm CURSOR FOR
		SELECT 
	   		o.name as objectname
			, USER_NAME(p.grantee_principal_id)
			, p.permission_name   
		FROM ' + @SourceDB + '.sys.database_permissions p (NOLOCK)
		INNER JOIN ' + @SourceDB + '.sys.objects o (NOLOCK)
			ON p.major_id = o.object_id
		INNER JOIN ' + @SourceDB + '.sys.schemas s
			ON o.schema_id = s.schema_id
		WHERE p.class = 1	
		AND s.name = ''' + @SourceSchema + 
		''' AND o.type in (''P'',''U'',''V'')
		AND (o.name LIKE ''%V_S%'' OR o.name LIKE ''%T_S%'')	
		AND o.name not LIKE ''%SYS%''
		AND o.name NOT LIKE ''%Model%''
		AND o.name NOT LIKE ''T_S_TRL%''
		AND o.name NOT LIKE ''V_S_CPA%''
		AND EXISTS(SELECT * FROM ' + @TargetDB + '.sys.objects (NOLOCK) sso WHERE sso.name = o.name)	
		AND EXISTS(SELECT * FROM ' + @TargetDB + '.sys.database_principals dbp WHERE dbp.name = USER_NAME(p.grantee_principal_id))		
		AND USER_NAME(grantee_principal_id) <> SYSTEM_USER						-- eigenen User ausschließen
		ORDER BY o.name, USER_NAME(p.grantee_principal_id), p.permission_name'

		--PRINT @SQL

		EXEC sp_executesql @SQL
		OPEN cur_perm

		FETCH NEXT FROM cur_perm INTO @objectname, @GranteeName, @permission

		WHILE @@FETCH_STATUS = 0 
		BEGIN
			SET @SQL = 'USE ' +@TargetDB + ' GRANT ' + @permission + ' ON ' + @TargetSchema + '.' + @objectname + ' TO [' + @GranteeName + ']'
			--PRINT (@SQL)

			EXEC(@SQL)

			FETCH NEXT FROM cur_perm INTO @objectname, @GranteeName, @permission
		END

		CLOSE cur_perm
		DEALLOCATE cur_perm

	END
Zusatzprozedur: P_APP_Copy_Synonyms
CREATE PROC [dbo].[P_APP_CreateSynonyms] (@TargetDB varchar(128) = NULL, @SourceDB varchar(128) = NULL) 
AS

SET NOCOUNT ON

DECLARE @synname varchar(250)
DECLARE @base_object varchar(500)
DECLARE @SQL nvarchar(2000)

IF LEN(ISNULL(@SourceDB,'')) = 0 
OR LEN(ISNULL(@TargetDB,'')) = 0
BEGIN
	PRINT 'P_APP_CreateSynonyms
	The procedure will search for differences in synonyms between a Sourcedatabase and teh current database.
	
	Parameters:
	@TargetDB     - Name of Targetdatabase
	@SourceDB     - Name of Sourcedatabase
	
	Examples:
	EXEC dbo.P_APP_CreateSynonyms @TargetDB = ''Chair_Test'', @SourceDB = ''Chair_Prod'' - Create all synonyms that are available on the Sourcedatabase but not on the Targetdatabase. Both databases are on the same currently selected server.
	 
	'
END
ELSE
BEGIN
	-- Database names in brackets
	SET @TargetDB = dbo.F_BC_Clean_ObjName(@TargetDB, 1, 0)
	SET @SourceDB = dbo.F_BC_Clean_ObjName(@SourceDB, 1, 0)
	
	-- Select synonyms of Source database
	-- Replacing the source database name with the target database name
	
	SET @SQL = 'DECLARE cur_syn CURSOR FOR 
	SELECT
		stest.name
		, REPLACE(stest.base_object_name,''' + @SourceDB + ''',''' + @TargetDB +''') 
	FROM ' + @SourceDB + '.sys.synonyms stest (NOLOCK)
	WHERE LEFT(stest.name,1) in (''T'',''V'',''S'')
	AND stest.name not LIKE ''%Model%''
	AND NOT EXISTS(SELECT * FROM ' + @TargetDB + '.sys.synonyms sprod WHERE sprod.name = stest.name)'

	--PRINT @SQL

	EXEC sp_executesql @SQL

	open cur_syn

	FETCH NEXT FROM cur_syn INTO @synname, @base_object

	WHILE @@FETCH_STATUS = 0 
	BEGIN

		SET @SQL = 'USE ' + @TargetDB + ' CREATE SYNONYM ' + @synname + ' For ' + @base_object
		--PRINT @SQL

		EXEC (@SQL)
		FETCH NEXT FROM cur_syn INTO @synname, @base_object
	END

	CLOSE cur_syn
	DEALLOCATE cur_syn
END
F_BC_Clean_Objectname
CREATE FUNCTION [dbo].[F_BC_Clean_ObjName] (@ObjName varchar(150), @AddBracket bit = 1, @AddDot bit = 0) 
RETURNS varchar(150)
BEGIN
	DECLARE @RetVal varchar(150)
	
	SET @RetVal = isnull(replace(replace(CASE WHEN right(@ObjName, 1) = '.' AND len(@ObjName) > 1 THEN left(@ObjName, len(@ObjName)-1) WHEN @ObjName = '.' THEN @@servername ELSE @ObjName END , '[', ''), ']', ''), '')
	SELECT @RetVal = CASE WHEN @AddBracket = 1 and @RetVal <> '' THEN '[' ELSE '' END + @RetVal + CASE WHEN @AddBracket = 1 and @RetVal <> '' THEN ']' ELSE '' END + CASE WHEN @AddDot = 1 and @RetVal <> '' THEN '.' ELSE '' END

	RETURN @RetVal
END