データベーススキーマが存在するかどうかを照会する方法


98

ビルドプロセスの一部として、コードを4つの異なる環境に展開するときにデータベース更新スクリプトを実行します。同じクエリは、私たちが生産にリリースをドロップするまでに追加されますので、それが持っている特定のデータベースに複数回実行できるようにします。このような:

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

現在、配置/ビルドスクリプトにcreate schemaステートメントがあります。スキーマの存在をどこで問い合わせればよいですか?


2
受け入れられた回答の変更を検討してください。あなたが受け入れた答えが実際に書かれたとおりに機能することは不可能です。
アーロンベルトラン

回答:


165

sys.schemasをお探しですか?

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

CREATE SCHEMAは独自のバッチで実行する必要があることに注意してください(以下の回答に従って)


くそ...私が投稿を編集して読みやすくするのにかかった時間に...あなたは私の問題を修正しました。どうもありがとう!
パルスヘッド2008年

18
CREATE SCHEMAはバッチの最初のステートメントである必要があるため、これはSQL 2008では機能しません。回避策についてはvfilbyの投稿を参照してください
sergiom

4
「sys.schemasから1を選択」を使用して、パフォーマンスを改善できます。
vijaysylvester

4
@vijaysylvesterいいえ、これは神話です。SQL Serverは列リストを最適化するため、そこに何を入力してもかまいません。完全に無視されます。証拠が必要ですか?プットSELECT 1/0...
アーロンバートランド

1
私はこの回答を正しくないように更新しました(つまり、以下のstackoverflow.com/a/521271/2688のスクリプトを使用します)
bdukes

157

@bdukesは、スキーマが存在するかどうかを判断するのに最適ですが、上記のステートメントはSQL Server 2005では機能しませんCREATE SCHEMA <name>。独自のバッチで実行する必要があります。回避CREATE SCHEMA策は、execでステートメントを実行することです。

これが私がビルドスクリプトで使用したものです。

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

魅力のように動作します!これにより、自分の印刷ステートメントとすべてを置くことができます。
2014年

2

これは古いので、追加を余儀なくされました。SQLSERVER 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する方法検証コードに類似の、多くの場合、意図的にスロー例外の私はにそれの良いを信じて、私はそれの信じているから考えられるすべての戻り結果を説明するための「 'ベストプラクティス'」ではありませんが、致命的な例外を生成するだけであっても、通常、処理を停止する既知の効果は、トラップされていないエラーの不明なカスケード効果よりも優れているためです。それは非常に低いですので、私はそれの価値が別々のトラブルとは思いませんでした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 2017年

@Stijn:これは、検証コードが意図的に頻繁に行われる方法と同様の「設計による」Throw Exceptionです。あなたが言ったように、それは起こる可能性が「ありそう」ではないので、私見、それは全体の価値はありませんでしたTry- CatchまたはCountよりユーザーフレンドリーな致命的なエラーを生成するための個別のチェックはありませんでしたが、とにかく、私はおそらく致命的なエラーを望みます。考えられるすべての戻り結果を説明することは「ベストプラクティス」であると信じていますが、致命的な例外を生成する可能性はほとんどありませんが、処理を停止する既知の効果は、通常、トラップされない未知のカスケード効果よりも優れているためです。エラー。
トム・

それはすべて正常に聞こえますが、それが意図的なものであるかどうかはわかりませんでした:)あなたのコメントは、コメントで述べたように、いくつかの追加の説明から恩恵を受けることができます。
user247702

@Stijn:私のペットpeeveがあればチェックしていないの「『ベストプラクティス』」それほど一般的であるSelectInsertUpdateまたはDeleteステートメントが返さ/より多くの影響を受けたか、少ないしかしそう行の予想#より。Unique Index返される/影響を受ける行の予想される数(つまり1)が現在確保されている場合でも、将来的には(偶然または(近視的に)「意図的に」)変更される可能性があります。
トム

1

コンポーネントのレイアウトで可能であれば、これも機能します。

存在する場合(sys.schemasからSELECT 1 WHERE name = 'myschema')NOEXECをONに設定します 
行く
スキーマの作成myschema
GO 
SET NOEXEC OFF-さらに処理が必要な場合。
GO
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.