ओरेकल में अनुक्रम.नेक्स्टवल शून्य कैसे हो सकता है?


11

मेरे पास एक Oracle अनुक्रम है जिसे इस तरह परिभाषित किया गया है:

CREATE SEQUENCE  "DALLAS"."X_SEQ"  
    MINVALUE 0 
    MAXVALUE 999999999999999999999999999 
    INCREMENT BY 1 START WITH 0 NOCACHE  NOORDER  NOCYCLE ;

इसका उपयोग संग्रहित प्रक्रिया में रिकॉर्ड डालने के लिए किया जाता है:

PROCEDURE Insert_Record
                (p_name    IN  VARCHAR2,                
                 p_userid  IN  INTEGER,
                 cur_out   OUT TYPES_PKG.RefCursor)
    IS
        v_id NUMBER := 0;
    BEGIN
        -- Get id value from sequence
        SELECT x_seq.nextval
          INTO v_id
          FROM dual;

        -- Line below is X_PKG line 40
        INSERT INTO X
            (the_id,            
             name,                        
             update_userid)
          VALUES
            (v_id,
             p_name,                        
             p_userid);

        -- Return new id
        OPEN cur_out FOR
            SELECT v_id the_id
              FROM dual;
    END;

कभी-कभी, यह प्रक्रिया अनुप्रयोग कोड से निष्पादित करते समय एक त्रुटि देता है।

ORA-01400: cannot insert NULL into ("DALLAS"."X"."THE_ID") 
ORA-06512: at "DALLAS.X_PKG", line 40 
ORA-06512: at line 1

ऐसा विवरण जो प्रासंगिक हो या न हो:

  • ओरेकल डेटाबेस 11 जी एंटरप्राइज संस्करण 11.2.0.1.0 - 64 बिट उत्पादन रिलीज
  • प्रक्रिया Microsoft.Practices.EnterpriseLibrary - Data.Oracle.OracleDatabase.ExecuteReader (DbCommand कमांड) के माध्यम से निष्पादित की जाती है
  • एप्लिकेशन एक स्पष्ट लेनदेन में कॉल को लपेटता नहीं है।
  • सम्मिलित रुक-रुक कर विफल - 1% से कम

किन परिस्थितियों में x_seq.nextvalअशक्त हो सकता है?


चयन और सम्मिलित के बीच कितना कोड है? क्या उस कोड में कोई BEGIN..END ब्लॉक या कोई अपवाद कथन हैं? क्या उस कोड में v_id को बिल्कुल संदर्भित किया गया है? थोड़ा अजीब लगता है। क्या आप स्टेटमेंट के बाद सीधे "IF v_id IS NULL THEN .... END IF" ब्लॉक कर सकते हैं और कुछ डिबगिंग आउटपुट छोड़ सकते हैं यदि अनुक्रम वास्तव में v_id को शून्य असाइन करता है? उस अनुक्रम को BEGIN..EXCEPTION ब्लॉक में चुनें, क्योंकि ऐसा कुछ हो सकता है जो पकड़ा नहीं गया हो। एक आखिरी चीज - क्या आपके द्वारा इसमें डाली जा रही मेज पर ट्रिगर है जिससे यह पैदा हो सकता है?
फिलो

@Phil - चयन डालने से ठीक पहले है। BEGIN / END के अलावा कोई BEGIN, END, या EXCEPTION नहीं। v_idकेवल अनुक्रम चयन, प्रविष्टि और अंतिम कर्सर में संदर्भित है। हमारा अगला कदम डिबगिंग कोड को जोड़ना था। हमें परिणामों के लिए इंतजार करना पड़ सकता है क्योंकि यह केवल उत्पादन में होता है और बहुत ही कम बार। एक ट्रिगर है जो एक ऑडिट टेबल में सम्मिलित होता है। मैंने बिना किसी धूम्रपान बंदूक के साथ इसके माध्यम से कंघी की है। ट्रिगर के बिना भी समस्या कभी-कभी अन्य तालिकाओं में होती है। निगाह डालने के लिए धन्यवाद।
कॉर्बिन मार्च

5
केवल एक चीज जो मैं इस समय सोच सकता हूं, वह यह है कि: new.the_id किसी तरह ट्रिगर में NULL बन जाएगा, जो टेबल X पर है।
फिलो

