2008-12-01 16 views
30

मेरे कोड (जावा) से मैं यह सुनिश्चित करना चाहता हूं कि मेरे कोड को निष्पादित करने के बाद डेटाबेस में एक पंक्ति मौजूद है (डीबी 2)।क्या डीबी 2 में "डालने या अपडेट" कथन है?

मेरा कोड अब select करता है और यदि कोई परिणाम नहीं लौटाया जाता है तो यह insert करता है। मुझे वास्तव में यह कोड पसंद नहीं है क्योंकि यह बहु-थ्रेडेड वातावरण में चलते समय मुझे समवर्ती मुद्दों के बारे में बताता है।

मैं यह करना चाहता हूं कि यह तर्क मेरे जावा कोड के बजाय डीबी 2 में डालना है। क्या डीबी 2 में insert-or-update कथन है? या ऐसा कुछ भी जिसे मैं उपयोग कर सकता हूं?

उदाहरण के लिए:

insertupdate into mytable values ('myid') 

करने का एक और तरीका है यह शायद होगा हमेशा डालने और पकड़ करने के लिए "एसक्यूएल-कोड -803 प्राथमिक कुंजी पहले से मौजूद है", लेकिन मुझे लगता है कि यदि संभव हो तो से बचने के लिए चाहते हैं ।

+0

क्या प्रति थ्रेड एक लेनदेन होना बेहतर नहीं होगा? डीबीएमएस कई धागे के साथ अच्छे हैं, यही कारण है कि लेनदेन का आविष्कार किया गया था। वे समवर्ती मुद्दे को हल करेंगे। – bortzmeyer

+0

यह समवर्ती मुद्दे को हल नहीं करेगा क्योंकि लेनदेन केवल पहले से मौजूद पंक्ति पर अवरुद्ध करके काम करता है।यदि पंक्ति मौजूद नहीं है, तो लेनदेन इस पर अवरुद्ध नहीं हो सकता है और इसलिए इस प्रकार का ऑपरेशन अभी भी समवर्ती मुद्दों के लिए खुला है – Richard

उत्तर

38

हां, डीबी 2 में मेर्ज स्टेटमेंट है, जो यूपीएसईआरटी (अपडेट या डालने) करेगा।

MERGE INTO target_table USING source_table ON match-condition 
{WHEN [NOT] MATCHED 
      THEN [UPDATE SET ...|DELETE|INSERT VALUES ....|SIGNAL ...]} 
[ELSE IGNORE] 

देखें:

http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?topic=/com.ibm.db2.udb.admin.doc/doc/r0010873.htm

+2

