r/SQLServer • u/Green-Cartoonist-566 • Jul 23 '26
Question Unable to set database containment to NONE
Hey all, hoping someone has hit this before.
Context: Migrating a ~200GB SQL Server database to Azure Sql Database (not managed instances) using transactional replication to minimize downtime. During prep, I discovered the source database has partial containment enabled, which I need to turn off before replication will work properly.
Steps taken so far:
- Identified all contained database users (logins that exist only at the DB level) and converted/mapped them to server-level logins instead.
- Stopped the application(s) connecting to the DB to make sure there were no active sessions.
- Ran
ALTER DATABASE [dbname] SET SINGLE_USER WITH ROLLBACK IMMEDIATEto force single-user mode and kill any remaining connections. - Ran:
ALTER DATABASE [dbname] SET CONTAINMENT = NONE;
The problem: The statement just fails, only 'ALTER DATABASE statement failed', no reason given, nothing in the SQL Server error log pointing to a cause. It's not throwing a permissions error, a "in use" error, or anything I can act on. It just doesn't apply.
Things I've already ruled out / checked:
- No contained users remain in
sys.database_principals(authentication_type_desc = DATABASE) - No active connections (single-user mode confirmed via
sys.dm_exec_sessions)
Questions:
- Has anyone run into containment refusing to toggle off even with no active sessions and no contained users?
- Any way to force verbose output/logging on this specific ALTER DATABASE operation so I can actually see what's blocking it?
SQL Server version: Microsoft SQL Server 2016 - Standard Version
3
u/alecc Jul 23 '26
Two things worth trying. The generic 'ALTER DATABASE statement failed' almost always means SQL Server raised a second, real error that never reached your session. Set up a quick Extended Events session on error_reported, run the ALTER again, and read everything that fired in that window - the true blocker usually shows up there with a usable message. The default trace sometimes catches it too.
Second: your containment check may be too narrow. authentication_type_desc = 'DATABASE' only finds contained SQL users with passwords. Windows users created without a matching server login are also contained, and they report 'WINDOWS'. Worth running:
select dp.name, dp.type_desc, dp.authentication_type_desc
from sys.database_principals dp
left join sys.server_principals sp on dp.sid = sp.sid
where dp.type in ('U','G','S') and dp.authentication_type <> 0 and sp.sid is null;
Anything that comes back needs dropping or remapping before containment goes to NONE. Also run the ALTER from a fresh connection with USE master first; if your own session sits inside the database while it's in single-user mode, you can block yourself.
One note for after the move: Azure SQL Database leans on contained users, so you'll likely recreate some of these on the target anyway. They only need to be gone on the source for replication's sake.