ओरेकल एसक्यूएल: एक टेबल को दूसरी टेबल के डेटा के साथ अपडेट करें


251

तालिका एक:

id    name    desc
-----------------------
1     a       abc
2     b       def
3     c       adf

तालिका 2:

id    name    desc
-----------------------
1     x       123
2     y       345

Oracle SQL में, मैं एक sql अद्यतन क्वेरी कैसे चलाता हूं जो तालिका 1 को तालिका 2 के साथ nameऔर descउसी का उपयोग करके अपडेट कर सकती है id? तो अंतिम परिणाम मुझे मिलेगा

तालिका एक:

id    name    desc
-----------------------
1     x       123
2     y       345
3     c       adf

प्रश्न दूसरे से डेटा के साथ एक तालिका को अपडेट करने से लिया जाता है , लेकिन विशेष रूप से ओरेकल एसक्यूएल के लिए।



आपको अपने अन्य प्रश्न पर वापस जाने की आवश्यकता है, उस उत्तर को स्वीकार न करें, और विशेष रूप से बताएं कि आपको Oracle PLSQL सिंटैक्स की आवश्यकता है।
18 अक्टूबर को p.campbell

3
@ p.campbell, यह मेरा सवाल नहीं है ...
Muhd

1
ओह मैं समझा। तो आपने प्रश्न निकाय को कॉपी-पेस्ट किया, लेकिन ओरेकल बिट को शामिल करने के लिए संशोधित किया।
पी। काम्पबेल

2
हाँ। और यह शायद सबसे अच्छा उदाहरण नहीं है क्योंकि "डीईएससी" एक आरक्षित शब्द है, लेकिन ओह अच्छी तरह से।
मुहाद

जवाबों:


512

इसे सहसंबद्ध अद्यतन कहा जाता है

UPDATE table1 t1
   SET (name, desc) = (SELECT t2.name, t2.desc
                         FROM table2 t2
                        WHERE t1.id = t2.id)
 WHERE EXISTS (
    SELECT 1
      FROM table2 t2
     WHERE t1.id = t2.id )

कुंजी-संरक्षित दृश्य में शामिल होने के परिणामों को मानते हुए, आप भी कर सकते हैं

UPDATE (SELECT t1.id, 
               t1.name name1,
               t1.desc desc1,
               t2.name name2,
               t2.desc desc2
          FROM table1 t1,
               table2 t2
         WHERE t1.id = t2.id)
   SET name1 = name2,
       desc1 = desc2

8
अपने पहले कोड उदाहरण में: बाहरी WHERE-clause सही परिणामों के लिए आवश्यक है? या आप इसका उपयोग केवल क्वेरी को गति देने के लिए करते हैं?
मथियास बैडर

41
@totoro - पहले उदाहरण में, यदि कोई मिलान पंक्ति नहीं है तो WHERE EXISTSआपको एक पंक्ति को अपडेट करने से रोकता t1है t2। इसके बिना, हर पंक्ति को t1अद्यतन किया जाएगा और NULLयदि कोई मिलान पंक्ति नहीं है, तो मानों को सेट किया जाएगा t2। यह आम तौर पर वह नहीं होता है जो आप चाहते हैं इसलिए WHERE EXISTSआम तौर पर इसकी आवश्यकता होती है।
जस्टिन गुफा

3
यह जोड़ने योग्य है कि एक अद्वितीय पंक्ति में परिणाम SELECT ... FROM t2 होना चाहिए । इसका मतलब है कि आपको उन सभी क्षेत्रों पर चयन करना होगा जिसमें एक अद्वितीय कुंजी शामिल है - एक गैर-अद्वितीय प्राथमिक कुंजी पर्याप्त नहीं है। अद्वितीयता के बिना, आप @ पॉलकर के पाश की तरह कुछ कम हो जाते हैं - और यदि कोई अद्वितीय सहसंबंध नहीं है, तो प्रत्येक स्रोत पंक्ति के लिए एक से अधिक लक्ष्य पंक्ति को अपडेट किया जा सकता है।
एंड्रयू लीच

