जांचें कि क्या कोई अस्थायी तालिका मौजूद है और अस्थायी तालिका बनाने से पहले मौजूद है या नहीं


662

यदि अस्थायी तालिका मौजूद है और तालिका को फिर से बनाने से पहले मौजूद है, तो यह जांचने के लिए मैं निम्नलिखित कोड का उपयोग कर रहा हूं। यह तब तक ठीक काम करता है जब तक मैं कॉलम नहीं बदलता। यदि मैं बाद में एक कॉलम जोड़ता हूं, तो यह "अमान्य कॉलम" कहते हुए एक त्रुटि देगा। कृपया मुझे बताएं कि मैं क्या गलत कर रहा हूं।

IF OBJECT_ID('tempdb..#Results') IS NOT NULL
    DROP TABLE #Results

CREATE TABLE #Results
(
    Company                CHAR(3),
    StepId                TINYINT,
    FieldId                TINYINT,
)

select company, stepid, fieldid from #Results

--Works fine to this point

IF OBJECT_ID('tempdb..#Results') IS NOT NULL
    DROP TABLE #Results

CREATE TABLE #Results
(
    Company                CHAR(3),
    StepId                TINYINT,
    FieldId                TINYINT,
    NewColumn            NVARCHAR(50)
)

select company, stepid, fieldid, NewColumn from #Results

--Does not work

आप कॉलम कहां जोड़ रहे हैं? क्या आप सटीक कोड पोस्ट कर सकते हैं जो आपको एक त्रुटि दे रहा है?
मैक्रों

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

22
निम्नलिखित पैटर्न का उपयोग करने पर विचार करें BEGIN TRANSACTION; CREATE TABLE #Results; ...; DROP TABLE #Results; COMMIT:। यदि लेनदेन सफल होता है, तो तालिका हटा दी जाएगी। यदि यह विफल रहता है, तो तालिका को भी चला जाएगा (क्योंकि यह लेनदेन के भीतर बनाया गया था)। किसी भी मामले में: तालिका पहले से मौजूद है या नहीं, इसकी जांच करने की आवश्यकता नहीं है।
हेइंजी

1
लगता है जैसे आपको सिर्फ GO स्टेटमेंट की जरूरत है।
sam yi

जवाबों:


733

मैं त्रुटि को पुन: उत्पन्न नहीं कर सकता।

शायद मैं समस्या को नहीं समझ रहा हूँ।

SQL सर्वर 2005 में मेरे लिए निम्न कार्य ठीक है, अतिरिक्त "फू" कॉलम के साथ दूसरे चयन परिणाम में दिखाई दे रहा है:

IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results
GO
CREATE TABLE #Results ( Company CHAR(3), StepId TINYINT, FieldId TINYINT )
GO
select company, stepid, fieldid from #Results
GO
ALTER TABLE #Results ADD foo VARCHAR(50) NULL
GO
select company, stepid, fieldid, foo from #Results
GO
IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results
GO

1
यदि OBJECT_ID ('tempdb .. # परिणाम') पूर्ण नहीं है # परिणाम # परिणाम `बनाएँ #Results (कंपनी CHAR (3), StepId INT) कंपनी का चयन करें, aresults से stepid अब बनाएँ कथन पर वापस जाएं और एक जोड़ें स्तंभ फ़ील्ड को अंत में बदलें। फ़ील्ड को शामिल करने और चलाने के लिए कथन का चयन करें।
श्रीधर

28
'tempdb..#name'वास्तव में मैं क्या जरूरत है। मैं 'dbo.#name'एक मूर्ख की तरह उपयोग कर रहा था । मुझे tempdbभाग मिलता है , लेकिन दोहरे डॉट्स के साथ क्या है?
कॉनरैड.डीन

77
@ कॉनरैड.डीन डबल डॉट .dbo के लिए एक संक्षिप्त नाम है।
deutschZuid

