2013-04-23 5 views
8

मैं SQL स्क्रिप्ट विकसित कर रहा हूँ, SSMS, जो डेटाबेस में कुछ परिवर्तन करता है का उपयोग करते हुए:"अवैध स्तंभ नाम" त्रुटि जब डालने बुला के बाद तालिका बनाई

USE MyDatabase; 

BEGIN TRANSACTION; 

-- some statements 

PRINT(N'#1'); 

IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = N'dbo' AND TABLE_NAME = N'Table1' AND COLUMN_NAME = 'Table2_Id')) 
BEGIN 
    ALTER TABLE [dbo].[Table1] DROP CONSTRAINT [FK_Table1_Table2_Table2_Id]; 
    ALTER TABLE [dbo].[Table1] DROP COLUMN [Table2_Id]; 
    DROP TABLE [dbo].[Table2]; 

    PRINT(N'Table2 was dropped.'); 
END 

PRINT(N'#2'); 

IF (NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = N'dbo' AND TABLE_NAME = N'Table2')) 
BEGIN 
    CREATE TABLE [dbo].[Table2] 
    (
     [Id] INT NOT NULL PRIMARY KEY IDENTITY, 
     [Number] INT NOT NULL UNIQUE, 
     [Name] NVARCHAR(200) NOT NULL, 
     [RowVersion] TIMESTAMP NOT NULL 
    ); 
PRINT(N'Table2 was re-created.'); 
    INSERT INTO [dbo].[Table2]([Number], [Name]) VALUES(-1, N'Default value'); 
PRINT(N'Default value was inserted in Table2.'); 
END 

-- some statements 

COMMIT TRANSACTION; 

तो Table1 एक स्तंभ है, Table2_Id नाम है, तो डेटाबेस दो टेबल (Table1 और Table2) और उनके बीच एक विदेशी महत्वपूर्ण संबंध है। उस स्थिति में, मुझे यह करना होगा:

  • विदेशी कुंजी रिलेशनशिप ड्रॉप FK_Table1_Table2_Table2_Id;
  • ड्रॉप विदेशी कुंजी कॉलम Table1.Table2_Id;
  • ड्रॉप Table2;
  • नई तालिका स्कीमा का उपयोग करके Table2 फिर से बनाएं;
  • Table2 में कुछ डिफ़ॉल्ट मान डालें।

जब मैं इस स्क्रिप्ट निष्पादित करने के लिए कोशिश कर रहा हूँ, मैं इन त्रुटियों को हो रही है:

संदेश 207, स्तर 16, राज्य 1, पंक्ति 262 अमान्य स्तंभ नाम 'नंबर'।
संदेश 207, स्तर 16, राज्य 1, रेखा 262 अमान्य कॉलम नाम 'नाम'।

ऐसा लगता है कि एसक्यूएल सर्वर Table2 के लिए पुराने स्कीमा का उपयोग करता है (जो वास्तव में नहीं ये स्तंभ है), लेकिन यह कैसे संभव हो तो मेज सिर्फ नए स्कीमा के साथ बनाया गया है है?

मैं क्या गलत कर रहा हूं?

सर्वर संस्करण SQL सर्वर 2012 (SP1) - 11.0.3128.0 (X64) है।

अद्यतन

मैंने PRINT कॉल (ऊपर लिपि देखें) जोड़ा है। त्रुटि संदेशों को छोड़कर, संदेश विंडो में कुछ भी नहीं है। तो, लिपि को निष्पादित नहीं किया जा रहा है ... क्या चल रहा है ??

उत्तर

11

SQL सर्वर पूरे बैच को संकलित करने का प्रयास करता है। यदि तालिका पहले से मौजूद है तो यह पूर्व-मौजूदा परिभाषा के अनुसार संकलित होगी। नए कॉलम का संदर्भ देने वाला बयान संकलित नहीं होता है और इसलिए बैच कभी निष्पादित नहीं होता है।

आपको नई बैच में नई परिभाषा का उपयोग करके बयानों को समूहबद्ध करने की आवश्यकता है। आप SSMS में यह चला रहे हैं बस सम्मिलित एक GO

USE MyDatabase; 

BEGIN TRANSACTION; 

-- some statements 

PRINT(N'#1'); 

IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = N'dbo' AND TABLE_NAME = N'Table1' AND COLUMN_NAME = 'Table2_Id')) 
BEGIN 
    ALTER TABLE [dbo].[Table1] DROP CONSTRAINT [FK_Table1_Table2_Table2_Id]; 
    ALTER TABLE [dbo].[Table1] DROP COLUMN [Table2_Id]; 
    DROP TABLE [dbo].[Table2]; 

    PRINT(N'Table2 was dropped.'); 
END 

GO 

PRINT(N'#2'); 

IF (NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = N'dbo' AND TABLE_NAME = N'Table2')) 
BEGIN 
    CREATE TABLE [dbo].[Table2] 
    (
     [Id] INT NOT NULL PRIMARY KEY IDENTITY, 
     [Number] INT NOT NULL UNIQUE, 
     [Name] NVARCHAR(200) NOT NULL, 
     [RowVersion] TIMESTAMP NOT NULL 
    ); 
PRINT(N'Table2 was re-created.'); 
    INSERT INTO [dbo].[Table2]([Number], [Name]) VALUES(-1, N'Default value'); 
PRINT(N'Default value was inserted in Table2.'); 
END 

COMMIT 

नहीं तो आप

EXEC(N'INSERT INTO [dbo].[Table2]([Number], [Name]) VALUES(-1, N''Default value'');') 
+0

स्पष्टीकरण के लिए धन्यवाद एक बच्चे बैच में हमलावर लाइन चला सकते हैं ... यह - "तालिका में पहले से ही मौजूद है, तो तो यह पूर्व-मौजूदा परिभाषा के अनुसार संकलित होगा "- एक सबसे बेवकूफ और स्पष्ट रणनीति नहीं है जिसे मैं कभी कल्पना कर सकता हूं ... 'जाओ' एक अच्छा विकल्प नहीं है, लिपि बल्कि बड़ी है, और कुछ चर हैं, स्क्रिप्ट के शीर्ष पर घोषित किया गया, जो पूरी लिपि में व्यापक रूप से उपयोग किया जाता था। वैसे भी, धन्यवाद, मैं कामकाज के बारे में सोचूंगा। – Dennis

+0

@ डेनिस यदि आप अपने चर को खोना नहीं चाहते हैं, तो मैं विभिन्न संग्रहित प्रक्रियाओं में अलग-अलग बैचों (ड्रॉप/निर्माण टेबल) को विभाजित करने का सुझाव दूंगा, फिर उन्हें मुख्य संग्रहीत प्रक्रिया में लपेटना होगा। –

संबंधित मुद्दे