Veritabanı şeması olup olmadığını nasıl sorgulayabilirim?


102

Oluşturma sürecimizin bir parçası olarak, kodu 4 farklı ortama dağıtırken bir veritabanı güncelleme komut dosyası çalıştırıyoruz. Aynı sorgu biz üretime bir salımını damla kadar eklenir alacak beri Dahası, sahip belirli bir veritabanı üzerinde birden çok kez çalıştırmak için muktedir. Bunun gibi:

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

Şu anda dağıtım / oluşturma komut dosyasında bir şema oluştur deyimim var. Bir şemanın varlığını nerede sorgulayabilirim?


2
Lütfen kabul edilen cevabı değiştirmeyi düşünün. Kabul ettiğiniz cevabın aslında yazılı olarak sizin için işe yaraması mümkün değil.
Aaron Bertrand

Yanıtlar:


169

Sys.schemas mı arıyorsunuz ?

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

CREATE SCHEMAKendi grubunda çalıştırılması gerektiğini unutmayın ( aşağıdaki cevaba göre )


Kahretsin ... yazıyı daha okunaklı hale getirmek için düzenlemem gereken zamanda ... sorunumu çözdün. Çok teşekkürler!
Pulsehead

18
CREATE SCHEMA'nın bir toplu işteki ilk ifade olması gerektiğinden bu SQL 2008'de çalışmaz, geçici çözüm için vfilby gönderisine bakın
sergiom

4
Performansı iyileştirmek için 'sys.schemas'dan 1'i seçin' seçeneğini kullanabilirsiniz.
vijaysylvester

4
@vijaysylvester Hayır, bu bir efsane. SQL Server, sütun listesini optimize eder, böylece oraya ne koyduğunuz önemli değildir. Tamamen göz ardı edildi. Kanıt mı istiyorsunuz? PutSELECT 1/0...
Aaron Bertrand

1
Bu yanıtı yanlış olmayacak şekilde güncelledim (yani aşağıdaki stackoverflow.com/a/521271/2688'deki komut dosyasını kullanmak için )
bdukes

157

@bdukes, şemanın var olup olmadığını belirleme konusunda haklı, ancak yukarıdaki ifade SQL Server 2005'te CREATE SCHEMA <name>çalışmayacak. kendi toplu işinde çalışması gerekiyor. Çözüm, CREATE SCHEMAifadeyi bir exec'de yürütmektir .

Derleme komut dosyalarımda kullandım:

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

tıkır tıkır çalışıyor! bu bile yazılı ifadelerimi ve her şeyi koymama izin veriyor.
Tony

2

Bu eski, bu yüzden eklemeye mecbur hissediyorum: SQL SUNUCUSU 2008+ için Bunların hepsi çalışır (seçilen kısım için), ardından EXECUTE('CREATE SCHEMA <name>')negatif sonuçlarda gerçekten oluşturmak için kullanın .

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

1
IF schema_id ('MySchemaName') IS NULLiyi çalışıyor ve kabul edilen cevaptan biraz daha uygun görünüyor.
BradC

Kabul ediyorum @BradC. İstisna alanlar için: SCHEMA_ID ('out') NULL EXEC IS ('CREATE SCHEMA [out] AUTHORIZATION [out]');
Juozas

1

Sadece olmak ekstra aşağıdaki sürüm> 1 eşleme imkanı (ancak düşüktür) için hesaba bir Tür dönüştürme hatası üretir "savunma" Schemanasıl doğrulama koduna 'ın benzer ben' s iyi inanıyoruz ve bunu inanması nedeniyle İstisna en sık kasten Atma Olası tüm dönüş sonuçlarını hesaba katmak için "'en iyi uygulama'", ancak olası olmasa da ve yalnızca ölümcül bir istisna oluştursa bile, işlemeyi durdurmanın bilinen etkileri genellikle yakalanmamış hataların bilinmeyen kademeli etkilerinden daha iyidir. Çok olası olmadığından, daha kullanıcı dostu ölümcül bir hata ancak yine de ölümcül bir hata oluşturmak için ayrı bir Count+ Throwveya Try- Catch- kontrolünün zahmetine değeceğini düşünmedim Throw.

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

Sonra:

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

Büyük / küçük harfe duyarlı bir harmanlama kullandığınızda birden fazla eşleşen şemaya sahip olmanın mümkün olduğunu varsayıyorum, ancak "hata işlemeniz" aşağıdaki hatayla sonuçlanacaktır
user247702

@Stijn: Bu, doğrulama kodunun kasıtlı olarak yapılmasına benzer bir "Tasarım gereği" Throw Exception. Dediğin gibi, gerçekleşmesi "muhtemel" değil, bu yüzden IMHO, bir bütün olarak değersizdi Try- Catchya da Countdaha kullanıcı dostu ölümcül bir hata oluşturmak için ayrı bir kontrol, ama ne olursa olsun, muhtemelen ölümcül bir hata istiyorum. İnanıyorum ve olası tüm geri dönüş sonuçlarını hesaba katmanın "'en iyi uygulama" olduğuna inanıyorum ve bu olasılık dışı olsa da ve yalnızca ölümcül bir istisna oluştursa bile, işlemeyi durdurmanın bilinen etkileri genellikle tuzağa düşürülmemişin bilinmeyen kademeli etkilerinden daha iyidir. hatalar.
Tom

Kulağa hoş geliyor, kasıtlı olup olmadığından emin değildim :) Cevabınız, az önce yorumunuzda belirttiğiniz gibi bazı ek açıklamalardan yararlanabilir.
user247702

Benim hayvan kızdırmak değil-çok yaygın " 'en iyi uygulama'" bir olmadığını kontrol değil: @Stijn Select, Insert, Updateveya DeleteBildirimi daha / iade etkilenen veya daha az ancak olası Satırlar beklenen # daha. Unique IndexHalihazırda iade edilecek / etkilenecek beklenen Satır sayısını (yani 1) sağlayanlar olsa bile , bu (yanlışlıkla veya (kısa görüşle) "kasıtlı olarak") gelecekte değişebilir.
Tom

1

Bileşenlerin düzeni izin veriyorsa, bu da işe yarar.

VARSA (sys.schemas WHERE ad = 'myschema' DAN 1 SEÇİN) NOEXEC'i AÇIK olarak ayarlayın 
Git
ŞEMA Myschema OLUŞTUR
GİT 
NOEXEC'i KAPALI AYARLA - daha fazla işlem gerekiyorsa.
GİT
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.