SQL सर्वर: क्या एक ही समय में दो तालिकाओं में सम्मिलित करना संभव है?


144

मेरे डेटाबेस में तीन टेबल हैं Object_Table, Data_Tableऔर कहा जाता है Link_Table। लिंक टेबल में सिर्फ दो कॉलम होते हैं, एक ऑब्जेक्ट रिकॉर्ड की पहचान और एक डेटा रिकॉर्ड की पहचान।

मैं से डेटा कॉपी करना चाहते DATA_TABLEहै, जहां यह एक दिया वस्तु पहचान करने के लिए और में रिकॉर्ड इसी डालने से जुड़ा हुआ है Data_Tableऔर Link_Tableएक अलग दिया वस्तु पहचान के लिए।

मैं एक तालिका चर में चयन करके और प्रत्येक पुनरावृत्ति के लिए दो आवेषण करने के माध्यम से पाशन कर सकता हूं।

क्या यह करने का सबसे अच्छा तरीका है?

संपादित करें : मैं दो कारणों से एक लूप से बचना चाहता हूं, पहला यह है कि मैं आलसी हूं और एक लूप / टेम्प टेबल के लिए अधिक कोड की आवश्यकता होती है, अधिक कोड का मतलब है कि गलती करने के लिए अधिक स्थान और दूसरा कारण प्रदर्शन के बारे में चिंता है।

मैं एक प्रविष्टि में सभी डेटा को कॉपी कर सकता हूं लेकिन नए डेटा रिकॉर्ड से लिंक करने के लिए लिंक तालिका कैसे प्राप्त करें जहां प्रत्येक रिकॉर्ड में एक नया आईडी है?


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

2
मुझे दो आवेषणों से प्रसन्नता होगी, बस इसके लिए कि जिन पहचानपत्रों को लिंक तालिका में सम्मिलित करने की आवश्यकता है, वे पहली प्रविष्टि में उत्पन्न पहचान हैं।
tpower

जवाबों:


220

एक बयान में : नहीं।

एक लेन-देन में : हाँ

BEGIN TRANSACTION
   DECLARE @DataID int;
   INSERT INTO DataTable (Column1 ...) VALUES (....);
   SELECT @DataID = scope_identity();
   INSERT INTO LinkTable VALUES (@ObjectID, @DataID);
COMMIT

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


2
यह मैं लंबे समय से खोज रहा हूं। धन्यवाद :)
nandu.com

33
@ योएल, महान सवाल। संभवत: किसी ने एक वैकल्पिक वास्तविकता की कामना की और आप बुरी खबरों के वाहक थे। ;)
किर्क वोल्फ

2
इसने आज मेरा दिन बचाया :)
थैंक्स

12
यह समस्या को हल नहीं करता है। वह Object_Table से पढ़ा गया डेटा डालना चाहता है। Ie एक insert into ... select ...बयान। उपरोक्त कोड Object_Table डेटा के माध्यम से कैसे पढ़ा या लूप करता है। फिर भी आपको एक तालिका चर का उपयोग करने की आवश्यकता होती है जो पूछने वाला नहीं करना चाहता था।
होफनरविले

8
यकीन है कि इस समस्या को हल करती है। हो सकता है कि मैंने इसके लिए सभी कोड नहीं लिखे थे , लेकिन तब ओपी ने उन सभी स्तंभों को साझा नहीं किया था जिन्हें वह कॉपी करना चाहता था। इस उत्तर में प्रदर्शित विशेषताओं से ओपी को वह करने के लिए अनुमति देगा जो वह पूछ रहा है ... एक रिकॉर्ड बनाने के लिए एक क्वेरी चलाएं, नए रिकॉर्ड की आईडी प्राप्त करें, और उस आईडी का उपयोग परमाणु रिकॉर्ड में दूसरे रिकॉर्ड के लिए करें। ओपी पहले से ही एक सम्मिलित / चयन करने का तरीका जानता है। यह वह टुकड़ा है जो वह गायब था।
जोएल कोएहॉर्न

35

तुम अब भी दो की जरूरत INSERTबयान है, लेकिन यह लगता है कि आप प्राप्त करना चाहते हैं IDENTITYपहले डालने से और दूसरे में इसका इस्तेमाल करते हैं, जिस स्थिति में है, तो आप में देखना चाहते हो सकता है OUTPUTया OUTPUT INTO: http://msdn.microsoft.com/en- हमें / पुस्तकालय / ms177564.aspx


