Oracle 9 - إعادة ضبط التسلسل ليتناسب مع حالة الجدول
سؤال
لدي تسلسل يستخدم لبذر مفاتيحي الأساسية (المعتمدة على عدد صحيح) في جدول أوراكل.
يبدو أن هذا التسلسل لم يتم استخدامه دائمًا لإدراج قيم جديدة في الجدول.كيف يمكنني استعادة التسلسل بما يتوافق مع القيم الفعلية في الجدول؟
المحلول
إذا كان المعرف هو اسم عمود PK الخاص بك وكان PK_SEQ هو اسم التسلسل الخاص بك:
أوجد قيمة أعلى PK بواسطة حدد الحد الأقصى (المعرف) من اسم الجدول
أوجد قيمة PK_SEQ التالية ب حدد PK_SEQ. نكستفال من دوال
- إذا كان # 2 > # 1 ثم لا شيء يجب أن يكون تم ، على افتراض أنك تعامل هذه القيم كمفاتيح بديلة حقيقية
- وإلا، فقم بتغيير التسلسل إلى انتقل إلى الحد الأقصى للمعرف بواسطة ALTER SEQUENCE PK_SEQ الزيادة بمقدار [#1 القيمة - #2 القيمة]
عثرة التسلسل بواسطة SELECT PK_SEQ. نكستفال من دوال
إعادة تعيين قيمة زيادة التسلسل إلى 1 بواسطة PK_SEQ تسلسل ALTER زيادة بمقدار 1
يفترض كل هذا أنه ليس لديك إدراجات جديدة في الجدول أثناء قيامك بذلك...
نصائح أخرى
في قصيرة، لعبة ما يلي:
-- Current sequence value is 1000
ALTER SEQUENCE x INCREMENT BY -999;
Sequence altered.
SELECT X.NEXTVAL FROM DUAL;
1
ALTER SEQUENCE x INCREMENT BY 1;
Sequence altered.
ويمكنك الحصول على قيمة تسلسل ماكس المستخدمة في الجدول الخاص بك، تفعل الرياضيات، وتحديث تسلسل وفقا لذلك.
Declare
difference INTEGER;
sqlstmt varchar2(255);
sequenceValue Number;
begin
sqlstmt := 'ALTER SEQUENCE YOURSEQUENCE INCREMENT BY ';
select YOURSEQUENCE.NEXTVAL into sequenceValue from dual;
select (nvl(Max(YOURID),0) - sequenceValue)+1 into difference from YOURTABLE;
if difference > 0 then
EXECUTE IMMEDIATE sqlstmt || difference;
select YOURSEQUENCE.NEXTVAL INTO sequenceValue from dual;
EXECUTE IMMEDIATE sqlstmt || 1;
end if;
end;
وأنا جعلت هذا البرنامج النصي كما لم أجد السيناريو على الانترنت ان حيوي يحدد <م> جميع م> بلدي متواليات لأعلى ID الحالي. اختبارها على أوراكل 11.2.0.4.
DECLARE
difference INTEGER;
sqlstmt VARCHAR2(255) ;
sqlstmt2 VARCHAR2(255) ;
sqlstmt3 VARCHAR2(255) ;
sequenceValue NUMBER;
sequencename VARCHAR2(30) ;
sequencelastnumber INTEGER;
CURSOR allseq
IS
SELECT sequence_name, last_number FROM user_sequences ORDER BY sequence_name;
BEGIN
DBMS_OUTPUT.enable(32000) ;
OPEN allseq;
LOOP
FETCH allseq INTO sequencename, sequencelastnumber;
EXIT
WHEN allseq%NOTFOUND;
sqlstmt := 'ALTER SEQUENCE ' || sequencename || ' INCREMENT BY ';
--Assuming: <tablename>_id is <sequencename>
sqlstmt2 := 'select (nvl(Max(ID),0) - :1)+1 from ' || SUBSTR(sequencename, 1, LENGTH(sequencename) - 3) ;
--DBMS_OUTPUT.PUT_LINE(sqlstmt2);
--Attention: makes use of user_sequences.last_number --> possible cache problems!
EXECUTE IMMEDIATE sqlstmt2 INTO difference USING sequencelastnumber;
IF difference > 0 THEN
DBMS_OUTPUT.PUT_LINE('EXECUTE IMMEDIATE ' || sqlstmt || difference) ;
EXECUTE IMMEDIATE sqlstmt || difference;
sqlstmt3 := 'SELECT ' || sequencename ||'.NEXTVAL from dual';
DBMS_OUTPUT.PUT_LINE('EXECUTE IMMEDIATE ' || sqlstmt3 || ' INTO sequenceValue') ;
EXECUTE IMMEDIATE sqlstmt3 INTO sequenceValue;
DBMS_OUTPUT.PUT_LINE('EXECUTE IMMEDIATE ' || sqlstmt || 1) ;
EXECUTE IMMEDIATE sqlstmt || 1;
DBMS_OUTPUT.PUT_LINE('') ;
END IF;
END LOOP;
CLOSE allseq;
END;
في بعض الحالات، قد تجد أنه من الأسهل لمجرد الحصول على قيمة الحد الأقصى الحالية ثم
drop sequence x;
create sequence x start with {current max + 1};
وسيتم تقسيم التطبيق بعد القيام الهبوط. ولكن من شأنها أن تبقي أي شخص من إدراج صفوف خلال تلك الفترة، وخلق تسلسل سريع. تأكد من إعادة أي المنح على تسلسل منذ سيتم إسقاط تلك عندما التسلسل. وقد ترغب في إعادة ترجمة أي plsql التي تعتمد على تسلسل يدويا.
وإضافة إلى https://stackoverflow.com/a/15929548/1737973 ، ولكن دون اللجوء إلى SEQUENCENAME.NEXTVAL
بالتالي لا يؤدي في موقف واحد أكثر من ذلك يجب أن تكون:
DECLARE
difference INTEGER;
alter_sequence_statement VARCHAR2 (255);
sequence_value NUMBER;
BEGIN
-- Base for the statement that will set the sequence value.
alter_sequence_statement :=
'ALTER SEQUENCE SEQUENCENAME INCREMENT BY ';
-- Fetch current last sequence value used.
SELECT
-- You could maybe want to make some further computations just
-- below if the sequence is using caching.
last_number
INTO sequence_value
FROM all_sequences
WHERE sequence_owner = 'SEQUENCEOWNER' AND sequence_name = 'SEQUENCENAME';
-- Compute the difference.
SELECT max(id) - sequence_value + 1 INTO difference
FROM SCHEMANAME.TABLENAME;
IF difference <> 0 THEN
-- Set the increment to a big offset that puts the sequence near
-- its proper value.
EXECUTE IMMEDIATE alter_sequence_statement || difference;
-- This 'sequence_value' will be ignored, on purpose.
SELECT SEQUENCENAME.NEXTVAL INTO sequence_value FROM dual;
-- Resume the normal pace of incrementing one by one.
EXECUTE IMMEDIATE alter_sequence_statement || 1;
END IF;
END;
تنويه: إذا كان تسلسل يستخدم التخزين المؤقت (مجموعة all_sequences.cache_size
إلى أكبر من 0) ربما كنت ترغب في أخذه بعين الاعتبار في م> احسب الفرق <م> الخطوة م>