﻿{"id":173,"date":"2014-12-19T16:20:39","date_gmt":"2014-12-19T15:20:39","guid":{"rendered":"http:\/\/www.codereview.co\/?p=173"},"modified":"2014-12-18T12:25:45","modified_gmt":"2014-12-18T11:25:45","slug":"a-script-to-finddrop-all-orphaned-users-in-sql-server-databases","status":"publish","type":"post","link":"http:\/\/www.codereview.co\/index.php\/sql-server-tutorials\/a-script-to-finddrop-all-orphaned-users-in-sql-server-databases\/","title":{"rendered":"A script to find\/drop all orphaned users in SQL Server Databases"},"content":{"rendered":"<p><span style=\"color: #000000;\"><strong>Scenario Proposal<\/strong><\/span><\/p>\n<p><span style=\"color: #000000;\">One of my many day to day duties includes administering a database (actually many databases) for a Human Resources application. This application uses SQL logins for data access. This is a database I inherited so I had no input on how things were setup or administered. In the past the application administrator used a script to create new users but the script did not work well and frequently caused errors. When a user is created for the application a SQL login is created then a database user is created in many databases.<\/span><\/p>\n<p><span style=\"color: #000000;\">Since this script did not work well and I was the one that usually had to clean up the mess I decided to write a new script to create the users. After writing the script I also decided to write another script to delete users since the application did not provide a process for doing this. As I was writing the script to delete users it occurred to me that there may be orphaned users in many of the databases because deleting users has always been a manual process and it would be very easy to miss one. After checking a few databases and finding orphaned users I tried to find a script to clean up these orphaned users and was surprised that I could not find a script on the internet that did what I wanted so I decided to write my own and pass the information on to others.<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #000000;\"><strong>Solution<\/strong><\/span><\/p>\n<h5><span style=\"color: #000000;\">What Is An Orphaned SQL User?<\/span><\/h5>\n<p><span style=\"color: #000000;\">So, what is an orphaned SQL user? An orphaned user is a database user that does not have an associated SQL login. There are a number of ways a user can become orphaned. The most common way is when a database from a different server is restored. When a database is backed up and restored the database users are also backed up and restored with the database, but the SQL login is not. If a database is restored to the same server the backup came from and the logins already exist then the database users will not be orphaned because security identifiers (SID) will be the same. If a database is restored to a different server and there are logins with the same name chances are the database users will be orphaned because the identifiers are not the same. And if the logins do not exist at all the database users will be orphaned. Another way database users can be orphaned is if the SQL login is deleted without checking for database users.<\/span><\/p>\n<h5><span style=\"color: #000000;\">Find Orphans In All Databases<\/span><\/h5>\n<p><span style=\"color: #000000;\">In my quest, I did find scripts but none did all that I wanted or did it the way I wanted. So I used some of these scripts as models and wrote my own script to get the results I wanted. My purpose in creating this script was twofold. First find all orphaned users in all databases in a server instance and second delete those users if desired. One difficulty encountered when deleting database users is that the user may own objects in the database and cannot be dropped until the object is dropped or ownership is transferred. In my case all users owned a schema so my script had to deal with a schema owned by the user. I wrote the script to store information about orphaned users in a local temporary table, then the temporary table could be used to drop the schema and user.<\/span><\/p>\n<h5><span style=\"color: #000000;\">Find Orphaned Database Users Script<\/span><\/h5>\n<p><span style=\"color: #000000;\"><em>Use master<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>Go<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>Create Table #Orphans <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0(<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0 RowID\u00a0\u00a0\u00a0\u00a0 int not null primary key identity(1,1) ,<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0 TDBName varchar (100),<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0 UserName varchar (100),<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0 UserSid varbinary(85)<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em> )<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>SET NOCOUNT ON <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0DECLARE @DBName sysname, @Qry nvarchar(4000)<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em> SET @Qry = &#8221;<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em> SET @DBName = &#8221;<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em> WHILE @DBName IS NOT NULL<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em> BEGIN<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0 SET @DBName = <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0(<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0 SELECT MIN(name) <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0FROM master..sysdatabases <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0WHERE<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0 \/** to exclude named databases add them to the Not In clause **\/<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0 name NOT IN <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0(<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0 &#8216;model&#8217;, &#8216;msdb&#8217;, <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8216;distribution&#8217;<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0 ) And <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0DATABASEPROPERTY(name, &#8216;IsOffline&#8217;) = 0 <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0AND DATABASEPROPERTY(name, &#8216;IsSuspect&#8217;) = 0 <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0AND name &gt; @DBName<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0 )<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0 IF @DBName IS NULL BREAK<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Set @Qry = &#8216;select &#8221;&#8217; + @DBName + &#8221;&#8217; as DBName, name AS UserName, <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0sid AS UserSID from [&#8216; + @DBName + &#8216;]..sysusers <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0where issqluser = 1 and (sid is not null and sid &lt;&gt; 0x0) <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0and suser_sname(sid) is null order by name&#8217;<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em> Insert into #Orphans Exec (@Qry)<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0End<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>Select * from #Orphans<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\/** To drop orphans uncomment this section <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>Declare @SQL as varchar (200)<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>Declare @DDBName varchar (100)<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>Declare @Orphanname varchar (100)<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>Declare @DBSysSchema varchar (100)<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>Declare @From int<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>Declare @To int<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>Select @From = 0, @To = @@ROWCOUNT <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>from #Orphans<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>&#8211;Print @From<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>&#8211;Print @To<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>While @From &lt; @To<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em> Begin<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0 Set @From = @From + 1<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0 <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0Select @DDBName = TDBName, @Orphanname = UserName from #Orphans<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0 Where RowID = @From<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0 <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0Set @DBSysSchema = &#8216;[&#8216; + @DDBName + &#8216;]&#8217; + &#8216;.[sys].[schemas]&#8217;<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0 print @DBsysSchema<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0 Print @DDBname<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0 Print @Orphanname<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0 set @SQL = &#8216;If Exists (Select * from &#8216; + @DBSysSchema <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0+ &#8216; where name = &#8221;&#8217; + @Orphanname + &#8221;&#8217;)<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0 Begin<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0 Use &#8216; + @DDBName <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0+ &#8216; Drop Schema [&#8216; + @Orphanname + &#8216;]<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0 End&#8217;<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0 print @SQL<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0 Exec (@SQL)<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0 <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0Begin Try<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0 Set @SQL = &#8216;Use &#8216; + @DDBName <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0+ &#8216; Drop User [&#8216; + @Orphanname + &#8216;]&#8217;<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0\u00a0 Exec (@SQL)<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0 End Try<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0 Begin Catch<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0\u00a0 End Catch<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0\u00a0 <\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0End<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>**\/<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>\u00a0<\/em><\/span><br \/>\n<span style=\"color: #000000;\"><em>Drop table #Orphans<\/em><\/span><\/p>\n<h5><span style=\"color: #000000;\">\u00a0Things To Note About This Script<\/span><\/h5>\n<p><span style=\"color: #000000;\">Databases can be excluded from the search by adding the database name to exclude in the &#8216;NOT IN&#8217; where clause. If the &#8220;Drop Orphans&#8217; section is uncommented the script will drop any schema that the orphaned user owns then drop the orphaned user, there is no option to skip a schema\/user. The script will not check for other objects that may be owned by the user. I have tested the script on SQL 2005 and SQL 2008 R2.<\/span><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #000000;\"><strong>Thanks for reading this article,<\/strong><\/span><\/p>\n<p><span style=\"color: #000000;\"><strong>Next steps :<\/strong><\/span><\/p>\n<ol>\n<li><span style=\"color: #000000;\"><b><strong>Add this script to your database toolkit<\/strong><\/b><\/span><\/li>\n<li><span style=\"color: #000000;\"><strong>Share this with your colleagues because Sharing is Learning<\/strong><\/span><\/li>\n<li><span style=\"color: #000000;\"><strong>Comment below if you need any assistance<\/strong><\/span><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Scenario Proposal One of my many day to day duties includes administering a database (actually many databases) for a Human Resources application. This application uses SQL logins for data access. This is a database I inherited so I had no input on how things were setup or administered. In the past the application administrator used [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[32,3],"tags":[30,29,27,28,13,12],"_links":{"self":[{"href":"http:\/\/www.codereview.co\/index.php\/wp-json\/wp\/v2\/posts\/173"}],"collection":[{"href":"http:\/\/www.codereview.co\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.codereview.co\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.codereview.co\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.codereview.co\/index.php\/wp-json\/wp\/v2\/comments?post=173"}],"version-history":[{"count":2,"href":"http:\/\/www.codereview.co\/index.php\/wp-json\/wp\/v2\/posts\/173\/revisions"}],"predecessor-version":[{"id":175,"href":"http:\/\/www.codereview.co\/index.php\/wp-json\/wp\/v2\/posts\/173\/revisions\/175"}],"wp:attachment":[{"href":"http:\/\/www.codereview.co\/index.php\/wp-json\/wp\/v2\/media?parent=173"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.codereview.co\/index.php\/wp-json\/wp\/v2\/categories?post=173"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.codereview.co\/index.php\/wp-json\/wp\/v2\/tags?post=173"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}