We had many facilities that operate in areas where there is poor/no internet connection; the facility staff sent us monthly a backup of the facility database for us to restore it on our data center.
The problem is: when we restore the database all database users and their mappings to logins are lost (restores are done at the data center).
I intend to recreate the database users and map them to server logins after a database restore.
I listed all server logins and their mapped users on a single database [master].dbo.[OurDatabases] that had the simple following schema:
----------------------------------------
Id | DbName | LoginName | DbUser |
----------------------------------------
For that purpose, I wrote an algorithm and implemented it using an after insert trigger on [msdb].[dbo].[restorehistory] system database:
CREATE TRIGGER [dbo].[AfterRestoreDatabase]
ON [msdb].[dbo].[restorehistory]
FOR INSERT
AS
BEGIN
DECLARE @DatabaseName AS VARCHAR(500)
SELECT @DatabaseName = destination_database_name FROM INSERTED
IF @DatabaseName IN (SELECT D.DbName FROM [master].dbo.[OurDatabases] D )
BEGIN
DECLARE @DbUser AS NVARCHAR(50) = NULL
SELECT @DbUser = D.DbUser FROM [master].dbo.[OurDatabases] D WHERE D.DbName = @DatabaseName
IF @DbUser IS NULL
BEGIN
INSERT INTO DB_Users.dbo.Errors(Descr) VALUES ('Database Restored but no user mapping existed! REASON: UserName not exits in [master].dbo.[OurDatabases].')
END
ELSE
BEGIN
DECLARE @SQL NVARCHAR(MAX)
SET @SQL =
'
USE [' + @DatabaseName + ']
IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = N''' + @DbUser + ''')
CREATE USER ' + @DbUser + ' FOR LOGIN ' + @DbUser + '
EXEC sp_addrolemember ''db_owner'', N''' + @DbUser + ''''
EXEC (@SQL)
END
END
ELSE
BEGIN
INSERT INTO DB_Users.dbo.Errors(Descr) VALUES ('Database Restored but no user mapping existed! REASON: Database name not exits in [master].dbo.[OurDatabases].')
END
END
The problem is that the trigger does not do the expected on the target database.