1
धन्यवाद! मैं OUTPUT कीवर्ड के बारे में नहीं जानता था, वास्तव में मैं क्या देख रहा था। +1
रेक्स मॉर्गन

क्या एक
वर्ग

@ V। मुझे ऐसा नहीं लगता, मुझे देखने के लिए एक परीक्षा देनी होगी।
कैड रूक्स

18

तालिका चर का उपयोग करते हुए, निम्नलिखित स्थिति मेरे पास थी।

DECLARE @Object_Table TABLE
(
    Id INT NOT NULL PRIMARY KEY
)

DECLARE @Link_Table TABLE
(
    ObjectId INT NOT NULL,
    DataId INT NOT NULL
)

DECLARE @Data_Table TABLE
(
    Id INT NOT NULL Identity(1,1),
    Data VARCHAR(50) NOT NULL
)

-- create two objects '1' and '2'
INSERT INTO @Object_Table (Id) VALUES (1)
INSERT INTO @Object_Table (Id) VALUES (2)

-- create some data
INSERT INTO @Data_Table (Data) VALUES ('Data One')
INSERT INTO @Data_Table (Data) VALUES ('Data Two')

-- link all data to first object
INSERT INTO @Link_Table (ObjectId, DataId)
SELECT Objects.Id, Data.Id
FROM @Object_Table AS Objects, @Data_Table AS Data
WHERE Objects.Id = 1

एक अन्य जवाब के लिए धन्यवाद जिसने मुझे OUTPUT क्लॉज़ की ओर इशारा किया है जिसका मैं समाधान प्रदर्शित कर सकता हूं:

-- now I want to copy the data from from object 1 to object 2 without looping
INSERT INTO @Data_Table (Data)
OUTPUT 2, INSERTED.Id INTO @Link_Table (ObjectId, DataId)
SELECT Data.Data
FROM @Data_Table AS Data INNER JOIN @Link_Table AS Link ON Data.Id = Link.DataId
                INNER JOIN @Object_Table AS Objects ON Link.ObjectId = Objects.Id 
WHERE Objects.Id = 1

हालांकि यह पता चलता है कि निम्न त्रुटि के कारण वास्तविक जीवन में यह उतना सरल नहीं है

OUTPUT INTO खंड एक (प्राथमिक कुंजी, विदेशी कुंजी) संबंध के दोनों ओर नहीं हो सकता है

मैं अभी भी OUTPUT INTOएक अस्थायी तालिका बना सकता हूं और फिर सामान्य आवेषण के साथ समाप्त कर सकता हूं । इसलिए मैं अपने पाश से बच सकता हूं लेकिन मैं टेम्‍प टेबल से नहीं बच सकता।



6

ऐसा लगता है कि लिंक तालिका कई को कैप्चर करती है: ऑब्जेक्ट टेबल और डेटा टेबल के बीच कई संबंध।

मेरा सुझाव लेनदेन का प्रबंधन करने के लिए एक संग्रहीत प्रक्रिया का उपयोग करना है। जब आप ऑब्जेक्ट या डेटा तालिका में अपनी आवेषण करना चाहते हैं, तो नई आईडी प्राप्त करें और उन्हें लिंक तालिका में डालें।

यह आपके सभी तर्कों को स्पार्क कॉल करने के लिए एक आसान में समझाया जा सकता है।


किसी और ने आपको क्यों नहीं उकसाया? संग्रहीत प्रक्रिया स्पष्ट और सबसे अच्छा तरीका है। जोएल कोएहॉर्न के उत्तर के साथ अपने उत्तर को मिलाएं और आपको सबसे अच्छा उत्तर मिलेगा!
ऋषि

4

यदि आप चाहते हैं कि क्रियाएं कम से कम परमाणु हों, तो मैं उन्हें लेनदेन में लपेटना सुनिश्चित करूंगा। इस तरह आप सुनिश्चित कर सकते हैं कि दोनों हुआ या दोनों आवश्यकतानुसार नहीं हुआ।


2
यदि वे एक लेनदेन में लिपटे हुए हैं, तो परमाणु परमाणु हैं, न कि "अधिक या कम" परमाणु। जब तक आप निर्दिष्ट नहीं करते हैं, तब तक जरूरी नहीं कि वह अलगाव का स्तर हो।
डेव मार्कले

4

