By:Aaron Bertrand || Related Tips:More >System Databases
ProblemI'm sure we've all done this: inadvertently created objects in the master database. We may not have noticed we were in master, we may have left out a USE directive in our deployment script, or we may have been placed in that context without our knowledge (as in this Connect bug ). At the end of the day, though, you're probably going to want to remove those user-created objects from the system database.
SolutionWithout going into things like ensuring you haven't also inadvertently placed external dependencies on any of these objects (like an application that now talks to the master database instead of a user database, or even another database that depends on entities you placed in master), there is a specific strategy and order of operations you should follow when cleaning up system databases. I'm going to divide into two categories (things we won't be dropping and things we will be dropping) the types of things you might have inadvertently created in the master database:
Things we won't be dropping todayThere are certain object types I'm not going to handle, either because you're simply not going to be able to drop them, or because I do not want to encourage dropping things that could be irreversible or leave your system in an undesirable state. Some of these, also, may be created in master on purpose:
ET External table IT Internal table PC Assembly (CLR) stored procedure PG Plan guide RF Replication-filter-procedure S System table SQ Service queue TA Assembly (CLR) DML trigger X Extended procedure - CLR User-Defined Data Type (UDDT)There are also some system objects that *look* like user objects that we're going to want to avoid touching. While system objects shouldn't show up in sys.objects , a few do, and the list is version-dependent. This is the set I see in current builds of SQL Server 2016:
SELECT [name], [type], [type_desc]FROM sys.objects
WHERE [type] NOT IN ('IT','S')
AND is_ms_shipped = 1
ORDER BY [name];
/*
EventNotificationErrorsQueue SQ SERVICE_QUEUE
MSreplication_options U USER_TABLE
QueryNotificationErrorsQueue SQ SERVICE_QUEUE
ServiceBrokerQueue SQ SERVICE_QUEUE
sp_MScleanupmergepublisher P SQL_STORED_PROCEDURE
sp_MSrepl_startup P SQL_STORED_PROCEDURE
spt_fallback_db U USER_TABLE
spt_fallback_dev U USER_TABLE
spt_fallback_usg U USER_TABLE
spt_monitor U USER_TABLE
spt_values V VIEW
*/
You may also have created your own modules and marked them as system objects, in which case they might show up in the above list too. Note though that there really is no reliable way to distinguish such things from true system stored procedures, so you will have to have some other subjective way to identify those that shouldn't be there, or shouldn't be marked as system objects.
Some of the queries against catalog views may reference columns that only exist in SQL Server 2008 and above. I haven't tested the scripts against 2005, so it is possible you may need to make tweaks to use them against older, unsupported versions. I certainly use syntax that requires 2008+ (combined declare/set and +=).
And finally, there are some other scenarios where you may have adjusted master without meaning to, but that I'm going to shy away from here. Without making an extremely thorough list, I'm avoiding these scenarios either because they're one-off things (like the wrong compatibility level or recovery model), or because they are far too sensitive to allow for automated adjustment (such as cases where you added extra data files, or added a CLR assembly and associated aggregates and functions). I do not want to encourage any magic scripts or shortcuts to "fix" any of these miscues.
Things we will be dropping todayFor the items we do want to consider dropping, there is definitely an important order of operations that will produce the least amount of headache. Foreign keys and views should be eliminated before any tables, for example, and partition functions can't be removed until any tables that use them are dropped. Also, in many cases, circular references can exist, so scripts may need to be executed multiple times until they succeed in full.
There are some object types that are simply dropped with the table they're in, so there's no need to worry about them explicitly. You may see these items in sys.objects , but they will be gone once their tables are dropped. Note that there are two kinds of "default" that will register as type = 'D' in sys.objects ; a default constraint associated directly with exactly one column, and the old (deprecated) CREATE DEFAULT , defined at the database level, that could be used against multiple columns. We'll deal with the latter later.
In the meantime, these are the objects I don't need to worry about:
C Check constraint D Default constraintBut not the old-style, stand-alone CREATE DEFAULT PK Primary key constraint TR DML trigger UQ Unique constraint
The rest are, in order, and acknowledging that this list might not be 100% exhaustive:
1. F Foreign key constraint Need to be dropped before tables, as described below. 2. V View Should be dropped before tables, since they can have direct or indirect SCHEMABINDING . FN SQL scalar function IF SQL inline table-valued function TF SQL table-valued-function 3. P Stored procedure Need to be dropped before tables, but after views and functions (since procedures can reference views and functions, but can't be referenced by them except in rare cases using OPENQUERY() ). 4. U Table (user-defined) Dropped after foreign keys and any type of module that can reference them with SCHEMABINDING . 5. TT Table type Dropped after tables and modules, but before old-style rules that could be bound to them. Table types need to be dropped before other types. Alias types 6. SO Sequence object Dropped after tables/modules because they can't be dropped if any table or module references them. R Rule (old-style, stand-alone) D Old-style CREATE DEFAULT