INSERT स्टेटमेंट (SQL सर्वर) के इनटू क्लॉज में स्रोत कॉलम का उपयोग करना


16

मैं एक बैच प्रोसेसिंग इंसर्ट स्टेटमेंट लिख रहा हूं और प्रत्येक सम्मिलित पंक्ति के लिए SCOPE_IDENTITY () को स्वयं आइटम के माध्यम से लूप करने के बजाय सम्मिलित ID का ट्रैक रखने के लिए एक अस्थायी तालिका का उपयोग करना चाहूंगा।

जिस डेटा को डालने की जरूरत है (अस्थायी) आईडी उसे अन्य डेटा से लिंक कर रही है जिसे अन्य तालिका में भी डाला जाना चाहिए, इसलिए मुझे वास्तविक आईडी और अस्थायी आईडी का क्रॉस संदर्भ चाहिए।

यह मेरे लिए अब तक का एक उदाहरण है:

-- The existing table 
DECLARE @MyTable TABLE (ID INT IDENTITY(1,1), [Name] NVARCHAR(MAX));

-- My data I want to insert
DECLARE @MyInsertData TABLE (ID INT, [Name] NVARCHAR(MAX));
INSERT INTO @MyInsertData ( ID,Name)
VALUES ( -1 , 'bla'),(-2,'test'),(-3,'last');

DECLARE @MyCrossRef TABLE ([NewId] INT, OldId INT);

INSERT INTO @MyTable ( [Name] )
   OUTPUT Inserted.ID, INS.ID INTO @MyCrossRef
   SELECT [NAME] FROM @MyInsertData INS

-- Check the result
SELECT * FROM @MyCrossRef

समस्या यह है कि मैं ID को स्वीकार करने के लिए OUTPUT INTO क्लॉज़ प्राप्त नहीं कर सकता, मैंने कोशिश की है @MyInsertData.IDऔर अन्य तरकीबें अपने आप में तालिका में शामिल हो रही हैं, लेकिन कुछ भी काम नहीं करता है।

जवाबों:


28

वास्तव में, आप अपने INSERTको बदलकर एक ही चीज हासिल कर सकते हैं MERGE। जबकि MERGEकथन वास्तव में SQL सर्वर में "upserts" करने के लिए एक बहुत ही साफ-सुथरा तरीका है, केवल डालने के उद्देश्य से इसका उपयोग करने से आपको रोकने के लिए कुछ भी नहीं है:

-- The existing table 
DECLARE @MyTable TABLE (ID INT IDENTITY(1,1), [Name] NVARCHAR(MAX));

-- My data I want to insert
DECLARE @MyInsertData TABLE (ID INT, [Name] NVARCHAR(MAX));
INSERT INTO @MyInsertData ( ID,Name)
VALUES ( -1 , 'bla'),(-2,'test'),(-3,'last');

DECLARE @MyCrossRef TABLE ([NewId] INT, OldId INT);

MERGE INTO @MyTable AS dest
USING @MyInsertData AS ins ON 1=0   -- always false

WHEN NOT MATCHED BY TARGET          -- happens for every row, because 1 is never 0
    THEN INSERT ([Name])
         VALUES (ins.[NAME])

OUTPUT inserted.ID, ins.ID
INTO @MyCrossRef (NewId, OldId);

-- Check the result
SELECT * FROM @MyCrossRef

इसके बारे में एक अच्छी बात MERGEयह है कि यह आपको स्रोत स्तंभों के साथ-साथ खंड में अंतर्निहित insertedऔर deletedतालिकाओं तक पहुंचने की अनुमति देता है OUTPUT

मेरे कोड में त्रुटियां हो सकती हैं, क्योंकि मैंने वास्तव में इसका परीक्षण नहीं किया है। कुछ साल पहले का मेरा ब्लॉग पोस्ट क्वेरी प्रदर्शन सहित थोड़ा और विस्तार में जाता है।


एक दम बढ़िया! इस बार मुझे एक लूप से चिपकना होगा क्योंकि SQL Server 2005 के लिए समर्थन आवश्यक है। हालांकि मैं भविष्य की परियोजनाओं के लिए इसे ध्यान में रखूंगा। धन्यवाद!
लुईस सोमरस

3
शानदार, यह स्वीकृत उत्तर होना चाहिए।
क्रिस मोर

3
काश यह डीबीए स्टैकएक्सचेंज के बजाय स्टैकओवरफ्लो में होता। इसकी दृश्यता बहुत कम है। अद्भुत जवाब।
लॉर्डबल्मन

3
पहली कोशिश से एक आकर्षण की तरह काम किया ... भयानक जवाब!
बेमेर्जु

5

आउटपुट क्लॉज केवल लक्ष्य पंक्तियों और स्थिरांक / चर में डेटा तक पहुंच सकता है, न कि स्रोत में कहीं से डेटा SELECT, जैसे कि आप ट्रिगर में काम कर रहे थे।

https://docs.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql स्टेट्स:

संशोधित की जा रही तालिका में कॉलम का कोई भी संदर्भ INSERTED या DELETED उपसर्ग के साथ योग्य होना चाहिए।

इसलिए मूल आईडी प्राप्त करने के लिए आपको इसे गंतव्य तालिका में शामिल करना होगा ताकि आउटपुट क्लॉज इसे वापस प्रतिध्वनित कर सके, जैसे:

-- The existing table 
DECLARE @MyTable TABLE (ID INT IDENTITY(1,1), [Name] NVARCHAR(MAX), SourceID INT);

-- My data I want to insert
DECLARE @MyInsertData TABLE (ID INT, [Name] NVARCHAR(MAX));
INSERT INTO @MyInsertData ( ID,Name)
VALUES ( -1 , 'bla'),(-2,'test'),(-3,'last');

DECLARE @MyCrossRef TABLE ([NewId] INT, OldId INT);

INSERT INTO @MyTable ( [Name], SourceID )
   OUTPUT Inserted.ID, Inserted.SourceID INTO @MyCrossRef
   SELECT [NAME], ID FROM @MyInsertData INS

-- Check the result
SELECT * FROM @MyCrossRef

यद्यपि लक्ष्य वस्तु का स्कीमा बदलना आपकी स्थिति में व्यावहारिक नहीं हो सकता है इसलिए यह लागू नहीं हो सकता है।


3
जो काफी निराशाजनक है। यही कारण है कि उत्पादन खंड मेरी परिदृश्य के लिए बेकार renders जब तक वहाँ एक 2 कॉलम कि एक महत्वपूर्ण :-( ओह, ठीक है, कम से कम मैं कोशिश कर बंद करो और पाशन के साथ पर मिलता धन्यवाद कर सकते हैं के रूप में इस्तेमाल किया जा सकता
लुइस सोमर्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.