데이터베이스 스키마가 있는지 쿼리하는 방법


98

빌드 프로세스의 일부로 4 개의 서로 다른 환경에 코드를 배포 할 때 데이터베이스 업데이트 스크립트를 실행합니다. 동일한 쿼리는 우리가 생산으로 릴리스를 떨어질 때까지 추가 얻을 때문에 또한, 주어진 데이터베이스에 여러 번 실행할 수 있도록. 이렇게 :

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

현재 배포 / 빌드 스크립트에 스키마 생성 문이 있습니다. 스키마가 있는지 어디에서 쿼리합니까?


2
수락 된 답변을 변경해보십시오. 귀하가 수락 한 답변이 실제로 귀하를 위해 작성된대로 작동했을 가능성은 없습니다.
Aaron Bertrand

답변:


165

당신은 sys.schemas 를 찾고 있습니까?

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

(가) 있습니다 CREATE SCHEMA(당 자체의 배치에서 실행해야합니다 아래의 대답 )


젠장 ... 더 읽기 쉽게 게시물을 편집하는 데 시간이 걸렸을 때 ... 당신이 내 문제를 해결했습니다. 감사합니다!
Pulsehead

18
CREATE SCHEMA가 배치의 첫 번째 문이어야하므로 SQL 2008에서는 작동하지 않습니다. 해결 방법은 vfilby 게시물을 참조하십시오
sergiom

4
성능을 향상시키기 위해 'Select 1 from sys.schemas'를 사용할 수 있습니다.
vijaysylvester 2012

4
@vijaysylvester 아니요, 이것은 신화입니다. SQL Server는 열 목록을 최적화하므로 여기에 무엇을 넣든 상관 없습니다. 완전히 무시됩니다. 증거를 원하십니까? PutSELECT 1/0...
Aaron Bertrand

1
이 답변이
틀리지

157

@bdukes는 스키마가 존재하는지 확인하는 데 적합하지만 위의 문은 SQL Server 2005에서 작동하지 않습니다 CREATE SCHEMA <name>. 자체 배치로 실행해야합니다. 해결 방법은 CREATE SCHEMAexec 에서 문 을 실행하는 것입니다.

다음은 빌드 스크립트에서 사용한 것입니다.

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

매력처럼 작동합니다! 이것은 심지어 내 인쇄 진술과 모든 것을 넣을 수 있습니다.
Tony

2

이것은 오래되어서 추가해야한다고 느낍니다. For SQL SERVER 2008+ 이것들은 모두 (선택 부분에 대해) 작동하고, EXECUTE('CREATE SCHEMA <name>')실제로 부정적인 결과를 만드는 데 사용 합니다.

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

IF schema_id ('MySchemaName') IS NULL잘 작동하며 허용되는 답변보다 조금 더 편리해 보입니다.
BradC

1

그냥 할 수 추가 , 다음 버전> 1 일치의 가능성 (그러나 가능성)에 대한 계정에 형식 변환 오류가 발생합니다 "방어" Schema방법 유효성 검사 코드로의 유사한 I가 그것의 좋은 생각 나는 그것을 믿기 때문에 예외의를 종종 의도적으로 던져 가능한 모든 반환 결과를 설명하는 " '모범 사례'"는 가능성이 낮고 처리 중지의 알려진 효과가 일반적으로 포착되지 않은 오류의 알려지지 않은 연속 효과보다 낫기 때문에 치명적인 예외를 생성하는 경우에도 마찬가지입니다. 그것은 매우 가능성이기 때문에, 나는 그것의 가치가 별도의 문제를 생각하지 않았다 Count체크 + Throw또는 Try- Catch- 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

그때:

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

대 / 소문자 구분 데이터 정렬을 사용할 때 일치하는 스키마가 두 개 이상있을 수 있다고 가정하지만 "오류 처리"로 인해 다음 오류가 발생합니다. varchar 값 'ERROR'를 데이터 형식 int로 변환 할 때 변환에 실패했습니다.
user247702

@Stijn : 유효성 검사 코드가 의도적으로 사용하는 것과 유사한 "설계 별" Throw Exception입니다. 당신이, 그것은 " '가능성'"아니다 말했듯이 이럴 때문에, 그것은 전체의 가치가 없었다, 일이 Try- Catch또는 별도의 Count보다 사용자 친화적 인 치명적인 오류를 생성 할 수 체크,하지만 상관없이, 나는 가능성이 치명적인 오류를 원하는 것입니다. 나는 모든 가능한 반환 결과를 설명하는 것이 " '모범 사례'"라고 믿고 있습니다. 그러나 가능성은 낮지 만 치명적인 예외를 생성하는 경우에도 처리 중지의 알려진 효과가 일반적으로 알려지지 않은 캐스 케이 딩 효과보다 낫기 때문입니다. 오류.

모든 것이 잘 들리지만 의도적 인 것인지 확실하지 않았습니다. :) 귀하의 답변은 방금 귀하의 의견에 준 것처럼 몇 가지 추가 설명에서 도움이 될 수 있습니다.
user247702

내 애완 동물 초조는 그리 일반적인 " '가장 좋은 방법은'"인 경우 체크하지 않는 : @Stijn Select, Insert, Update또는 Delete문 더 / 반환 영향 또는 덜하지만 가능성 행의 예상 #보다. Unique Index현재 반환 / 영향을받을 것으로 예상되는 행 수 (예 : 1)를 보장하는 ' 이 있더라도 향후에 (실수로 또는 (근시안적으로) "'의도적으로" ") 변경 될 수 있습니다.

1

구성 요소의 레이아웃이 허용하는 경우 이것도 작동합니다.

존재하는 경우 (선택 1 FROM sys.schemas WHERE 이름 = 'myschema') SET NOEXEC ON 
가다
스키마 만들기 myschema
가다 
SET NOEXEC OFF-추가 처리가 필요한 경우.
가다
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.