32
@deutschZuid यह कहना अधिक सटीक है कि डबल डॉट उपयोगकर्ता का डिफ़ॉल्ट स्कीमा है, जो आमतौर पर डीबीओ है (जो कि एक महान विचार नहीं है, उपयोगकर्ताओं के लिए डिफ़ॉल्ट स्कीमा को
डीबो बनाता है

8
आपका कोड ओपी से इतना अलग है, कि आपका 'निरस्त नहीं कर सकता' कथन निरर्थक है। मैं आपके लिए खुश हूं कि आपको यह एक अलग तरीके से काम करने के लिए मिला।
गेरार्ड ओनली

85

कथन आदेश का होना चाहिए

  1. तालिका के लिए अल्टर स्टेटमेंट
  2. जाओ
  3. कथन का चयन करें।

बीच में 'गो' के बिना, पूरी बात को एक ही लिपि माना जाएगा और जब कॉलम के लिए चयन कथन दिखाई देगा, तो वह नहीं मिलेगा।

With जीओ ’के साथ, यह स्क्रिप्ट के भाग को part जीओ’ तक एक ही बैच के रूप में मानेगा और the जीओ ’के बाद क्वेरी में आने से पहले निष्पादित करेगा।


7
इसे सही उत्तर के रूप में चिह्नित किया जाना चाहिए। ऐसा नहीं है कि सेलेक्ट वास्तव में बनाने की मेज से पहले चलने वाला है, यह है कि इसे पार्स किया जा रहा है और चलाने से पहले एक त्रुटि फेंक रहा है, क्योंकि एक मौजूदा तालिका है जिसे #Results कहा जाता है जिसमें अभी तक FieldId कॉलम नहीं है समय का चयन करते हैं। इसमें एक GO जोड़कर क्वेरी को बैचों में अलग किया जाता है, जो प्रत्येक पार्स होती हैं और अलग-अलग चलती हैं।
दावोस

2
मैं इस और शीर्ष उत्तर के बीच वोटों में असमानता पर विश्वास नहीं कर सकता, जिसने कोड को इतना बदल दिया - बिना यह बताए कि क्यों - यह प्रतिक्रिया के रूप में अर्थहीन था।
अंडरस्कोर_ड

63

इसके बजाय droppingआप कर सकते हैं truncateऔर पुन: उपयोग अस्थायी तालिका बनाने के लिए

IF OBJECT_ID('tempdb..#Results') IS NOT NULL
    Truncate TABLE #Results
else
    CREATE TABLE #Results
    (
        Company             CHAR(3),
        StepId              TINYINT,
        FieldId             TINYINT,
    )

यदि आप उपयोग कर रहे हैं Sql Server 2016या Azure Sql Databaseफिर अस्थायी तालिका को छोड़ने और इसे फिर से बनाने के लिए नीचे दिए गए सिंटैक्स का उपयोग करें। अधिक जानकारी यहाँ MSDN

वाक्य - विन्यास

ड्रॉप टेबल [IF EXISTS] [database_name। [स्कीमा_नाम]। | स्कीमा_नाम। ] table_name [, ... n]

प्रश्न:

DROP TABLE IF EXISTS tempdb.dbo.#Results
CREATE TABLE #Results
  (
   Company             CHAR(3),
   StepId              TINYINT,
   FieldId             TINYINT,
  )

ऐसा लगता है कि यह truncate/reuseविधि DROP TABLE IF EXISTSऑन Sql Server 2016और Azure Sql Databaseसाथ ही अधिक कुशल होगी । क्या यह मामला नही है?
जादव

@prdp आप DROP TABLE IF ExistsSQL 2016 या Azure के लिए क्यों सुझाव देते हैं ? सिंटैक्स SQL ​​2008 शुरू करके उपलब्ध है। अपने उत्तर में MSDN लिंक देखें? प्रदर्शन कारक?
हैप्पीटाउन

4
कोई बात नहीं। मुझे अब एहसास हुआ, DROP TABLEएसक्यूएल सर्वर 2008 से समर्थित है, लेकिन IF EXISTSक्लॉज 2016 में पेश किया गया था।
हैप्पीटाउन

1
मैं उपयोग करता हूं INTO: dbo से * INTO #HistoricoUserTable का चयन करें। HistoricoUser
Kiquenet

54

मुझे लगता है कि इस समस्या को आपको बैचों में निष्पादन को अलग करने के लिए GO स्टेटमेंट को जोड़ने की आवश्यकता है। दूसरे ड्रॉप स्क्रिप्ट के रूप में यानी IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Resultsटेम्पर्ड टेबल को सिंगल बैच का हिस्सा नहीं बनाया गया। क्या आप कृपया नीचे दी गई स्क्रिप्ट को आज़मा सकते हैं।

IF OBJECT_ID('tempdb..#Results') IS NOT NULL
    DROP TABLE #Results

CREATE TABLE #Results
(
    Company                CHAR(3),
    StepId                TINYINT,
    FieldId                TINYINT,
)

GO

select company, stepid, fieldid from #Results

IF OBJECT_ID('tempdb..#Results') IS NOT NULL
DROP TABLE #Results

CREATE TABLE #Results
(
    Company                CHAR(3),
    StepId                TINYINT,
    FieldId                TINYINT,
    NewColumn            NVARCHAR(50)
)

GO

select company, stepid, fieldid, NewColumn from #Results

1
टिप्पणी का; tempdb..ऊपर दिए गए कोड में यह बहुत महत्वपूर्ण है। इसे अपने अस्थायी तालिका नाम से पहले करने की आवश्यकता है। केवल जाँच OBJECT_ID('#Results')करना पर्याप्त नहीं है। अस्थायी तालिकाएँ TempDB डेटाबेस में संग्रहीत की जाती हैं। प्रति Microsoft: TempDB सिस्टम डेटाबेस एक वैश्विक संसाधन है जो SQL सर्वर की आवृत्ति से जुड़े सभी उपयोगकर्ताओं के लिए उपलब्ध है या SQL डेटाबेस से जुड़ा है
iCode

धन्यवाद, @ आईकोड। यह टेम्‍प टेबलों को गिराने की कुंजी है: इस पर काम tempdbकरना होगा या यह नहीं चलेगी।
एलेक्स

37

इसे कोड की एक पंक्ति के साथ पूरा किया जा सकता है:

IF OBJECT_ID('tempdb..#tempTableName') IS NOT NULL DROP TABLE #tempTableName;   

1
मुझे इसे हर दिन देखना चाहिए
Ab Bennett

28

इसने मेरे लिए काम किया: social.msdn.microsoft.com/Forums/en/transactsql/thread/02c6da90-954d-487d-a823-e24b891ec1b0?profitable-required

if exists (
    select  * from tempdb.dbo.sysobjects o
    where o.xtype in ('U') 

   and o.id = object_id(N'tempdb..#tempTable')
)
DROP TABLE #tempTable;

1
यह सशर्त तालिका ड्रॉप के लिए बस अलग वाक्यविन्यास है। यह दिलचस्प है, लेकिन ओपी के सवाल को हल नहीं करता है, और इसमें से अधिकांश बेमानी है। यदि आप केवल OBJECT_ID (N'tempdb .. # Results ') की जांच करते हैं, तो शून्य नहीं है, तो यह साबित करने के लिए पर्याप्त है कि ऑब्जेक्ट पहले से मौजूद है।
दावोस

21

मेरी तरफ से बस एक छोटी सी टिप्पणी क्योंकि मेरे OBJECT_IDलिए काम नहीं करता है। यह हमेशा वही लौटाता है

`# टैम्पटेबल मौजूद नहीं है

..even हालांकि यह करता है अस्तित्व। मैंने अभी पाया कि इसे अलग-अलग नाम से संग्रहीत किया गया है ( _जैसे अंडरस्कोर द्वारा पोस्टफ़िक्स )

#tempTable________

यह मेरे लिए अच्छा काम करता है:

IF EXISTS(SELECT [name] FROM tempdb.sys.tables WHERE [name] like '#tempTable%') BEGIN
   DROP TABLE #tempTable;
END;

6
सावधानी: वह कोड किसी तालिका का पता लगाएगा यदि वह किसी थ्रेड द्वारा बनाई गई थी। एक # टेम्प टेबलों को प्रति थ्रेड / कॉलर के लिए अलग से एक संग्रहीत खरीद के लिए बनाया जाता है, यही वजह है कि नाम में अंडरस्कोर इतना है कि एक अलग प्रति प्रति थ्रेड / प्रक्रिया में मौजूद है। Object_ID को वर्तमान थ्रेड के लिए ठीक काम करना चाहिए, जब तक आप SQL 2005 या उसके बाद के हैं।
22

12

यदि आप SQL सर्वर (2016+) के नए संस्करणों में से किसी एक का उपयोग कर रहे हैं, तो अब आप नीचे दिए गए सिंटैक्स का उपयोग कर सकते हैं।

DROP TABLE IF EXISTS schema.yourtable(even temporary tables #...)

1
मैं SSMS 17.3 का उपयोग कर रहा हूं और यह देता हैIncorrect syntax near the keyword 'IF'.
StingyJack

7
@StingyJack क्योंकि SQL सिंटैक्स SSMS संस्करण से संबंधित नहीं है, लेकिन SQL सर्वर संस्करण संबंधित है। यह IF [NOT] EXISTSखंड SQL Server 2016 से उपलब्ध है। इससे कोई फर्क नहीं पड़ता कि आप कौन सा SSMS संस्करण उपयोग कर रहे हैं।
Pred

10

pmac72 बैचों में क्वेरी को तोड़ने और ALTER का उपयोग करने के लिए GO का उपयोग कर रहा है।

आप एक ही बैच चलाते हुए दिखाई देते हैं लेकिन इसे बदलने के बाद इसे दो बार चलाते हैं: DROP ... CREATE ... संपादित करें ... DROP ... CREAT ।।

शायद अपना सटीक कोड पोस्ट करें ताकि हम देख सकें कि क्या चल रहा है।


7

मैं आमतौर पर इस त्रुटि को मारता हूं जब मैंने पहले से ही अस्थायी तालिका बनाई है; कोड जो त्रुटियों के लिए एसक्यूएल स्टेटमेंट की जांच करता है, "पुरानी" अस्थायी तालिका को जगह में देखता है और बाद के वक्तव्यों में स्तंभों की संख्या पर एक मिसकाउंट देता है, जैसे कि टेम्प टेबल को कभी नहीं छोड़ा गया था।

पहले से ही कम स्तंभों के साथ एक संस्करण बनाने के बाद एक अस्थायी तालिका में स्तंभों की संख्या बदलने के बाद, तालिका को गिरा दें और अपनी क्वेरी चलाएं।


6

मैंने हाल ही में एक डीबीए को इस तरह से कुछ करते देखा है:

begin try
    drop table #temp
end try

begin catch 
    print 'table does not exist'
end catch 

create table #temp(a int, b int)

2
यह प्रयास विवरण तालिका को छोड़ने का प्रयास करते समय होने वाली अन्य त्रुटियों को पकड़ सकता है। यह कोड मानता है कि केवल कारण विफल हो जाएगा क्योंकि तालिका मौजूद नहीं है। यह शायद ज्यादातर समय काम करेगा, लेकिन मैं इसकी गारंटी नहीं देता। यदि किसी अन्य कारण से कोशिश कथन विफल हो जाता है, तो तालिका बनाते समय आपको एक त्रुटि मिलेगी, क्योंकि इससे तालिका को छोड़ने के साथ वास्तविक समस्या का सामना करना पड़ता है।
दावोस

यह काम करता है लेकिन बुरा मैं स्मार्ट और सही समाधान है जब वहाँ मुश्किल रास्ता प्रोत्साहित नहीं करते हैं। और यह भी, हालांकि ओपी ने 2005 संस्करण को निर्दिष्ट किया था, कोशिश करें कि ब्लॉक ब्लॉक पुराने संस्करणों में समर्थित नहीं है
dejjub-AIS

इसके साथ अन्य समस्या है कोशिश / पकड़ बनाम तर्क का उपयोग करने की विचारधारा। आप यहाँ अधिक बहस देख सकते हैं: stackoverflow.com/questions/17335217/try-catch-or-if-statement/…
logixologist

3

मेरा कोड एक Sourceतालिका का उपयोग करता है जो बदलता है, और एक Destinationतालिका जो उन परिवर्तनों से मेल खाती है।

-- 
-- Sample SQL to update only rows in a "Destination" Table
--  based on only rows that have changed in a "Source" table
--


--
-- Drop and Create a Temp Table to use as the "Source" Table
--
IF OBJECT_ID('tempdb..#tSource') IS NOT NULL drop table #tSource
create table #tSource (Col1 int, Col2 int, Col3 int, Col4 int)

--
-- Insert some values into the source
--
Insert #tSource (Col1, Col2, Col3, Col4) Values(1,1,1,1)
Insert #tSource (Col1, Col2, Col3, Col4) Values(2,1,1,2)
Insert #tSource (Col1, Col2, Col3, Col4) Values(3,1,1,3)
Insert #tSource (Col1, Col2, Col3, Col4) Values(4,1,1,4)
Insert #tSource (Col1, Col2, Col3, Col4) Values(5,1,1,5)
Insert #tSource (Col1, Col2, Col3, Col4) Values(6,1,1,6)

--
-- Drop and Create a Temp Table to use as the "Destination" Table
--
IF OBJECT_ID('tempdb..#tDest') IS NOT NULL drop Table #tDest
create table #tDest (Col1 int, Col2 int, Col3 int, Col4 int)

--
-- Add all Rows from the Source to the Destination
--
Insert #tDest
Select Col1, Col2, Col3, Col4 from #tSource


--
-- Look at both tables to see that they are the same
--
select *
from #tSource
Select *
from #tDest

--
-- Make some changes to the Source
--
update #tSource
    Set Col3=19
    Where Col1=1
update #tSource
    Set Col3=29
    Where Col1=2
update #tSource
    Set Col2=38
    Where Col1=3
update #tSource
    Set Col2=48
    Where Col1=4

--
-- Look at the Differences
-- Note: Only 4 rows are different. 2 Rows have remained the same.
--
Select Col1, Col2, Col3, Col4
from #tSource
except
Select Col1, Col2, Col3, Col4
from #tDest

--
-- Update only the rows that have changed
-- Note: I am using Col1 like an ID column
--
Update #tDest
    Set Col2=S.Col2,
        Col3=S.Col3,
        Col4=S.Col4
From    (   Select Col1, Col2, Col3, Col4
            from #tSource
            except
            Select Col1, Col2, Col3, Col4
            from #tDest
        ) S
Where #tDest.Col1=S.Col1 

--
-- Look at the tables again to see that
--  the destination table has changed to match
--  the source table.

select *
from #tSource
Select *
from #tDest

--
-- Clean Up
--
drop table #tSource
drop table #tDest

1

हां, "अमान्य कॉलम" यह त्रुटि लाइन "कंपनी, स्टेपिड, फील्डिड, न्यूकालेमेंट से #Results" से उठाया गया है।

T-sql को चलाने के दो चरण हैं,

सबसे पहले, पार्सिंग, इस चरण में sql सर्वर आपके द्वारा तालिका के स्तंभ सहित सबमेटेड sql स्ट्रिंग के सुधार की जाँच करता है, और सबसे तेज़ पुनर्प्राप्ति के लिए आपकी क्वेरी को अनुकूलित करता है।

दूसरा, चल रहा है, डेटा पुनर्प्राप्त कर रहा है।

यदि तालिका #Results मौजूद है, तो पार्सिंग प्रक्रिया आपके द्वारा निर्दिष्ट कॉलम की जाँच करेगी या नहीं, अन्यथा (तालिका मौजूद नहीं है) पार्सिंग आपके द्वारा निर्दिष्ट किए गए चेकिंग कॉलम को पास कर दिया जाएगा।


0

जब आप किसी अस्थायी तालिका में एक कॉलम बदलते हैं, तो आपको क्वेरी को फिर से चलाने से पहले तालिका को छोड़ना होगा। (हां, यह कष्टप्रद है। बस आपको क्या करना है।)

मैंने हमेशा यह माना है क्योंकि क्वेरी चलाने से पहले पार्सर द्वारा "अमान्य कॉलम" चेक किया जाता है, इसलिए यह तालिका में गिराए जाने से पहले स्तंभों पर आधारित है ..... और यही pnbs ने भी कहा है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.