2010-05-03 20 views
41

अद्यतन करें मैं SQL सर्वर डेटाबेस अद्यतन स्क्रिप्ट लिखने की कोशिश कर रहा हूं। मैं किसी तालिका में कॉलम के अस्तित्व के लिए परीक्षण करना चाहता हूं, फिर यदि यह मौजूद नहीं है तो डिफ़ॉल्ट मान वाले कॉलम को जोड़ें, और अंत में उसी तालिका में किसी भिन्न कॉलम के वर्तमान मान के आधार पर उस कॉलम को अपडेट करें। मैं चाहता हूं कि यह स्क्रिप्ट कई बार चलने योग्य हो, पहली बार तालिका को अद्यतन करने के बाद और बाद में चलने पर स्क्रिप्ट को अनदेखा किया जाना चाहिए। मेरे स्क्रिप्ट वर्तमान में ऐसा दिखाई देता है:टेस्ट कॉलम मौजूद है, कॉलम जोड़ें, और कॉलम

IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = 'PurchaseOrder' AND COLUMN_NAME = 'IsDownloadable') 
BEGIN 

ALTER TABLE [dbo].[PurchaseOrder] ADD [IsDownloadable] bit NOT NULL DEFAULT 0 

UPDATE [dbo].[PurchaseOrder] SET [IsDownloadable] = 1 WHERE [Ref] IS NOT NULL 

END 

एसक्यूएल सर्वर रिटर्न त्रुटि "अमान्य स्तंभ नाम 'IsDownloadable'", यानी मैं इससे पहले कि मैं स्तंभ अद्यतन कर सकते हैं DDL प्रतिबद्ध करने के लिए की जरूरत है। मैंने विभिन्न क्रमपरिवर्तनों की कोशिश की है लेकिन मुझे कहीं भी तेज़ नहीं मिल रहा है।

उत्तर

75

यह स्क्रिप्ट सफलतापूर्वक चला नहीं होगा जब तक कॉलम पहले से मौजूद है, जो ठीक है जब आप को इसकी आवश्यकता नहीं है।

SQL स्क्रिप्ट को निष्पादित किए जाने से पहले पार्स किया जाना चाहिए। यदि स्क्रिप्ट पार्स किए जाने पर कॉलम मौजूद नहीं है, तो पार्सिंग विफल हो जाएगी। इससे कोई फर्क नहीं पड़ता कि आपकी स्क्रिप्ट बाद में कॉलम बनाती है; पार्सर को यह जानने का कोई तरीका नहीं है।

यदि आप अभी तक जोड़े गए कॉलम तक पहुंचना चाहते हैं तो आपको GO कथन (बैच सेपरेटर) डालना होगा। हालांकि, एक बार ऐसा करने के बाद, आप पिछले बैच से किसी भी नियंत्रण प्रवाह या चर को बनाए रख सकते हैं - यह दो अलग-अलग स्क्रिप्ट चलाने की तरह है। यह एक ही समय में सशर्त रूप से डीडीएल और डीएमएल दोनों को करना मुश्किल बनाता है।

IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = 'PurchaseOrder' AND COLUMN_NAME = 'IsDownloadable') 
BEGIN 

    ALTER TABLE [dbo].[PurchaseOrder] ADD 
     [IsDownloadable] bit NOT NULL DEFAULT 0 

    EXEC sp_executesql 
     N'UPDATE [dbo].[PurchaseOrder] SET [IsDownloadable] = 1 WHERE [Ref] IS NOT NULL' 

END 
+0

ऐसा किया, धन्यवाद। –

+3

पूर्ण स्पष्टीकरण, धन्यवाद – Vladimirs

+1

बिल्कुल वही जो मैं खोज रहा था। इसके लिए शुक्रिया। –

-1

अल्टर टेबल के बाद "जाओ" कथन जोड़ने का प्रयास करें।

यह मेरे लिए खबर थी, लेकिन यह here कहता है कि बैच (जीओ से पहले जो लोग) में सभी बयान एक प्रश्न योजना में संकलित किए गए हैं।) एसक्यूएल में कोई भी नहीं है, पूरी योजना प्रभावी रूप से एक प्रश्न है।

संपादित करें: चूंकि GO एक सिंटैक्स त्रुटि (जो मेरे लिए अजीब लग रहा था) देता है, मैं कुछ इसी तरह बनाया है, और पाया यह काम किया

declare @doUpdate bit; 

SELECT @doUpdate = 0; 

IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = 'PurchaseOrder' AND COLUMN_NAME = 'IsDownloadable') 
BEGIN 
SELECT @doUpdate=1 
END 

IF @doUpdate<>0 
    ALTER TABLE [dbo].[PurchaseOrder] ADD [IsDownloadable] bit NOT NULL DEFAULT 0 

IF @doUpdate<>0 
    UPDATE [dbo].[PurchaseOrder] SET [IsDownloadable] = 1 WHERE [Ref]=0 

COMMIT TRAN 
+0

'0' के पास गलत वाक्यविन्यास। यह उन क्रमिक क्रमों में से एक है जिन्हें मैंने पहले ही कोशिश की है। –

1
:

सरलतम वैकल्पिक हल है, जो मैं शायद आप के लिए सलाह देते हैं, क्योंकि आपके DML बहुत जटिल नहीं है, गतिशील एसक्यूएल उपयोग करने के लिए है, जो पार्सर "क्रम" जब तक पार्स करने के लिए कोशिश नहीं करेंगे

मैं अक्सर इस समस्या से नाराज हूं, और दुर्भाग्यवश Aaronaught's answer में सुझाया गया समाधान जल्दी से गन्दा हो जाता है जब @parameters और 'तार' शामिल होते हैं। हालांकि, मुझे समानार्थी शब्द के उपयोग का शोषण करके एक अलग कामकाज मिला है:

IF(COL_LENGTH('MyTable', 'NewCol') IS NULL) 
BEGIN 
    ALTER TABLE MyTable ADD NewCol VARCHAR(16) NULL; 

    CREATE SYNONYM hack FOR MyTable; 
    UPDATE hack SET NewCol = 'Hello ' + OldCol; 
    DROP SYNONYM hack; 

    ALTER TABLE MyTable ALTER COLUMN NewCol VARCHAR(16) NOT NULL; 
END