You are trying to drop a database user, but are getting the following error message:
The database principal owns a schema in the database, and cannot be dropped. (Microsoft SQL Server, Error: 15138)
This error is self-explanatory as it tells you that the database user you are trying to drop is the database schema owner.
To successfully drop the database user, you must find all the schemas that are owned by the database user, and then transfer their ownership to another user.
Here is the Transact-SQL script, which I wrote a while ago, to drop the database user. This script first transfer’s ownership of all database schemas associated with particular database user to the specified database user, and then drops that database user from the database.
To use this script, change the following two local variables of this script:
- @SQLUser – Specify the name of the database user that you want to drop
- @NewSchemaOwner – Specify the name of the database user that will be used as new schema owner for the schemas that is owned by the database user, which you are dropping
-- Ensure a USE database_name statement has been executed first. SET NOCOUNT ON; DECLARE @ID [int] , @CurrentCommand [nvarchar](MAX) , @ErrorMessage [nvarchar](2000) , @SQLUser [sysname] , --Specify the name of the database user that you want to drop @NewSchemaOwner [sysname]; --Specify the name of the database user that will be used as new schema --owner for the schemas that is owned by the database user you are dropping SET @SQLUser = N'Specify_Database_User_You_Want_To_Drop'; --Example: testuser SET @NewSchemaOwner = N'Specify_Database_User_Who_Will_User_As_New_Schema_Owner'; --Example: liveuser DECLARE @Work_To_Do TABLE ( [ID] [int] IDENTITY(1, 1) PRIMARY KEY , [TSQL_Text] [varchar](1024) , [Completed] [bit] ); INSERT INTO @Work_To_Do ( [TSQL_Text] , [Completed] ) SELECT N'ALTER AUTHORIZATION ON SCHEMA::' + [name] + SPACE(1) + 'TO' + SPACE(1) + QUOTENAME(@NewSchemaOwner) , 0 FROM [sys].[schemas] WHERE [principal_id] = USER_ID(@SQLUser); INSERT INTO @Work_To_Do ( [TSQL_Text] , [Completed] ) SELECT N'DROP USER' + SPACE(1) + @SQLUser , 0 SELECT @ID = MIN([ID]) FROM @Work_To_Do WHERE [Completed] = 0; WHILE @ID IS NOT NULL BEGIN SELECT @CurrentCommand = [TSQL_Text] FROM @Work_To_Do WHERE [ID] = @ID; BEGIN TRY EXEC [sys].[sp_executesql] @CurrentCommand PRINT @CurrentCommand END TRY BEGIN CATCH SET @ErrorMessage = N'"Oops, an error occurred that could not be resolved. For more information, see below:' + CHAR(13) + ERROR_MESSAGE() RAISERROR(@ErrorMessage,16,1) WITH NOWAIT GOTO ChooseNextCommand END CATCH ChooseNextCommand: UPDATE @Work_To_Do SET [Completed] = 1 WHERE [ID] = @ID SELECT @ID = MIN([ID]) FROM @Work_To_Do WHERE [Completed] = 0 END; SET NOCOUNT OFF;
Thanks for the script Basit, Its very usefull in emegency
That’s some pretty nice code, Basit. If you were to turn it into an “sp_” sproc and show people how to convert it to a “system stored procedure” that’s executable from any database and add some comments for each embedded query, you should consider submitting it on SQLServerCentral.com or Simple-Talk.com as an article and explain each piece. I’m sure the membership over there would enjoy it.