SQL Clone
SQLServerCentral is supported by Redgate
 
Log in  ::  Register  ::  Not logged in
 
 
 

How to fix Orphaned Users easily

What are Orphaned Users

“Orphaned Users” is a common issue in SQL Server where a Database User is no longer associated with its relevant Server Login.

This often happens when the Server Login is deleted (even if  it’s recreated later), or when the database is moved or restored to a different SQL Server.
You can find some more info on it in this article from Microsoft.

The symptoms that you can expect from such a scenario is inability to use such database users.
Specifically, using the login to connect to the database that it’s supposed to be mapped to. It just doesn’t work.
You’ll receive the following error:

Login failed for user ‘MyUser’. (Microsoft SQL Server, Error: 18456)

The Login could exist on the server level.
The User also exists within the relevant database.
But it doesn’t work because the SID that the database user is mapped to, is different from the SID of the actual Server Login.

This is the real problem, because Users are mapped to their Logins by their SID, not by their names.
And every time you create a new Login, it receives a new, random SID.

 

The “Correct” Solution

The most correct solution for this problem, is to have consistent SIDs to your Logins across all your SQL Servers.
So that even when a database is moved to a different server, it could still use the same SID that it was originally created for.
And also, when you recreate a previously deleted Login, you’d need to create it with the same SID that it originally had.

 

This is, obviously, not a trivial matter, and not always possible.

 

But if this is a direction that interests you, then you will find the following very useful:
A long time ago, Microsoft created a special procedure for the purpose of migrating logins from one server to another.
This procedure outputs the CREATE script for a specified login (or all logins), by retaining its original SID and even its password (if it’s a SQL Login).
They called it “sp_help_revlogin” and published this article to explain how to use it.
Even though this is very, very, very old, they still only provide it till this day as a “downloadable” script instead of a built-in system procedure.

 

One drawback of this procedure, though, is that it only provides the creation script for the Login itself, but not for its permissions, roles, etc.

 

If you ever need to migrate Logins from one SQL Server to another, including their roles and permissions and such, I recommend the easy-to-use Powershell library “dbatools” which contains the command Copy-DbaLogin. More info here.

 

The Easy Solution

Orphaned Users are nothing new in SQL Server.
That’s why the (now deprecated) system procedure sp_change_users_login exists since, about, forever.
You can use it with parameter @Action = ‘Auto_Fix’ and it’ll automatically remap an orphan database user to a Login with the same name, if such exists.

But this procedure (and even its modern counterpart ALTER USER) only affects a single Login at a time.

 

So, what if you have A LOT of such orphaned users?
Even worse, what if you have a lot of servers and a lot of orphaned users in each?
What if this is a commonly recurring problem within your organization?

 

Will you write the same command every time for every user?

I wouldn’t.

I would prefer to write a T-SQL script that will do it for me.

Kinda like the following script, which can be used to reconnect all users within the current database:

 

SET NOCOUNT ON;
DECLARE @user NVARCHAR(MAX);

DECLARE Orphans CURSOR FOR
SELECT dp.name AS user_name 
FROM sys.database_principals AS dp 
LEFT JOIN sys.server_principals AS sp ON dp.SID = sp.SID 
WHERE sp.SID IS NULL 
AND authentication_type_desc = 'INSTANCE'
AND dp.name IN (SELECT name FROM sys.server_principals);

OPEN Orphans
FETCH NEXT FROM Orphans INTO @user

WHILE @@FETCH_STATUS = 0
BEGIN
 DECLARE @Command NVARCHAR(MAX);
 SET @Command = N'ALTER USER ' + QUOTENAME(@user) + N' WITH LOGIN = ' + QUOTENAME(@user)
 PRINT @Command
 EXEC (@Command);

 FETCH NEXT FROM Orphans INTO @user
END

CLOSE Orphans
DEALLOCATE Orphans

 

Or like this script, which also can reconnect all users to their logins, but for ALL of the databases on the server:

 

SET NOCOUNT ON;
DECLARE @db SYSNAME, @user NVARCHAR(MAX);
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL DROP TABLE #tmp;
CREATE TABLE #tmp (DBName SYSNAME NULL, UserName NVARCHAR(MAX));
exec sp_MsforEachDB '
INSERT INTO #tmp
SELECT ''?'', dp.name AS user_name 
FROM [?].sys.database_principals AS dp 
LEFT JOIN sys.server_principals AS sp ON dp.SID = sp.SID 
WHERE sp.SID IS NULL 
AND authentication_type_desc = ''INSTANCE''
AND dp.name IN (SELECT name COLLATE database_default FROM sys.server_principals);'

DECLARE Orphans CURSOR FOR
SELECT DBName, UserName FROM #tmp;

OPEN Orphans
FETCH NEXT FROM Orphans INTO @db, @user

WHILE @@FETCH_STATUS = 0
BEGIN
 DECLARE @Command NVARCHAR(MAX)
 SET @Command = N'USE ' + QUOTENAME(@db) + N'; ALTER USER ' + QUOTENAME(@user) + N' WITH LOGIN = ' + QUOTENAME(@user)
 PRINT @Command;
 EXEC (@Command);

 FETCH NEXT FROM Orphans INTO @db, @user
END

CLOSE Orphans
DEALLOCATE Orphans

 

Feel free to use the above scripts for your convenience!

 

The post How to fix Orphaned Users easily appeared first on Madeira Data Solutions.

Eitan Blumin

Eitan Blumin is a SQL Server database expert and a senior consultant at Madeira SQL Server Services. He has more than 10 years of experience in all fields of the SQL Server DBA role, including but not limited to: Database design, management, development, tuning, replication, backup management, security management, SSIS, SSRS, encryption and more. Eitan also has 10 years of experience in ASP web development, and some experience in a wide variety of development environments such as PHP, C, C++, C#, VB, Java, Perl, Assembler and more.

Comments

Leave a comment on the original post [www.madeiradata.com, opens in a new window]

Loading comments...