@Phil: यह निश्चित रूप से समस्या का कारण है। आपको इसका जवाब देना चाहिए।
रेने Nyffenegger

@ RenéNyffenegger -यह समस्या उन प्रॉपर में भी होती है जो बिना ट्रिगर के तालिकाओं में सम्मिलित होती हैं। यह एक समान अवसर बग प्रतीत होता है।
कॉर्बिन मार्च

जवाबों:


4

मुझे पूरा यकीन है कि यह आपके कोड की एक कलाकृतियाँ, या .net ड्राइवर का उपयोग कर रहा है। मैंने शुद्ध एसक्यूएल - पीएल / एसक्यूएल का उपयोग करते हुए आपके लिए एक त्वरित डेमो खटखटाया है और कभी भी खोया हुआ अनुक्रम मान प्राप्त नहीं किया है। संयोग से आपके द्वारा उपयोग किया जा रहा रेफरी कर्सर संभवतः अनावश्यक है और कोड के प्रदर्शन और पठनीयता पर प्रभाव डालता है - मेरे डेमो में एक Insert_record2 प्रक्रिया शामिल है जो लगातार 10% से अधिक तेजी से प्रदर्शन करती है, मेरे लैपटॉप पर 36 के लगभग Ref कर्सर संस्करण के लिए 36 है। मैं कम से कम यह भी समझता हूं कि समझना आसान है। आप स्पष्ट रूप से ऑडिट ट्रिगर के साथ अपने परीक्षण डेटाबेस के खिलाफ एक संशोधित संस्करण चला सकते हैं।

/* 
demo for dbse 
assumes a user with create table, create sequence, create procedure pivs and quota. 

*/

drop table dbse13142 purge;

create table dbse13142(
    the_id number not null
,   name   varchar2(20)
,   userid number)
;

drop sequence x_seq;
CREATE SEQUENCE  X_SEQ NOCACHE  NOORDER  NOCYCLE ;

create or replace PROCEDURE Insert_Record
                (p_name    IN  VARCHAR2,                
                 p_userid  IN  INTEGER,
                 cur_out   OUT sys_refcursor)
    IS
        v_id NUMBER := 0;
    BEGIN
        -- Get id value from sequence
        SELECT x_seq.nextval
          INTO v_id
          FROM dual;

        -- Line below is X_PKG line 40
        INSERT INTO dbse13142
            (the_id,            
             name,                        
             userid)
          VALUES
            (v_id,
             p_name,                        
             p_userid);

        -- Return new id
        OPEN cur_out FOR
            SELECT v_id the_id
              FROM dual;
    END;
/


create or replace PROCEDURE Insert_Record2
                (p_name    IN  VARCHAR2,                
                 p_userid  IN  INTEGER,
                 p_theid   OUT dbse13142.the_id%type)
    IS
    BEGIN
        -- Get id value from sequence
        SELECT x_seq.nextval
          INTO p_theid
          FROM dual;

        -- Line below is X_PKG line 40
        INSERT INTO dbse13142
            (the_id,            
             name,                        
             userid)
          VALUES
            (p_theid,
             p_name,                        
             p_userid);
    END;
/

set timing on

declare
   c sys_refcursor;
begin   
for i in 1..100000 loop
   insert_record('User '||i,i,c);
   close c;
end loop;
commit;
end;
/

select count(*) from dbse13142;
truncate table dbse13142;

declare
  x number;
begin   
for i in 1..100000 loop
   insert_record2('User '||i,i,x);
end loop;
commit;
end;
/

select count(*) from dbse13142;
truncate table dbse13142;

1
जिस तरह से the_id कॉलम के लिए एक ट्रिगर का उपयोग करने के पारंपरिक दृष्टिकोण के साथ एक संस्करण और इस प्रकार की प्रक्रिया भी तेज हो गई है या PROCEDURE Insert_Record3 (p_name IN dbse13142.name% प्रकार, p_userid IN dbse13142.userid% प्रकार, p_theid OUT db1313 पर बदलें) .the_id% प्रकार) BEGIN INSERT INTO dbse13142 (नाम, उपयोगकर्ता नाम) VALUES (p_name, p_userid) the_id को p_theid में लौटाता है; समाप्त; /
Niall Litchfield