2
Updatable के लिए कुंजी से संरक्षित आवश्यकता पर स्पष्टीकरण मिलती है: asktom.oracle.com/pls/asktom/...
वादज़्मी

1
@ राचिटशर्मा - इसका मतलब है कि आपकी उपशम (से क्वेरी table2) एक या एक से अधिक table1मूल्यों के लिए कई पंक्तियाँ लौटा रही है और ओरेकल को पता नहीं है कि आप किसका उपयोग करना चाहते हैं। आम तौर पर, इसका मतलब है कि आपको उपकुंजी को परिष्कृत करने की आवश्यकता है ताकि यह एक अलग पंक्ति को लौटाए।
जस्टिन केव

132

इसे इस्तेमाल करे:

MERGE INTO table1 t1
USING
(
-- For more complicated queries you can use WITH clause here
SELECT * FROM table2
)t2
ON(t1.id = t2.id)
WHEN MATCHED THEN UPDATE SET
t1.name = t2.name,
t1.desc = t2.desc;

4
बहुत तेजी से, 1159477 पंक्तियों को 15,5 में विलय कर दिया गया
जेफिसु

3
मुझे उम्मीद है कि 2015 के बाद इस सवाल का जवाब देने वाले हर व्यक्ति को यह जवाब मिलेगा। ध्यान दें कि यह भी काम करता है table1और अगर table2एक ही तालिका है, ONतो WHERE-state की देखभाल के लिए -part और -clause SELECTका ध्यान रखें table2!
sjngm

1
मुझे लगता है कि हर बार मुझे एक और मर्ज करने की ज़रूरत है जो मैं प्रेरणा के लिए इस उत्तर पर वापस आता रहता हूं। मैं इसे प्रिंट कर सकता हूं और इसे अपनी दीवार पर फ्रेम कर सकता हूं
arnehehe

आकर्षण जैसा काम करता है !! धन्यवाद!
davidwillianx

DISTINCT ID, FIELD1, FIELD1 टेबल से F2 का चयन करें, जहां ID NULL नहीं है
जोसेफ

17

प्रयत्न

UPDATE Table1 T1 SET
T1.name = (SELECT T2.name FROM Table2 T2 WHERE T2.id = T1.id),
T1.desc = (SELECT T2.desc FROM Table2 T2 WHERE T2.id = T1.id)
WHERE T1.id IN (SELECT T2.id FROM Table2 T2 WHERE T2.id = T1.id);

4
इसका नकारात्मक पक्ष यह है कि SELECT स्टेटमेंट को 3 बार दोहराया जाता है। जटिल उदाहरणों में जो एक सौदा तोड़ने वाला हो सकता है।
बजे डेविड बाल्विक

9
Update table set column = (select...)

मेरे लिए कभी भी काम नहीं किया क्योंकि सेट केवल 1 मूल्य की अपेक्षा करता है - SQL त्रुटि: ORA-01427: एकल-पंक्ति सबक्वेरी एक पंक्ति से अधिक देता है।

यहाँ समाधान है:

BEGIN
For i in (select id, name, desc from table1) 
LOOP
Update table2 set name = i.name, desc = i.desc where id = i.id;
END LOOP;
END;

ठीक इसी तरह से आप इसे SQLDeveloper वर्कशीट पर चलाते हैं। वे कहते हैं कि यह धीमा है लेकिन यह एकमात्र समाधान है जिसने इस मामले पर मेरे लिए काम किया है।


किसी को समझा सकते हैं कि यह प्रतिष्ठा के लायक क्यों -2 है? जबरदस्त हंसी।
पौ कर्र

