How do I query if a database schema exists
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?
Solution 1:
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:
@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:
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:
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:
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