Jak sprawdzić, czy istnieje schemat bazy danych

98

W ramach naszego procesu budowania uruchamiamy skrypt aktualizacji bazy danych, wdrażając kod w 4 różnych środowiskach. Co więcej, ponieważ to samo zapytanie zostanie dodane do czasu, gdy upuścimy wydanie do produkcji, musi być w stanie uruchomić wiele razy w danej bazie danych. Lubię to:

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

Obecnie mam instrukcję tworzenia schematu w skrypcie wdrażania / kompilacji. Gdzie mam zapytać o istnienie schematu?

Pulsehead
źródło
2
Prosimy o rozważenie zmiany zaakceptowanej odpowiedzi. Nie jest możliwe, aby zaakceptowana przez Ciebie odpowiedź zadziałała tak, jak została napisana.
Aaron Bertrand,

Odpowiedzi:

165

Szukasz sys.schemas ?

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

Zauważ, że CREATE SCHEMAmusi być uruchomiony we własnej partii (zgodnie z odpowiedzią poniżej )

bdukes
źródło
Cholera ... w czasie, który zajęło mi edytowanie postu, aby był bardziej czytelny ... naprawiłeś mój problem. Dzięki dużo!
Pulsehead
18
to nie działa w SQL 2008, ponieważ CREATE SCHEMA musi być pierwszą instrukcją w partii, zobacz post vfilby dla obejścia
sergiom
4
Możesz użyć opcji „Wybierz 1 z sys.schemas”, aby poprawić wydajność.
vijaysylvester
4
@vijaysylvester Nie, to mit. SQL Server optymalizuje listę kolumn, więc nie ma znaczenia, co tam umieścisz. Całkowicie zignorowane. Chcesz dowód? PutSELECT 1/0...
Aaron Bertrand
1
Zaktualizowałem tę odpowiedź, aby nie była niepoprawna (tj. Aby użyć skryptu z poniższego stackoverflow.com/a/521271/2688 )
bdukes
157

@bdukes ma rację, jeśli chodzi o pieniądze, aby określić, czy schemat istnieje, ale powyższa instrukcja nie będzie działać w SQL Server 2005. CREATE SCHEMA <name>musi działać we własnej partii. Obejściem jest wykonanie CREATE SCHEMAinstrukcji w pliku exec.

Oto, czego użyłem w moich skryptach kompilacji:

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
vfilby
źródło
działa jak marzenie! to pozwala mi nawet umieścić moje oświadczenia drukowane i wszystko.
Tony
2

To jest stare, więc czuję się zobligowany do dodania: Dla SQL SERVER 2008+ Te wszystkie działają (dla wybranej części), a następnie użyj, EXECUTE('CREATE SCHEMA <name>')aby faktycznie utworzyć je na negatywnych wynikach.

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
Mark Schultheiss
źródło
IF schema_id ('MySchemaName') IS NULLdziała dobrze i wydaje się nieco wygodniejsza niż zaakceptowana odpowiedź.
BradC
1

Wystarczy być dodatkowo „obronny”, dodaje się wersja generuje błąd typu konwersji do konta możliwość (jednak mało prawdopodobne)> 1 dopasowywania Schema„s podobny do sposobu kod weryfikacyjny często celowo Rzut Wyjątek s, ponieważ uważam, że dobrze jest i wierzę, że to „Najlepsza praktyka” ”uwzględniająca wszystkie możliwe wyniki zwracania, choć mało prawdopodobne, a nawet jeśli ma to na celu tylko wygenerowanie krytycznego wyjątku, ponieważ znane efekty zatrzymania przetwarzania są zwykle lepsze niż nieznane kaskadowe skutki niezabezpieczonych błędów. Ponieważ jest to wysoce nieprawdopodobne, nie sądziłem, że warto osobno Countsprawdzić + Throwlub Try- Catch- Throwaby wygenerować bardziej przyjazny dla użytkownika błąd krytyczny, ale mimo to błąd krytyczny.

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

Następnie:

if @HasSchemaX = 1
begin
   ...
end -- if @HasSchemaX = 1
Tomek
źródło
Przypuszczam, że możliwe jest posiadanie więcej niż jednego zgodnego schematu, gdy używasz sortowania z uwzględnieniem wielkości liter, ale Twoja „obsługa błędów” spowoduje następujący błąd: Konwersja nie powiodła się podczas konwersji wartości varchar „ERROR” na typ danych int.
user247702
@Stijn: To jest "z założenia" podobne do tego, jak kod walidacyjny często jest celowo Throw Exception. Jak powiedziałeś, nie jest to „prawdopodobne”, więc IMHO, nie było warte całości Try- Catchani oddzielnego Countsprawdzenia, aby wygenerować bardziej przyjazny dla użytkownika błąd krytyczny, ale mimo wszystko prawdopodobnie chciałbym krytycznego błędu. Wierzę w i uważam, że „najlepszą praktyką” jest uwzględnienie wszystkich możliwych wyników zwrotów, choć mało prawdopodobne, a nawet jeśli ma to na celu tylko wygenerowanie krytycznego wyjątku, ponieważ znane efekty zatrzymania przetwarzania są zwykle lepsze niż nieznane efekty kaskadowe braku pułapki błędy.
Tom
To wszystko brzmi dobrze, nie byłam pewna, czy to było zamierzone :) Wasza odpowiedź mogłaby zyskać na dodatkowym wyjaśnieniu, takim jak przed chwilą w komentarzu.
user247702
@Stijn: My Pet zirytować jest powszechne nie tak „«najlepsze praktyki»” o sprawdzenie, czy nie Select, Insert, Updatelub Deletekomunikat zwrócony / dotknięte więcej lub mniej niż oczekiwana # wierszy jednak mało prawdopodobne. Nawet jeśli istnieją Unique Indexobecnie systemy zapewniające oczekiwaną liczbę (tj. 1) wierszy, które mają zostać zwrócone / dotknięte, może to zmienić (przypadkowo lub (krótkowzrocznie) „celowo” ”) w przyszłości.
Tom
1

Jeśli pozwala na to układ komponentów, to też działa.

JEŚLI ISTNIEJE (SELECT 1 FROM sys.schemas WHERE name = 'myschema') USTAW NOEXEC ON 
udać się
STWÓRZ SCHEMAT myschema
UDAĆ SIĘ 
WYŁĄCZ NOEXEC - jeśli potrzebne jest dalsze przetwarzanie.
UDAĆ SIĘ
benik9
źródło