आप अपने सम्मिलित विवरण के लिए आवश्यक कॉलम नामों का चयन करते हुए एक दृश्य बना सकते हैं, INSERT ट्रिगर का INSTEAD जोड़ें और इस दृश्य में डालें।


4

मैं उपयोग करने पर जोर देना चाहता हूं

SET XACT_ABORT ON;

कई sql बयानों के साथ MSSQL लेनदेन के लिए।

देखें: https://msdn.microsoft.com/en-us/library/ms188792.aspx वे एक बहुत अच्छा उदाहरण प्रदान करते हैं।

तो, अंतिम कोड निम्नलिखित की तरह दिखना चाहिए:

SET XACT_ABORT ON;

BEGIN TRANSACTION
   DECLARE @DataID int;
   INSERT INTO DataTable (Column1 ...) VALUES (....);
   SELECT @DataID = scope_identity();
   INSERT INTO LinkTable VALUES (@ObjectID, @DataID);
COMMIT

2

इन्सर्ट एक बार में केवल एक टेबल पर काम कर सकता है। मल्टीपल इंसर्ट में कई स्टेटमेंट होने चाहिए।

मुझे नहीं पता है कि आपको टेबल चर के माध्यम से लूपिंग करने की आवश्यकता है - क्या आप एक मेज में एक बड़े पैमाने पर डालने का उपयोग नहीं कर सकते हैं, फिर बड़े पैमाने पर दूसरे में डालें?

वैसे - मैं अनुमान लगा रहा हूँ कि आप ऑब्जेक्ट का ऑब्जेक्ट Object_Table से कॉपी करेंगे; अन्यथा सवाल का कोई मतलब नहीं है।


2

ओरेकल में एक मल्टीटेस्ट इंसर्ट करने में सक्षम होने से पहले, आप एक इंसर्ट को सम्मिलित करने के लिए एक ट्रिक का उपयोग कर सकते हैं, जिसमें इंसर्ट को सम्मिलित करने के लिए उस पर स्थापित ट्रिगर का INSTEAD था। यह SQL सर्वर में किया जा सकता है?


-1
-- ================================================
-- Template generated from Template Explorer using:
-- Create Procedure (New Menu).SQL
--
-- Use the Specify Values for Template Parameters 
-- command (Ctrl-Shift-M) to fill in the parameter 
-- values below.
--
-- This block of comments will not be included in
-- the definition of the procedure.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE InsetIntoTwoTable

(
@name nvarchar(50),
@Email nvarchar(50)
)

AS
BEGIN

    SET NOCOUNT ON;


    insert into dbo.info(name) values (@name)
    insert into dbo.login(Email) values (@Email)
END
GO

क्या आप कुछ स्पष्टीकरण जोड़ सकते हैं?
Kyll

-2

// यदि आप पहली तालिका के समान सम्मिलित करना चाहते हैं

$qry = "INSERT INTO table (one, two, three) VALUES('$one','$two','$three')";

$result = @mysql_query($qry);

$qry2 = "INSERT INTO table2 (one,two, three) VVALUES('$one','$two','$three')";

$result = @mysql_query($qry2);

// या यदि आप तालिका एक के कुछ भागों को सम्मिलित करना चाहते हैं

 $qry = "INSERT INTO table (one, two, three) VALUES('$one','$two','$three')";


  $result = @mysql_query($qry);

 $qry2 = "INSERT INTO table2 (two) VALUES('$two')";

 $result = @mysql_query($qry2);

// मुझे पता है कि यह सही होने के लिए बहुत अच्छा लगता है, लेकिन यह काम करता है और आप क्वेरी के बदलाव को जोड़ सकते हैं

    "$qry"-number and number in @mysql_query($qry"")

मेरे पास 17 टेबल हैं जिनमें यह काम किया है।


अगर आवेषण के बीच में कुछ गलत हो जाता है? आपके आवेषण अधूरे होंगे। सही? यदि ऐसा कर रहे हैं .. क्या आपके पास इसका इलाज करने के लिए रोलबैक फ़ंक्शन है? यदि नहीं .. तो आपको अपने डेटा अखंडता के साथ समस्या है।
गहराती

7
-1। यह उत्तर PHP में MySQL के तरीकों का उपयोग करता हुआ प्रतीत होता है। प्रश्न में SQL और SQL- सर्वर को टैग किया गया है , जिसमें MySQL या PHP का कोई उल्लेख नहीं है।
mskfisher 21
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.