2012-11-06 8 views
6

मैं प्राथमिक कुंजी को ऑरैकल मर्ज क्वेरी से वापस करना चाहता हूं। .. मैं एक सिंगल स्टेटमेंट का उपयोग कर रहा सम्मिलित करने के लिए करता है, तो मौजूद नहीं है और मैं ऐसा करने के लिए प्रक्रिया या कार्य का उपयोग नहीं करना चाहतेओरैकल मर्ज क्वेरी से प्राथमिक कुंजी कैसे वापस करें

इस नमूना क्वेरी

merge into myTable e 
    using (select :empname name from dual) s 
    on (UPPER(TRIM(e.empname)) = UPPER(TRIM(s.name))) 
    when not matched then insert (empname) 
    values (s.name) 

है और मैं प्राप्त करने की आवश्यकता myTable का एक और प्राथमिक कुंजी फ़ील्ड। प्राथमिक कुंजी अनुक्रम का उपयोग डाला जाता है और गति प्रदान

मैं RETURNING empID into :empId जोड़ने की कोशिश की, लेकिन यह त्रुटि

+0

यह "एक त्रुटि देता है" क्योंकि [वहाँ में लौटने का उपयोग करने की कोई सुविधा है] (http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_9016.htm#SQLRF01606) । हालांकि, अगर आप पीके _by परिभाषा को वापस करना चाहते हैं तो आपको इसे किसी चीज़ में वापस करना होगा, जिसका अर्थ है कि आप कुछ विवरण के रैपर का उपयोग कर रहे हैं। इस रैपर के साथ पीएल/एसक्यूएल ब्लॉक होने में क्या गलत है।यदि आप यह नहीं चाहते हैं कि यह एक प्रक्रिया/कार्य हो, तो आपको यह निर्दिष्ट करना होगा कि आप क्या उपयोग करना चाहते हैं अन्यथा इस सवाल का जवाब देना असंभव है। – Ben

+1

मैं ऐसा करने के लिए एक एकल ऑरैकल क्वेरी का उपयोग कर रहा हूं। : empId मैं आउटपुट पैरामीटर के रूप में इस क्वेरी को पास कर रहा हूं। क्या एक एकल विलय क्वेरी से आउटपुट पैरामीटर मान प्राप्त करना संभव है? –

+1

आपको इसे पढ़ने में रुचि हो सकती है - http://www.oracle-developer.net/display.php?id=413 –

उत्तर

8

देता है एक समस्या नहीं है है।

  1. Merge IntoReturning Into का समर्थन नहीं करता है, इसलिए यह काम नहीं करेगा।
  2. अनुक्रम हमेशा उपयोग नहीं किया जाएगा, क्योंकि यह केवल नए रिकॉर्ड डालने पर ही उपयोग किया जाता है।
  3. अनुक्रम का मौजूदा मान प्राप्त करना काम नहीं करेगा, क्योंकि अगर आप वर्तमान सत्र में अनुक्रम का उपयोग नहीं करते हैं तो आप Sequence.currval से पूछना चाहते हैं तो आपको कोई त्रुटि मिलती है।

इसे हल करने के लिए:

  1. मान को अद्यतन करने की कोशिश करने के लिए एक प्रक्रिया या अनाम कार्यक्रम ब्लॉक का उपयोग करें। यदि sql%rowcount अद्यतन के बाद 0 लौटाएं, तो इसके बजाय सम्मिलित करें।
  2. अपडेट किए गए रिकॉर्ड को खोजने के लिए चयन (UPPER(TRIM(name)) के लिए क्वेरी) का उपयोग करें।
+2

क्या आप इसे काम करने में सक्षम हैं? – GolezTrol

3

आप इसे आजमा सकते हैं। तुम एक पैकेज की घोषणा करने के लिए अपने आईडी पर कब्जा करने की आवश्यकता होगी, अन्यथा यह SQL विवरण को दिखाई नहीं होगा और आप एक त्रुटि प्राप्त होगी:

कृपया-00231: समारोहनामएसक्यूएल में इस्तेमाल नहीं किया जा सकता है

तो, पहले कार्यों के साथ पैकेज पर कब्जा करने की बना सकते हैं और फिर बाद में मर्ज बयान से आईडी का उपयोग:

CREATE OR REPLACE PACKAGE CaptureId 
AS 
    FUNCTION SaveId(newId IN NUMBER) RETURN NUMBER; 
    FUNCTION GetId RETURN NUMBER; 
END; 

CREATE OR REPLACE PACKAGE BODY CaptureId 
AS 
    capturedId NUMBER(10); 

    FUNCTION SaveId(newId IN NUMBER) RETURN NUMBER IS 
    BEGIN 
     capturedId := newId; 
     RETURN capturedId; 
    END; 

    FUNCTION GetId RETURN NUMBER IS 
    BEGIN 
     RETURN capturedId; 
    END; 
END; 

एक सरल मेज और अनुक्रम जनरेटर को देखते हुए के रूप में परिभाषित:

CREATE TABLE EMPLOYEE 
(
    EMPLOYEE_ID NUMBER(10) NOT NULL, 
    FIRST_NAME VARCHAR2(120) NOT NULL, 
    LAST_NAME VARCHAR2(120) NOT NULL, 
    CONSTRAINT PK_EMPLOYEE PRIMARY KEY (EMPLOYEE_ID) ENABLE 
); 

CREATE SEQUENCE SEQ_EMPLOYEE; 

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

BEGIN 
    MERGE INTO EMPLOYEE USING (SELECT CaptureId.SaveId(:myInputId) AS EMPLOYEE_ID, 
            :myFirstName as FIRST_NAME, 
            :myLastName as LAST_NAME 
           FROM DUAL) B 
     ON (A.EMPLOYEE_ID = B.EMPLOYEE_ID) 
    WHEN NOT MATCHED THEN 
     INSERT (EMPLOYEE_ID, 
       FIRST_NAME, 
       LAST_NAME) 
     VALUES (CaptureId.SaveId(SEQ_EMPLOYEE.NEXTVAL), 
       B.FIRST_NAME, 
       B.LAST_NAME) 
    WHEN MATCHED THEN 
    UPDATE SET A.FIRST_NAME= B.FIRST_NAME, 
       A.LAST_NAME= B.LAST_NAME; 

    SELECT CaptureId.GetId INTO :myOutputId FROM DUAL; 
END; 
+0

इस दृष्टिकोण के साथ एक और समस्या है। यदि आप ON कथन में EMPLOYEE_ID के अलावा क्वालीफायर का उपयोग करते हैं (उदा। 'A.EMPLOYEE_ID = B.EMPLOYEE_ID या A.LAST_NAME = B.LAST_NAME') तो आप आईडी को कैप्चर करने में विफल हो जाएंगे। उस क्वालीफायर के साथ, आप 'EMPLOYEE_ID' के लिए 'NULL' पास कर सकते हैं और' LAST_NAME' पर मेल खाते हैं। यदि यह 'EMPLOYEE_ID' द्वारा नहीं मिलता है, तो यह' LAST_NAME' से मेल खाने वाले 'EMPLOYEE_ID' को कैप्चर करने में विफल रहेगा। –

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