उदाहरण व्यापक रूप से उपयोगी हो सकता है: txt ('col1', 'col2') का उपयोग करके mytable में __merge (tmp (कोड, नाम) mytable.code = tmp.code पर मिलान करते समय सेट करें नाम सेट करें = col2 '__ – agad

7

यह प्रतिक्रिया उम्मीद है कि पूरी तरह से जवाब देने के लिए क्वेरी MrSimpleMind use-update-and-insert-in-same-query में था और डालने और अद्यतन के परिदृश्य के साथ डीबी 2 मर्ज बयान के एक काम कर सरल उदाहरण प्रदान करना है एक बार में (आईडी 2 के साथ रिकॉर्ड अपडेट किया गया है और रिकॉर्ड आईडी 3 डाला गया है)।

CREATE TABLE STAGE.TEST_TAB ( ID INTEGER, DATE DATE, STATUS VARCHAR(10) ); 
COMMIT; 

INSERT INTO TEST_TAB VALUES (1, '2013-04-14', NULL), (2, '2013-04-15', NULL); COMMIT; 

MERGE INTO TEST_TAB T USING (
    SELECT 
    3 NEW_ID, 
    CURRENT_DATE NEW_DATE, 
    'NEW' NEW_STATUS 
    FROM 
    SYSIBM.DUAL 
UNION ALL 
    SELECT 
    2 NEW_ID, 
    NULL NEW_DATE, 
    'OLD' NEW_STATUS 
    FROM 
    SYSIBM.DUAL 
) AS S 
    ON 
    S.NEW_ID = T.ID 
    WHEN MATCHED THEN 
    UPDATE SET 
     (T.STATUS) = (S.NEW_STATUS) 
    WHEN NOT MATCHED THEN 
    INSERT 
    (T.ID, T.DATE, T.STATUS) VALUES (S.NEW_ID, S.NEW_DATE, S.NEW_STATUS); 
COMMIT; 
+1

मेरे लिए काम किया। धन्यवाद – Li3ro

+0

मैं यह इंगित करना चाहता हूं कि कुछ आईबीएम डेटाबेस 'SYSIBM.SYSDUMMY1'' SYSIBM.DUAL' – tgdn

2

एक और तरीका यह 2 प्रश्न निष्पादित करना है। एक मर्ज स्टेटमेंट बनाने से यह आसान है:

update TABLE_NAME set FIELD_NAME=xxxxx where MyID=XXX; 

INSERT INTO TABLE_NAME values (MyField1,MyField2) 
WHERE NOT EXISTS(select 1 from TABLE_NAME where MyId=xxxx); 

पहली क्वेरी केवल अपडेट करें फ़ील्ड जो आपको चाहिए, यदि MyId मौजूद है। दूसरा डालने में डीबी में पंक्ति है यदि MyId मौजूद नहीं है।

परिणाम यह है कि आपके डीबी में केवल एक प्रश्न निष्पादित किया गया है।

+2

की बजाय डमी तालिका के रूप में उपयोग करते हैं यदि डीबी 2 के आपके संस्करण में 'MERGE' है, तो इसे प्राथमिकता दें - इससे कुछ संभावित समरूपता को समाप्त करने में मदद मिलेगी मुद्दे। मैं स्वचालित रूप से इस "सरल" लेबल नहीं करता, हालांकि; आपके पास दो बयानों से निपटने से अतिरिक्त ओवरहेड है (जिसे सिंक में बनाए रखा जाना चाहिए!), और यह वास्तव में 'UPDATE' और अपने स्वयं के 'INSERT' के बीच पंक्ति डालने वाली एक अलग प्रक्रिया की संभावना को हल नहीं करता है ... –

+1

वह 'डालने' कथन वाक्य रचनात्मक रूप से गलत है। – mustaccio

11

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

निम्नलिखित वाक्यविन्यास एक अलग temp तालिका की आवश्यकता के बिना काम करने लगता है।

यह तालिका संरचना बनाने के लिए VALUES() का उपयोग करके काम करता है। चयन * अधिशेष IMHO लगता है लेकिन इसके बिना मुझे वाक्यविन्यास त्रुटियां मिलती हैं।

MERGE INTO mytable AS mt USING (
    SELECT * FROM TABLE (
     VALUES 
      (123, 'text') 
    ) 
) AS vt(id, val) ON (mt.id = vt.id) 
WHEN MATCHED THEN 
    UPDATE SET val = vt.val 
WHEN NOT MATCHED THEN 
    INSERT (id, val) VALUES (vt.id, vt.val) 
; 

यदि आपको एक से अधिक पंक्ति डालना है, तो VALUES भाग को बाकी डुप्लिकेट किए बिना दोहराया जा सकता है।

VALUES 
    (123, 'text'), 
    (456, 'more') 

परिणाम एक भी बयान है कि डालने या एक या एक से अधिक पंक्तियाँ अद्यतन कर सकते हैं शायद एक परमाणु आपरेशन के रूप में है।

+0

एक मौका है कि आप 'चयन मूल्य से' चयन * के बजाय 'SELECT' मान 'SYSIBM.SYSDUMMY1' नाम का उपयोग करना चाहते हैं। – tgdn

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