2011-05-23 16 views
29

किसी कारण से, अतीत में लोगों ने अनुक्रम का उपयोग किए बिना डेटा डाला है .EXTVAL। तो जब मैं तालिका को पॉप्युलेट करने के क्रम में अनुक्रम का उपयोग करने के लिए जाता हूं, तो मुझे एक पीके उल्लंघन मिलता है, क्योंकि उस नंबर में पहले से ही तालिका में उपयोग किया जा रहा है।मौजूदा कॉलम में अगले मान पर ओरेकल अनुक्रम को रीसेट करने का सबसे अच्छा तरीका?

मैं अगले मूल्य को कैसे अपडेट कर सकता हूं ताकि यह उपयोग योग्य हो सके? अभी, मैं सफल होने तक बस ऊपर और ऊपर डाल रहा हूं (INSERT INTO tbl (pk) VALUES (sequence.NEXTVAL)), और यह अगली कड़ी को सिंक करता है।

+0

@rationalSpring मैंने अनुक्रम को छोड़ने और फिर से बनाने का निर्णय लिया। –

+0

देखें [यह वही सवाल] (http://stackoverflow.com/questions/6057191/sequence-creation-in-oracle/6057249#6057249) –

+1

अनुक्रम छोड़ने और पुनर्निर्माण के साथ समस्या यह है कि आपको किसी को फिर से लागू करना होगा इस पर अनुदान (उल्लेख नहीं है कि यह किसी भी विचार या पीएल/एसक्यूएल को अस्थायी रूप से अमान्य करता है जो इसे संदर्भित करता है)। –

उत्तर

13

इन दो प्रक्रियाओं ने मुझे अनुक्रम को रीसेट करने और डेटा के आधार पर अनुक्रम को रीसेट करने दिया है एक मेज (इस ग्राहक के द्वारा उपयोग कोडिंग सम्मेलनों के लिए क्षमा याचना):

CREATE OR REPLACE PROCEDURE SET_SEQ_TO(p_name IN VARCHAR2, p_val IN NUMBER) 
AS 
    l_num NUMBER; 
BEGIN 
    EXECUTE IMMEDIATE 'select ' || p_name || '.nextval from dual' INTO l_num; 

    -- Added check for 0 to avoid "ORA-04002: INCREMENT must be a non-zero integer" 
    IF (p_val - l_num - 1) != 0 
    THEN 
     EXECUTE IMMEDIATE 'alter sequence ' || p_name || ' increment by ' || (p_val - l_num - 1) || ' minvalue 0'; 
    END IF; 

    EXECUTE IMMEDIATE 'select ' || p_name || '.nextval from dual' INTO l_num; 

    EXECUTE IMMEDIATE 'alter sequence ' || p_name || ' increment by 1 '; 

    DBMS_OUTPUT.put_line('Sequence ' || p_name || ' is now at ' || p_val); 
END; 

CREATE OR REPLACE PROCEDURE SET_SEQ_TO_DATA(seq_name IN VARCHAR2, table_name IN VARCHAR2, col_name IN VARCHAR2) 
AS 
    nextnum NUMBER; 
BEGIN 
    EXECUTE IMMEDIATE 'SELECT MAX(' || col_name || ') + 1 AS n FROM ' || table_name INTO nextnum; 

    SET_SEQ_TO(seq_name, nextnum); 
END; 
+0

के बाद इसे "अंत IF" की आवश्यकता है क्या यह 11 जी के साथ काम करता है? मुझे "अज्ञात सेट विकल्प ~~~" – Worthy7

53

आप अस्थायी रूप से कैश आकार बढ़ाने के लिए और एक डमी का चयन करते हैं और उसके बाद तो उदाहरण

ALTER SEQUENCE mysequence INCREMENT BY 100; 

select mysequence.nextval from dual; 

ALTER SEQUENCE mysequence INCREMENT BY 1; 
+4

स्नीकी। मुझें यह पसंद है। –

+1

आप यह सुनिश्चित करना चाहते हैं कि कोई भी बदलाव बदलते समय अनुक्रम का उपयोग नहीं कर रहा हो। –

9

आप समय की अवधि के लिए होने जहां तालिका है पर भरोसा कर सकते हैं के लिए 1. करने के लिए तेह कैश आकार रीसेट वापस कर सकते हैं में कोई नया आवेषण के साथ एक स्थिर स्थिति में चल रहा है, इस लिए यह (untested) करना चाहिए:

DECLARE 
    last_used NUMBER; 
    curr_seq NUMBER; 
BEGIN 
    SELECT MAX(pk_val) INTO last_used FROM your_table; 

    LOOP 
    SELECT your_seq.NEXTVAL INTO curr_seq FROM dual; 
    IF curr_seq >= last_used THEN EXIT; 
    END IF; 
    END LOOP; 
END; 

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

+1

यह काम करता है, आईएफ लाइन – tomgeraghty3

9

ओरेकल 10.2g के साथ:

select level, sequence.NEXTVAL 
from dual 
connect by level <= (select max(pk) from tbl); 

अपनी तालिका के अधिकतम (पी) के लिए वर्तमान अनुक्रम मूल्य सेट हो जाएगा (यानी NEXTVAL के लिए अगली कॉल आपको सही परिणाम देगा); यदि आप टॉड का उपयोग करते हैं, तो कथन चलाने के लिए F5 दबाएं, F9 नहीं, जो आउटपुट पेज (इस प्रकार, आमतौर पर 500 पंक्तियों के बाद वृद्धि को रोकता है)। अच्छी तरफ: यह समाधान केवल डीएमएल है, डीडीएल नहीं। केवल एसक्यूएल और पीएल-एसक्यूएल नहीं। बुरा पक्ष: इस समाधान प्रिंट अधिकतम (पी) उत्पादन की पंक्तियों से, यानी आम तौर पर ALTER SEQUENCE समाधान की तुलना में धीमी है।

+0

नहीं मिल रहा है 'अधिकतम (पीके) + 1'? – Worthy7

+0

नहीं: अनुक्रम का चयन करने के बाद, अनुक्रम का वर्तमान मान अधिकतम (पीके) होगा, इसलिए, जब आपको अनुक्रम का अगला मान चाहिए, तो अनुक्रम कॉलिंग .EXTVAL आपको अधिकतम (पीके) +1 का मान देगा। वैसे भी, इसे आज़माएं: यह सुंदर है। – tech

4

मेरे मामले में मैं एक दृश्य PS_LOG_SEQ कहा जाता है जो एक LAST_NUMBER = 3920 था की है।

फिर मैंने अपनी स्थानीय मशीन पर PROD से कुछ डेटा आयात किया और PS_LOG तालिका में डाला। उत्पादन डेटा नवीनतम LOG_ID (प्राथमिक कुंजी) 20070. किया जा रहा है का आयात मैं इस तालिका में नई पंक्तियों को सम्मिलित करने की कोशिश की करने के बाद से अधिक 20000 पंक्तियों था, लेकिन जब बचत मैं इस तरह एक अपवाद है:

ORA-00001: unique constraint (LOG.PS_LOG_PK) violated 

निश्चित रूप से यह है अनुक्रम PS_LOG_SEQPS_LOG तालिका के साथ जुड़े के साथ क्या करना। LAST_NUMBER डेटा मैं आयातित जो पहले से ही PS_LOG_SEQ से अगले ID मान का इस्तेमाल किया था के साथ टकराने की गई थी।

हल करने के लिए है कि मैं नवीनतम \ max(LOG_ID) + 1 के अनुक्रम अद्यतन करने के लिए इस आदेश का प्रयोग किया है:

alter sequence PS_LOG_SEQ restart start with 20071; 

यह आदेश LAST_NUMBER मूल्य रीसेट और मैं तो तालिका में नई पंक्तियाँ सम्मिलित कर सकता है। कोई और अधिक टक्कर।:)

नोट: इस alter sequence आदेश ओरेकल 12C में नया है।