2011-01-28 12 views
6

पृष्ठभूमि: एक संग्रहीत प्रक्रिया है जो किसी दिए गए नाम की अस्थायी तालिका के साथ "सामान" करती है। प्रक्रिया सामान्य है कि यह अस्थायी तालिका की स्कीमा का निरीक्षण करती है और फिर स्कीमा के आधार पर अलग-अलग "सामान" करती है। मैं समझता हूं कि यह थोड़ा अजीब है लेकिन मैं इसे बदलने के लिए अनिच्छुक हूं क्योंकि यह सभी स्थितियों में ठीक काम करता है ....SQL सर्वर क्यों सोचता है कि एक Temp तालिका पहले से मौजूद है जब यह नहीं है?

यदि मेरे पास एक संग्रहीत प्रक्रिया है जो एक temp तालिका के लिए दो अलग-अलग स्कीमा बनाती है वही नाम। तर्कसंगत रूप से यह केवल आईएफ की शाखा के आधार पर एक अस्थायी तालिका बनाता है। समस्या यह है कि जब sproc एसक्यूएल सर्वर द्वारा जाँच की है ऐसा लगता है जैसे कि यह अगर के दोनों किनारों मूल्यांकन कर रही है है

तो यह एसक्यूएल में विफल रहता है (अगर यह SQL सिंटैक्स की जाँच कर रहा है जो समझ में आता है।):

IF (1=1) 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL 
    ) 
END 
ELSE 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL, 
     c BIGINT NOT NULL 
    ) 
END 

--exec SomeProcedureWhichDoesStuffWith#Test 

DROP TABLE #test 
निम्न त्रुटि के साथ

:

Msg 2714, Level 16, State 1, Line 14
There is already an object named '#test' in the database.

आईएफएस अंदर ड्रॉप तालिका का कोई संयोजन (पहले या बाद में बनाने तालिका DDL) एसक्यूएल चेकर को पूरा करने लगता है।

कोई विचार मैं यह कैसे कर सकता हूं? क्या मैं, उदाहरण के लिए, एसक्यूएल को सिंटैक्स चेक नहीं करने के लिए कह सकता हूं और केवल स्पोक को स्वीकार कर सकता हूं?

उत्तर

6

यह एक सीमा है। डायनामिक एसक्यूएल या तो काम नहीं करेगा क्योंकि #tmp नए सत्र में बनाया जाएगा और तुरंत खो जाएगा। सटीक स्निपेट दिखाया गया है के लिए, यह एक ही बैच के भीतर एक ही

CREATE TABLE #test 
(
    a BIGINT NOT NULL, 
    b BIGINT NOT NULL 
) 

IF not (1=1) 
    ALTER TABLE #test ADD c BIGINT NOT NULL 

वहाँ दो का निर्माण नहीं किया जा सकता है करता है .. #name, लेकिन यह भी सामान्य रूप

IF (1=1) 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL 
    ); 
END 
GO 

IF NOT (1=1) 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL, 
     c BIGINT NOT NULL 
    ) 
END 
0

के बाद से मुझे नहीं में काम करेंगे एसक्यूएल 2008 है, मैं इसका परीक्षण नहीं कर सकता। हालांकि जहां तक ​​मुझे पता है, यह स्पष्ट रूप से temp तालिकाओं के साथ एक पार्सर मुद्दा है। एक ही इस सुलझाने के लिए सामान्य टेबल

के साथ ठीक काम करेगा, बस तार्किक GO बयान

के साथ अपने कोड को विभाजित आदर्श: अस्थायी तालिकाओं के होने की जाँच से पहले आप अपने अस्थायी टेबल बना, उन्हें छोड़ अगर वे मौजूद हैं, एक जाना आग, फिर से अस्थायी तालिकाओं का निर्माण करते हैं, एक जाना है, तो किसी भी पोस्ट प्रोसेसिंग आग, एक जाना आग, अंत में उन्हें फिर से ड्रॉप और आग पिछले जाना


आप भी कोशिश करते हैं और उपयोग करने के लिए चाहते हो सकता है यदि ऊपर है तो temp तालिकाओं के बजाय तालिका चर आपके लिए हल नहीं करता है

+0

हाँ धन्यवाद। दुर्भाग्य से यह एक स्पोक में टेबल बना रहा है, इसलिए इसे एक ही बैच में होना चाहिए (इसलिए यह गो पर नहीं है)। –

0

आप कभी भी "धोखा" हो सकता है:

DECLARE @SQL VARCHAR(200) 

IF (1=1) 
BEGIN 
    SET @SQL = 'CREATE TABLE #Temp  ' + 
       '(      ' + 
       ' a BIGINT NOT NULL, ' + 
       ' b BIGINT NOT NULL ' + 
       ')      ' 
END 
ELSE 
BEGIN 
    SET @SQL = 'CREATE TABLE #Temp  ' + 
       '(      ' + 
       ' a BIGINT NOT NULL, ' + 
       ' b BIGINT NOT NULL, ' + 
       ' c BIGINT NOT NULL ' + 
       ')      ' 
END 

EXEC SP_EXECUTESQL @SQL 
+0

यह काम नहीं करेगा क्योंकि यह तुरंत दायरे से बाहर निकल जाएगा और बाहरी लिपि में प्रयोग योग्य नहीं होगा इसे वैश्विक अस्थायी तालिका होने की आवश्यकता होगी या अस्थायी एसक्यूएल के सभी उपयोगों को गतिशील एसक्यूएल में होना आवश्यक होगा। –

2

#test के बजाय, एक पूरी तरह से योग्य नाम का उपयोग करें। उदाहरण के लिए,

[tempdb].[dbo].[temptable] 

मैं इस छोटे चाल यहाँ Insert result of executing dynamic query into a table सीखा है।

इंटेलिसेंस शिकायत करेगा लेकिन आप अभी भी संग्रहित प्रक्रिया को बनाने या बदलने में सक्षम होंगे।

जब यह के साथ किया, इसे छोड़ करना न भूलें: जानकारी के लिए

DROP TABLE [tempdb].[dbo].[temptable] 
संबंधित मुद्दे