यदि डेटाबेस स्कीमा मौजूद है तो मैं कैसे क्वेरी कर सकता हूं


98

अपनी निर्माण प्रक्रिया के भाग के रूप में हम एक डेटाबेस अपडेट स्क्रिप्ट चलाते हैं क्योंकि हम 4 अलग-अलग वातावरणों में कोड तैनात करते हैं। इसके अलावा, के बाद से एक ही क्वेरी जब तक हम उत्पादन में एक रिलीज ड्रॉप में जुड़ती जाएगी यह है एक दिया डेटाबेस पर कई बार चलाने के लिए सक्षम होने के लिए। ऐशे ही:

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

वर्तमान में मेरे पास तैनाती / निर्माण स्क्रिप्ट में एक स्कीमा स्टेटमेंट है। स्कीमा के अस्तित्व के लिए मैं कहां क्वेरी करूं?


2
कृपया स्वीकृत उत्तर को बदलने पर विचार करें। यह संभव नहीं है कि आपके द्वारा स्वीकार किया गया उत्तर वास्तव में आपके लिए लिखित रूप में काम करे।
हारून बर्ट्रेंड

जवाबों:


165

क्या आप sys.schemas की तलाश कर रहे हैं ?

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

ध्यान दें कि CREATE SCHEMAअपने स्वयं के बैच में चलाया जाना चाहिए ( नीचे दिए गए उत्तर के अनुसार )


डारन ... उस समय में पोस्ट को संपादित करने के लिए इसे और अधिक पठनीय बनाने के लिए मुझे ले गया ... आपने मेरी समस्या को ठीक कर दिया। बहुत बहुत धन्यवाद!
पल्सहेड

18
यह SQL 2008 में काम नहीं करता है क्योंकि क्रिएट स्कीमा को एक बैच में पहला स्टेटमेंट होना चाहिए, वर्कअराउंड के लिए vfilby पोस्ट देखें
Sergiom

4
आप प्रदर्शन को बेहतर बनाने के लिए 'sys.schemas से 1 का चयन करें' का उपयोग कर सकते हैं।
vijaysylvester

4
@vijaysylvester नहीं, यह एक मिथक है। SQL सर्वर स्तंभ सूची से दूर हो जाता है, इसलिए इससे कोई फर्क नहीं पड़ता कि आपने वहां क्या रखा है। पूरी तरह से नजरअंदाज कर दिया। प्रमाण चाहिए? डालSELECT 1/0...
हारून बर्ट्रेंड

1
मैंने इस उत्तर को गलत नहीं होने के लिए अपडेट किया है (यानी नीचे दी गई स्क्रिप्ट का उपयोग करने के लिए stackoverflow.com/a/521271/2688 )
bdukes

157

@bdukes स्कीमा मौजूद है, यह निर्धारित करने के लिए पैसे पर सही है, लेकिन ऊपर बयान SQL सर्वर 2005 में काम नहीं करेगा। CREATE SCHEMA <name>अपने स्वयं के बैच में चलाने की जरूरत है। चारों ओर एक कार्य निष्पादन में CREATE SCHEMAकथन को निष्पादित करना है ।

यहाँ मैं अपनी बिल्ड स्क्रिप्ट में इस्तेमाल किया है:

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

एक जादू की तरह काम करता है! यहां तक ​​कि मुझे अपने प्रिंट स्टेटमेंट और सब कुछ डालने देता है।
टोनी

2

यह पुराना है, इसलिए मैं इसे जोड़ने के लिए मजबूर महसूस करता हूं: 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अच्छी तरह से काम करता है, और स्वीकृत उत्तर की तुलना में थोड़ा अधिक सुविधाजनक लगता है।
ब्रैडॉक

1

