Everything seems to be normal until someone yells at a DBA asking why they couldn’t give database role permissions to a login due to this error.
This error occurs when particular login in question is associated to ‘dbo’ user in the database. In other words, this particular login is the ‘db_owner’ of the database which is causing the issue.
This error occurs while we try to give any database role permissions to the login associated with ‘dbo’ user
I recreated the error by creating a new database name ‘Test’, create a new login with name ‘TestUser’ and giving the authorization to the newly created ‘testuser’.
CREATE DATABASE TEST GO USE [master] GO CREATE LOGIN [TestUser] WITH PASSWORD=N'@eE$9@', DEFAULT_DATABASE=[master] GO ALTER AUTHORIZATION ON DATABASE::[Test] TO [TestUser] GO
In the Login ‘TestUser’ properties, database mapping tab, you should see the login associated to user ‘dbo’
I then tried to add a database role ‘db_datareader’ to the database Test which throws an error
Change the database owner to ‘sa’, then create a user associated to the login in the Database and then add the login to database roles with the new created user.
USE [Test] GO -- Change the database owner to 'sa' account ALTER AUTHORIZATION ON DATABASE::[Test] TO [sa] GO USE [Test] GO CREATE USER [TestUser] FOR LOGIN [TestUser] GO USE [Test] GO ALTER ROLE [db_datareader] ADD MEMBER [TestUser] GO
These kind of errors seems to be tricky in the beginning, but once we understand the reason behind it, its pretty easy to solve. These kind of errors are caused by couple of reasons including database migration from lower environments of sql server. When the database is migrated to latest versions, the user ‘dbo’ user was not associated with ‘sa’ account. The other reason is when the authorization of the database is changed to specific login, ‘dbo’ user is associated to the login. It is always important to check which login is associated with the ‘dbo’ user in the database. You can check that using the below query:
--check which login is associated with 'dbo' user select ab.name as DatabaseUser, cd.name as SrvrLogin, ab.type_desc, ab.owning_principal_id, ab.authentication_type_desc From sys.database_principals ab inner join sys.server_principals cd on ab.sid = cd.sid where ab.name = 'dbo';
The result of the query looks like this:
Hope this helps!