Login or Sign Up to become a member!
LessThanDot Sit Logo

LessThanDot

Data Management

Less Than Dot is a community of passionate IT professionals and enthusiasts dedicated to sharing technical knowledge, experience, and assistance. Inside you will find reference materials, interesting technical discussions, and expert tips and commentary. Once you register for an account you will have immediate access to the forums and all past articles and commentaries.

LTD Social Sitings

Lessthandot twitter Lessthandot Linkedin Lessthandot friendfeed Lessthandot facebook Lessthandot rss

Note: Watch for social icons on posts by your favorite authors to follow their postings on these and other social sites.

Your profile

    Search

    XML Feeds

    Google Ads

    « Finding Duplicates - Interesting twistData Quality and Master Data Management with Microsoft SQL Server 2008 R2 book available as a free download »
    comments

    If you are on SQL Server 2005 and up and you are still using sp_change_users_login (I know old habits die slow) then listen up, there is an easier way to fix permissions.

    If you have a login on one server and you have the same login on another server and you did not use the sp_help_revlogin to create the login with the same SID then you have 2 options. drop and create the user(and apply all the permissions) or you can map the existing database user to a SQL Server login.

    This is the old way

    1. EXECUTE sp_change_users_login 'Update_One', 'UserName', 'UserName'

    And here is the new way, much cleaner

    1. ALTER USER UserName WITH LOGIN = UserName

    Let's write some code and see how this all works

    First we are creating a new user named TestLogin

    1. USE [master]
    2. GO
    3. CREATE LOGIN [TestLogin] WITH PASSWORD=N'test', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
    4. GO

    Now it is time to create a new database, in this database we will create the user TestLogin

    1. CREATE DATABASE TestLogin
    2. GO
    3.  
    4. USE TestLogin
    5. GO
    6.  
    7.  
    8. CREATE USER TestLogin FOR LOGIN TestLogin
    9. GO

    Now we will backup the database

    1. USE master
    2. GO
    3.  
    4. BACKUP DATABASE TestLogin TO  DISK = N'c:\Temp\TestLogin.BAK' WITH NOFORMAT, INIT,  NAME = N'TestLogin-Full',
    5. SKIP, NOREWIND, NOUNLOAD,  STATS = 10

    And now we can drop the database since we will create it again later anyhow

    1. USE master
    2. GO
    3.  
    4. DROP DATABASE TestLogin
    5. GO

    Since I want to show you the code so that you can run it on the same server, we will just drop and recreate the login

    1. USE [master]
    2. GO
    3.  
    4. IF  EXISTS (SELECT * FROM sys.server_principals WHERE name = N'TestLogin')
    5. DROP LOGIN [TestLogin]
    6. GO
    7.  
    8.  
    9. USE [master]
    10. GO
    11. CREATE LOGIN [TestLogin] WITH PASSWORD=N'test', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
    12. GO

    Now, we will create the same database again with the same user

    1. CREATE DATABASE TestLogin
    2. GO
    3.  
    4. USE TestLogin
    5. GO
    6.  
    7.  
    8. CREATE USER TestLogin FOR LOGIN TestLogin
    9. GO
    10.  
    11. USE master
    12. GO

    Go ahead and restore the backup we created before

    1. ALTER DATABASE TestLogin SET SINGLE_USER WITH ROLLBACK IMMEDIATE
    2. GO
    3.  
    4. RESTORE DATABASE TestLogin FROM  DISK = N'c:\Temp\TestLogin.BAK' WITH  FILE = 1,
    5. NOUNLOAD,  REPLACE,  STATS = 10
    6. GO
    7.  
    8.  
    9. ALTER DATABASE TestLogin SET MULTI_USER WITH ROLLBACK IMMEDIATE
    10. GO

    We now will use this database and use the sp_change_users_login procedure to see if any SIDs are mismatched

    1. USE TestLogin
    2. GO
    3.  
    4. EXECUTE sp_change_users_login 'report'

    On my machine, I get the following back

    UserName	UserSID
    TestLogin	0x7ED6E205155E9C40BA684E72453BAE1B

    We can easily test this because if you try to login as that user and then execute the command below you will get an error message

    1. USE testlogin
    2. GO

    Msg 916, Level 14, State 1, Line 1
    The server principal "TestLogin" is not able to access the database "TestLogin" under the current security context.

    Leave that query window open for now, we will get back to it later.
    Now let's fix the user by mapping the user to the login

    1. EXECUTE sp_change_users_login 'Update_One', 'TestLogin', 'TestLogin'


    Now this query doesn't return any rows since the user has been fixed

    1. EXECUTE sp_change_users_login 'report'

    Now refresh the query or connect again and run this

    1. USE testlogin
    2. GO

    As you can see it is fine now

    Disconnect from the DB with the TestLogin account and then drop the database

    1. USE master
    2. GO
    3.  
    4. DROP DATABASE TestLogin
    5. GO

    We will create the database again, create the user again and finally we will restore the database

    1. USE master
    2. GO
    3.  
    4. CREATE DATABASE TestLogin
    5. GO
    6.  
    7. USE TestLogin
    8. GO
    9.  
    10.  
    11. CREATE USER TestLogin FOR LOGIN TestLogin
    12. GO
    13.  
    14. USE master
    15. GO
    16.  
    17. ALTER DATABASE TestLogin SET SINGLE_USER WITH ROLLBACK IMMEDIATE
    18. GO
    19.  
    20. RESTORE DATABASE TestLogin FROM  DISK = N'c:\Temp\TestLogin.BAK' WITH  FILE = 1,
    21. NOUNLOAD,  REPLACE,  STATS = 10
    22. GO
    23.  
    24.  
    25.  
    26. ALTER DATABASE TestLogin SET MULTI_USER WITH ROLLBACK IMMEDIATE
    27. GO

    Just as before, we are getting back the mis matched SID

    1. USE TestLogin
    2. GO
    3.  
    4. EXECUTE sp_change_users_login 'report'


    UserName	UserSID
    TestLogin	0x7ED6E205155E9C40BA684E72453BAE1B

    You will get the same error from before if you try to connect to this database

    1. USE testlogin
    2. GO

    Msg 916, Level 14, State 1, Line 1
    The server principal "TestLogin" is not able to access the database "TestLogin" under the current security context.

    Here is how to do the same thing with ALTER USER as with sp_change_users_login

    1. ALTER USER TestLogin WITH LOGIN = TestLogin

    As you can see, this doesn't return anything anymore

    1. EXECUTE sp_change_users_login 'report'



    So, start using ALTER USER UserName WITH LOGIN = UserName instead of sp_change_users_login to fix the mappings, sp_change_users_login is on the endangered deprecated list and will be removed in a feature versions.

    About the Author

    User bio imageDenis has been working with SQL Server since version 6.5. Although he worked as an ASP/JSP/ColdFusion developer before the dot com bust, he has been working exclusively as a database developer/architect since 2002. In addition to English, Denis is also fluent in Croatian and Dutch, but he can curse in many other languages and dialects (just ask the SQL optimizer) He lives in Princeton, NJ with his wife and three kids.
    Social SitingsTwitterFacebookLinkedInHomePageFlickrLTD RSS Feed
    1528 views
    Instapaper

    1 comment

    Comment from: kohmars [Visitor]
    kohmars Awesome, love it, thanks!
    03/21/12 @ 12:58

    Leave a comment


    Your email address will not be revealed on this site.

    Your URL will be displayed.
    (Line breaks become <br />)
    (Name, email & website)
    (Allow users to contact you through a message form (your email will not be revealed.)