सहमत हैं कि यह ऐप कोड या ड्राइवर के साथ एक समस्या है। मैं बस उत्सुक हूं कि एक साइड इफेक्ट के रूप में एक अशक्त अगली बात क्या हो सकती है। पेचीदा। प्रदर्शन टिप के लिए धन्यवाद। यह अच्छी सलाह है कि मैं टीम को सुझाव दूंगा।
कॉर्बिन मार्च

1
कॉर्बिन, मेरा क्या मतलब है (और केविन) यह है कि आपके कोड और ओरेकल के बीच कुछ अजीब चल रहा है - यदि आप SQL में पूरी तरह से परीक्षण चलाते हैं तो आपको प्रभाव नहीं मिलता है। लेकिन ऑडिट ट्रिगर के बारे में फिल की टिप्पणी देखें (जिसे आप अक्षम करने का प्रयास कर सकते हैं)।
निल लिचफील्ड

मुझे समझ में आ गया है। समस्या प्रॉपर टेबल के साथ और ट्रिगर के बिना सम्मिलित करने में मौजूद है इसलिए ट्रिगर की आवश्यकता नहीं है। जब एक ट्रिगर मौजूद होता है, तो यह केवल एक ऑडिट टेबल में सम्मिलित होता है। मैंने पुष्टि की है :new.the_idकि अछूता है। मैं समझता हूं कि मेरा सवाल एक लंबा शॉट है। यह मेरे google-fu के लिए प्रतिरोधी है और यहाँ कई लोगों ने अपना सिर खुजलाया है। मुझे लगा कि किसी को पर्याप्त नेत्रगोलक दिए गए लक्षण (और उपचार) की पहचान हो सकती है। निगाह डालने के लिए धन्यवाद।
कॉर्बिन मार्च

2

टेस्ट केस करने की कोशिश करें। डेटाबेस से अपने अनुक्रम का उपयोग करके एक डमी टेबल बनाएं और 100,000 रिकॉर्ड डालें। मैं शर्त लगा रहा हूं कि आपको कोई समस्या नहीं होगी। अगला अपने आवेदन से एक ही चीज़ सम्मिलित करने का प्रयास करें।

क्या यह ओरेकल क्लाइंट मिसमैच जैसे अन्य मुद्दों के कारण हो सकता है?

एक और समाधान जो समस्या को ठीक करेगा लेकिन समस्या यह नहीं है कि तालिका में एक ट्रिगर जोड़ें।
Dallas.X IF पर तालिका में सम्मिलित होने से पहले: the_id null का चयन करें x_seq.nextval INTO: the_id दोहरी से; अगर अंत;


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

0

मेरे पास अभी तक टिप्पणी करने के लिए कोई पूर्वाग्रह नहीं है, इसलिए इसे उत्तर के रूप में लिखें: चूंकि आप Oracle संस्करण> = 11.1 का उपयोग कर रहे हैं, जो SQL के बजाय PL / SQL अभिव्यक्तियों में अनुक्रम की अनुमति देता है :

   v_id := x_seq.nextval;

इसके अलावा:

 -- Get id value from sequence
    SELECT x_seq.nextval
      INTO v_id
      FROM dual;

या, हालांकि मैंने ".currval" का उपयोग करते समय संदेह / नुकसान सुना है, शायद v_id के अलग असाइनमेंट को छोड़ दें और केवल इस कोड का उपयोग करें ?:

 -- Line below is X_PKG line 40
        INSERT INTO X
            (the_id,            
             name,                        
             update_userid)
          VALUES
            (x_seq.nextval,
             p_name,                        
             p_userid);

        -- Return new id
        OPEN cur_out FOR
            SELECT x_seq.currval the_id
              FROM dual;

क्षमा करें, मेरे पास अब इसे आज़माने के लिए 11g उदाहरण नहीं है।


यह निश्चित रूप से कोई फर्क नहीं पड़ता। मैं select into...9i और 10g में 11 का उपयोग करता हूं । 11+ से एकमात्र लाभ इसे स्पष्ट रूप से संदर्भित करने में सक्षम हो रहा है जैसा आपने बताया है।
बेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.