2010-07-16 13 views
29

में रिकॉर्ड पहले से मौजूद नहीं है, तो मुझे आश्चर्य है कि तालिका में रिकॉर्ड डालने का कोई तरीका है या नहीं, यदि तालिका में पहले से ही वह रिकॉर्ड नहीं है?केवल रिकॉर्ड दर्ज करें यदि रिकॉर्ड

क्या कोई प्रश्न है जो यह करेगा, या मुझे एक संग्रहीत प्रक्रिया की आवश्यकता होगी?

+4

क्या आपने एक विशिष्टता बाधा जोड़ने पर विचार किया है? – bmm6o

उत्तर

24

आप SQL सर्वर का संस्करण नहीं कहें। एसक्यूएल सर्वर 2008 आप MERGE

नायब उपयोग कर सकते हैं: यह एक Upsert के लिए मर्ज है जो मैं मूल रूप से सोचा था कि सवाल पूछ रहा था उपयोग करने के लिए हमेशा की तरह है, लेकिन यह WHEN MATCHED खंड के बिना और सिर्फ एक WHEN NOT MATCHED खंड इतना काम करता है के साथ मान्य है इस मामले के लिए भी। उदाहरण उपयोग

CREATE TABLE #A(
[id] [int] NOT NULL PRIMARY KEY CLUSTERED, 
[C] [varchar](200) NOT NULL) 


    MERGE #A AS target 
    USING (SELECT 3, 'C') AS source (id, C) 
    ON (target.id = source.id) 
    /*Uncomment for Upsert Semantics 
     WHEN MATCHED THEN 
     UPDATE SET C = source.C */ 
    WHEN NOT MATCHED THEN  
     INSERT (id, C) 
     VALUES (source.id, source.C); 

निष्पादन के संदर्भ में लागत दो लगभग बराबर एक सम्मिलित किया जा रहा है जब देखो ...

Link to plan images for first run

लेकिन इसके दूसरे भाग जब वहाँ मैथ्यू के लिए किया जाना नहीं डालने है पर जवाब कम लागत दिखता है। मुझे यकीन नहीं है कि इसमें सुधार करने का कोई तरीका है या नहीं।

Link to plan images for second run

टेस्ट स्क्रिप्ट

select * 
into #testtable 
from master.dbo.spt_values 

CREATE UNIQUE CLUSTERED INDEX [ix] ON #testtable([type] ASC,[number] ASC,[name] ASC) 


declare @name nvarchar(35)= 'zzz' 
declare @number int = 50 
declare @type nchar(3) = 'A' 
declare @low int 
declare @high int 
declare @status int = 0; 



MERGE #testtable AS target 
USING (SELECT @name, @number, @type, @low, @high, @status) AS source (name, number, [type], low, high, [status]) 
ON (target.[type] = source.[type] AND target.[number] = source.[number] and target.[name] = source.[name]) 
WHEN NOT MATCHED THEN  
INSERT (name, number, [type], low, high, [status]) 
VALUES (source.name, source.number, source.[type], source.low, source.high, source.[status]); 

set @name = 'yyy' 

IF NOT EXISTS 
    (SELECT * 
    FROM #testtable 
    WHERE [type] = @type AND [number] = @number and name = @name) 
    BEGIN 
INSERT INTO #testtable 
(name, number, [type], low, high, [status]) 
VALUES (@name, @number, @type, @low, @high, @status); 
END 
+0

है, मुझे वास्तव में यह सुनिश्चित नहीं है कि मैं वर्तमान में किस संस्करण का उपयोग कर रहा हूं। विलय कैसे काम करेगा? –

+0

@ मेगा - मैंने इस मामले के लिए अपना जवाब अपडेट किया है कि इस मामले के लिए 'MERGE' का उपयोग कैसे किया जा सकता है। मैं निष्पादन आंकड़ों की जांच करूंगा कि 2 दृष्टिकोणों के बीच कोई अंतर है या नहीं। –

+3

समस्या सहीता है, प्रदर्शन नहीं। 'अगर नहीं है (चयन करें ...) INSERT' लोड के तहत डुप्लिकेट त्रुटियों का कारण बनता है, गारंटीकृत। –

13
IF NOT EXISTS 
    (SELECT {Columns} 
    FROM {Table} 
    WHERE {Column1 = SomeValue AND Column2 = SomeOtherVale AND ...}) 
INSERT INTO {Table} {Values} 
+8

-1 क्योंकि यह ** ** उच्च लोड के तहत डुप्लिकेट त्रुटियों को प्राप्त करने का ** सुशोभ तरीका है। चयन और INSERT अलग-अलग समय पर चलता है और दो समवर्ती धागे को एक ही मान डालने का प्रयास करने से रोकने के लिए कुछ भी नहीं है। मार्टिन द्वारा पोस्ट किया गया मेर्ज, एक उचित समाधान –

1

संक्षेप में, आप एक मेज आप की क्षमता प्रदान करने की गारंटी की जरूरत है एक पंक्ति वापस जाने के लिए:

Insert dbo.Table (Col1, Col2, Col3.... 
Select 'Value1', 'Value2', 'Value3',.... 
From Information_Schema.Tables 
Where Table_Schema = 'dbo' 
    And Table_Name = 'Table' 
    And Not Exists (
        Select 1 
        From dbo.Table 
        Where Col1 = 'Foo' 
         And Col2 = 'Bar' 
         And .... 
        ) 

मैं में इस बदलाव देखा है जंगली भी:

Insert Table (Col1, Col2, Col3.... 
Select 'Value1', 'Value2', 'Value3'.... 
From (
     Select 1 As Num 
     ) As Z 
Where Not Exists (
        Select 1 
        From Table 
        Where Col1 = Foo 
         And Col2 = Bar 
         And .... 
        ) 
0

मुझे CONSTRAINT जोड़ने के लिए वोट देना होगा। यह सबसे सरल और सबसे मजबूत जवाब है। मेरा मतलब है, यह देखते हुए कि अन्य उत्तरों कितने जटिल हैं, मैं कहूंगा कि वे सही पाने के लिए बहुत कठिन हैं (और सही रखें)।

डाउनसाइड्स: [1] यह कोड पढ़ने से स्पष्ट नहीं है कि डीबी में विशिष्टता लागू की जाती है [2] क्लाइंट कोड को अपवाद पकड़ने के लिए पता होना चाहिए। दूसरे शब्दों में, आपके पीछे आने वाला लड़का आश्चर्यचकित हो सकता है "यह कभी कैसे काम करता है?"

उस तरफ: मुझे चिंता थी कि अपवाद फेंकना/पकड़ना एक प्रदर्शन हिट था, लेकिन मैंने कुछ परीक्षण किया (SQL सर्वर 2005 पर) और यह महत्वपूर्ण नहीं था।

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