How do I query if a database schema exists

Sql Server-2005Schema

Sql Server-2005 Problem Overview


As part of our build process we run a database update script as we deploy code to 4 different environments. Further, since the same query will get added to until we drop a release into production it has to be able to run multiple times on a given database. Like this:

IF NOT EXISTS (SELECT * FROM sys.tables WHERE object_id = OBJECT_ID(N'[Table]'))
BEGIN
  CREATE TABLE [Table]
  (...)
END

Currently I have a create schema statement in the deployment/build script. Where do I query for the existence of a schema?

Sql Server-2005 Solutions


Solution 1 - Sql Server-2005

Are you looking for sys.schemas?

IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'jim')
BEGIN
EXEC('CREATE SCHEMA jim')
END

Note that the CREATE SCHEMA must be run in its own batch (per the answer below)

Solution 2 - Sql Server-2005

@bdukes is right on the money for determining if the schema exists, but the statement above won't work in SQL Server 2005. CREATE SCHEMA <name> needs to run in its own batch. A work around is to execute the CREATE SCHEMA statement in an exec.

Here is what I used in my build scripts:

IF NOT EXISTS (SELECT 1 FROM sys.schemas WHERE name = '<name>')
BEGIN
    -- The schema must be run in its own batch!
    EXEC( 'CREATE SCHEMA <name>' );
END

Solution 3 - Sql Server-2005

This is old so I feel compelled to add: For SQL SERVER 2008+ These all work (for the select part), then use EXECUTE('CREATE SCHEMA <name>') to actually create it on negative results.

DECLARE @schemaName sysname = 'myfunschema';
-- shortest
If EXISTS (SELECT 1 WHERE SCHEMA_ID(@schemaName) IS NOT NULL)
PRINT 'YEA'
ELSE
PRINT 'NOPE'

SELECT DB_NAME() AS dbname WHERE SCHEMA_ID(@schemaName) IS NOT NULL -- nothing returned if not there

IF NOT EXISTS ( SELECT  top 1 *
                FROM    sys.schemas
                WHERE   name = @schemaName )
PRINT 'WOOPS MISSING'
ELSE
PRINT 'Has Schema'

SELECT SCHEMA_NAME(SCHEMA_ID(@schemaName)) AS SchemaName1 -- null if not there otherwise schema name returned

SELECT SCHEMA_ID(@schemaName) AS SchemaID1-- null if not there otherwise schema id returned


IF EXISTS (
	SELECT sd.SchemaExists 
	FROM (
		SELECT 
			CASE 
				WHEN SCHEMA_ID(@schemaName) IS NULL THEN 0
				WHEN SCHEMA_ID(@schemaName) IS NOT NULL THEN 1
				ELSE 0 
			END AS SchemaExists
	) AS sd
	WHERE sd.SchemaExists = 1
)
BEGIN
	SELECT 'Got it';
END
ELSE
BEGIN
	SELECT 'Schema Missing';
END

Solution 4 - Sql Server-2005

If the layout of components allows it, this works too.

IF EXISTS (SELECT 1 FROM sys.schemas WHERE name = 'myschema') SET NOEXEC ON
go
CREATE SCHEMA myschema
GO
SET NOEXEC OFF -- if any further processing is needed.
GO

Solution 5 - Sql Server-2005

Just to be extra "defensive", the following version generates a Type conversion error to account for the possibility (however unlikely) of > 1 matching Schema's similar to how validation code often intentionally Throw Exception's because I believe it's good to and I believe it's "'best practice'" to account for all possible return results however unlikely and even if it's just to generate a fatal exception because the known effects of stopping processing is usually better than unknown cascading effects of un-trapped errors. Because it's highly unlikely, I didn't think it's worth the trouble of a separate Count check + Throw or Try-Catch-Throw to generate a more user-friendly fatal error but still fatal error nonetheless.

SS 2005-:

declare @HasSchemaX bit
set @HasSchemaX = case (select count(1) from sys.schemas where lower(name) = lower('SchemaX')) when 1 then 1 when 0 then 0 else 'ERROR' end

SS 2008+:

declare @HasSchemaX bit = case (select count(1) from sys.schemas where lower(name) = lower('SchemaX')) when 1 then 1 when 0 then 0 else 'ERROR' end

Then:

if @HasSchemaX = 1
begin
   ...
end -- if @HasSchemaX = 1

Solution 6 - Sql Server-2005

IF NOT EXISTS (SELECT TOP (1) 1 FROM [sys].[schemas] WHERE [name] = 'Person')
BEGIN
	EXEC ('CREATE SCHEMA [Person]')
END

IF NOT EXISTS (SELECT TOP (1) 1 FROM [sys].[tables] AS T
			   INNER JOIN [sys].[schemas] AS S ON S.schema_id = T.schema_id
			   WHERE T.[name] = 'Guests' AND S.[name] = 'Person')
BEGIN
	EXEC ('CREATE TABLE [Person].[Guests]
		   (
			    [GuestId] INT IDENTITY(1, 1) NOT NULL,
			    [Forename] NVARCHAR(100) NOT NULL,
			    [Surname] NVARCHAR(100) NOT NULL,
			    [Email] VARCHAR(255) NOT NULL,
			    [BirthDate] DATETIME2 NULL,
			    CONSTRAINT [PK_Guests_GuestId] PRIMARY KEY CLUSTERED ([GuestId]),
			    CONSTRAINT [UX_Guests_Email] UNIQUE([Email])
		   )')
END

NOTICE: CREATE SCHEMA AND CREATE TABLE NEED COMPLETLY SEPARATED BATCH TO EXECUTE

TO MORE DESCRIPTION VISIT MICROSOFT DOCS WEBSITE :)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPulseheadView Question on Stackoverflow
Solution 1 - Sql Server-2005bdukesView Answer on Stackoverflow
Solution 2 - Sql Server-2005vfilbyView Answer on Stackoverflow
Solution 3 - Sql Server-2005Mark SchultheissView Answer on Stackoverflow
Solution 4 - Sql Server-2005benik9View Answer on Stackoverflow
Solution 5 - Sql Server-2005TomView Answer on Stackoverflow
Solution 6 - Sql Server-2005Mohammad Sadeq SirjaniView Answer on Stackoverflow