13
मैंने रेट कम नहीं किया, लेकिन यह एक अच्छा समाधान नहीं है। सबसे पहले: यदि सबस्क्रिप्शन कई मानों को वापस कर रहा था, तो लूप के लिए कुछ / सभी रिकॉर्ड (साफ नहीं) के लिए कई बार तालिका 2 पर नाम लिखना होगा। दूसरी बात: खंड द्वारा कोई आदेश नहीं है, इसलिए यह अप्रत्याशित तरीके से घटित होगा (यानी अव्यवस्थित जीत में अंतिम मूल्य)। तीसरी बात: यह बहुत धीमी होगी। मान लें कि लूप के परिणाम का इरादा था, प्रत्येक रिकॉर्ड के लिए केवल 1 मान वापस करने के लिए मूल नियंत्रित को कुछ नियंत्रित तरीके से फिर से लिखा जा सकता है ... सबसे आसान तरीका होगा (चयनित नाम (नाम) ...)
अल्टरनेटर

यह वही था जो मुझे चाहिए था। धन्यवाद (+1)
रॉबर्ट हयात

3
यदि आपको अपनी अधीनता में कई मान मिलते हैं, तो आप क्वेरी को पुनर्विचार कर सकते हैं और MIN, MAX के साथ DISTINCT या GROUP BY का उपयोग कर सकते हैं। एक विचार है।
फ्रांसिस

लंबी कहानी छोटी: यदि आप इससे बच सकते हैं, तो कभी भी टी-एसक्यूएल स्टेटमेंट में किसी भी तरह के एलओपी का उपयोग न करें। व्यक्तिगत रूप से, यदि यह उस समय के 0.001% के लिए नहीं था जहां कोई अन्य समाधान नहीं है, तो मुझे नहीं लगता कि यह टी-एसक्यूएल में उपलब्ध फ़ंक्शन भी होना चाहिए। टी-एसक्यूएल को सेट-आधारित होने के लिए डिज़ाइन किया गया है, इसलिए यह डेटा के पूरे सेट पर काम करता है; इसका उपयोग डेटा लाइन-बाय-लाइन पर काम करने के लिए नहीं किया जाना चाहिए।
रे के।

8

यहाँ 'इन' क्लॉज़ 'के साथ एक और बेहतर उत्तर प्रतीत होता है जो जुड़ने के लिए कई कुंजियों की अनुमति देता है :

update fp_active set STATE='E', 
   LAST_DATE_MAJ = sysdate where (client,code) in (select (client,code) from fp_detail
  where valid = 1) ...

गोमांस उन स्तंभों के पास होता है जिन्हें आप कोष्ठक में कुंजी के रूप में उपयोग करना चाहते हैं, जहां 'से पहले' खंड में होता है और कोष्ठक में समान स्तंभ नामों के साथ चयन कथन होता है। जहां ( कॉलम 1, कॉलम 2 ) टेबल से " ( कॉलम 1, कॉलम 2 )" जहां "मैं चाहता हूं" सेट करें ;


लिंक की समय सीमा समाप्त हो गई है। ( 404)
दमबो

-3

यदि आपकी तालिका t1 और यह बैकअप t2 है तो कई कॉलम हैं, यहाँ यह करने का एक कॉम्पैक्ट तरीका है।

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

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

चाल यह है कि जब आप डुप्लिकेट कॉलम नामों के साथ तालिकाओं की एक जोड़ी से * का चयन करते हैं, तो 2 को _1 नाम मिलेगा। तो यहाँ मैं क्या लेकर आया हूँ:

  update (
    select * from t1 join t2 on t2.id = t1.id
    where id in (
      select id from (
        select id, col1, col2, ... from t2
        minus select id, col1, col2, ... from t1
      )
    )
  ) set col1=col1_1, col2=col2_1, ...

यह Oracle 11g में मेरे लिए काम नहीं करता है। क्या आप इस पद्धति का एक कार्यशील उदाहरण बना सकते हैं?
जॉन हेलर

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