बस अतिरिक्त "रक्षात्मक" होने के लिए, निम्न संस्करण संभावना (हालांकि संभावना नहीं) के लिए खाते में एक टाइप रूपांतरण त्रुटि उत्पन्न करता है> 1 मिलान Schemaके समान है कि सत्यापन कोड अक्सर जानबूझकर कैसे फेंकता है क्योंकि मेरा मानना ​​है कि यह अच्छा है और मुझे विश्वास है "सबसे अच्छा अभ्यास '" सभी संभावित रिटर्न परिणामों के लिए खाता है, लेकिन संभावना नहीं है और भले ही यह सिर्फ एक घातक अपवाद उत्पन्न करने के लिए है क्योंकि प्रसंस्करण को रोकने के ज्ञात प्रभाव आमतौर पर अन-ट्रैप्ड त्रुटियों के अज्ञात कैस्केडिंग प्रभावों से बेहतर है। क्योंकि यह अत्यधिक संभावना नहीं है, मुझे नहीं लगता कि यह एक अलग Countचेक + की परेशानी के लायक हैThrow या Try- Catch- Throwफिर भी एक और अधिक उपयोगकर्ता के अनुकूल गंभीर त्रुटि है लेकिन अभी भी गंभीर त्रुटि उत्पन्न करने के लिए।

एसएस 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

एसएस 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

मुझे लगता है कि जब आप केस संवेदी टकराव का उपयोग करते हैं तो एक से अधिक मिलान स्कीमा होना संभव है, लेकिन आपके "त्रुटि हैंडलिंग" के परिणामस्वरूप निम्न त्रुटि होगी: डेटा प्रकार int के लिए varchar मान 'ERROR' परिवर्तित करते समय रूपांतरण विफल।
13:24 पर user247702

@Stijn: यह "बाय डिज़ाइन" के समान है कि सत्यापन कोड अक्सर जानबूझकर कैसे होता है Throw Exception। जैसा कि आपने कहा, ऐसा होने की "संभावना" नहीं है, इसलिए IMHO, यह एक अधिक उपयोगकर्ता के अनुकूल घातक त्रुटि उत्पन्न करने के लिए एक संपूर्ण Try- Catchया अलग-अलग Countजांच के लायक नहीं था , लेकिन इसकी परवाह किए बिना, मैं संभवतः एक घातक त्रुटि चाहता हूं। मुझे विश्वास है और मेरा मानना ​​है कि सभी संभावित रिटर्न परिणामों के लिए यह "सर्वश्रेष्ठ अभ्यास" है, लेकिन संभावना नहीं है और भले ही यह केवल एक घातक अपवाद उत्पन्न करने के लिए है क्योंकि प्रसंस्करण को रोकने के ज्ञात प्रभाव आमतौर पर अन-फंस के अज्ञात कैस्केडिंग प्रभावों से बेहतर है त्रुटियों।
टॉम

यह सब ठीक लगता है, मुझे यकीन नहीं था कि क्या यह जानबूझकर किया गया था :) आपका जवाब कुछ अतिरिक्त स्पष्टीकरण से लाभान्वित हो सकता है, जैसे आपने अपनी टिप्पणी में दिया था।
15:24 पर user247702

@Stijn: मेरा पालतू पेशाब सामान्य जांच के लिए "सबसे अच्छा अभ्यास" है अगर नहीं Select, तो Insert, Updateया Deleteस्टेटमेंट वापस आ गया है या कम से कम # रो की उम्मीद से अधिक प्रभावित है । यहां तक ​​कि अगर (हैं) तो Unique Indexवर्तमान में पंक्तियों की वापसी (प्रभावित) होने की उम्मीद (# 1) सुनिश्चित कर रहे हैं , जो भविष्य में (आकस्मिक रूप से या "जानबूझकर" ") बदल सकता है।
टॉम

1

यदि घटकों का लेआउट इसे अनुमति देता है, तो यह भी काम करता है।

यदि EXISTS (चयन 1 से sys.schemas कहाँ है = 'myschema') SEXEX पर चालू करें 
जाओ
मेरा नाम शकेमा बनाएँ
जाओ 
SET NOEXEC OFF - यदि किसी और प्रसंस्करण की आवश्यकता है।
जाओ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.