Làm cách nào để thiết lập lại một chuỗi trong Oracle?


169

Trong PostgreSQL , tôi có thể làm một cái gì đó như thế này:

ALTER SEQUENCE serial RESTART WITH 0;

Có tương đương với Oracle không?


1
Có một cái nhìn vào "Đặt lại trình tự" ở đây .
gerikson

3
CẢNH BÁO: tất cả các mã dưới đây chỉ hợp lệ cho các chuỗi được tạo ban đầu với "tăng thêm 1". Nếu chuỗi ban đầu được tạo với số gia! = 1; sau khi áp dụng bất kỳ quy trình nào ở trên, mức tăng sẽ thay đổi thành 1! Giá trị gia tăng chính xác để sử dụng có thể được lấy từ chế độ xem user_ resultences.

1
Thả và tạo lại chuỗi
Viswanath Lekshmanan

Câu trả lời:


152

Đây là một quy trình tốt để đặt lại bất kỳ chuỗi nào về 0 từ guru Tom Kyte của Oracle . Thảo luận tuyệt vời về những ưu và nhược điểm trong các liên kết dưới đây quá.

tkyte@TKYTE901.US.ORACLE.COM> 
create or replace
procedure reset_seq( p_seq_name in varchar2 )
is
    l_val number;
begin
    execute immediate
    'select ' || p_seq_name || '.nextval from dual' INTO l_val;

    execute immediate
    'alter sequence ' || p_seq_name || ' increment by -' || l_val || 
                                                          ' minvalue 0';

    execute immediate
    'select ' || p_seq_name || '.nextval from dual' INTO l_val;

    execute immediate
    'alter sequence ' || p_seq_name || ' increment by 1 minvalue 0';
end;
/

Từ trang này: SQL động để đặt lại giá trị chuỗi
Một cuộc thảo luận tốt khác cũng có ở đây: Làm cách nào để đặt lại chuỗi?


@Dougman: hi 'm người mới bắt đầu .... trong câu trả lời ở trên, tại sao bạn lại đề cập đến mệnh đề cuối cùng thay vì thực hiện ngay lập tức' chọn '| | p_seq_name | | '.nextval VÀO l_val từ kép';
Thiyagu ATR

@Thiyagu: Trong PL / SQL, đây là cú pháp khi sử dụng execute immediateđể nắm bắt đầu ra của một lựa chọn trả về tối đa 1 hàng. Dưới đây là tài liệu về thực thi ngay lập tức: docs.oracle.com/cd/B28359_01/appdev.111/b28370/ mẹo
Doug Porter

@matra Tôi không thấy một kịch bản trong đó người ta sẽ cần phải thiết lập lại một chuỗi và trong một môi trường đồng thời sẽ xóa sạch những người dùng khác của cùng một chuỗi.
Ekevoo

Tại sao bạn cần chọn chuỗi, tại sao không chỉ thực hiện dòng cuối cùng'alter sequence ' || p_seq_name || ' increment by 1 minvalue 0';
Goku

99

Một khởi động lại thực sự là không thể AFAIK . (Vui long sửa cho tôi nêu tôi sai!).

Tuy nhiên, nếu bạn muốn đặt thành 0, bạn chỉ cần xóa và tạo lại nó.

Nếu bạn muốn đặt giá trị cụ thể, bạn có thể đặt TĂNG thành giá trị âm và nhận giá trị tiếp theo.

Nghĩa là, nếu chuỗi của bạn ở mức 500, bạn có thể đặt nó thành 100 thông qua

ALTER SEQUENCE serial INCREMENT BY -400;
SELECT serial.NEXTVAL FROM dual;
ALTER SEQUENCE serial INCREMENT BY 1;

4
Chỉ cần một lưu ý cho những người trong PLQuery. Hãy chắc chắn để thêm "giới hạn 1;" hoặc "rownum = 1" cho câu lệnh chọn nếu không bạn có thể chạy nextVal một vài lần và tăng thêm -400 tuy nhiên nhiều lần.
dùng830914

1
Trình tự lỗi .NEXTVAL xuống dưới MINVALUE và không thể được khởi tạo khi TĂNG CƯỜNG B --NG - << big_number >>
zloctb 17/08/2015

47

Đây là cách tiếp cận của tôi:

  1. thả trình tự
  2. tái tạo nó

Thí dụ:

--Drop sequence

DROP SEQUENCE MY_SEQ;

-- Create sequence 

create sequence MY_SEQ
minvalue 1
maxvalue 999999999999999999999
start with 1
increment by 1
cache 20;

29
Chỉ cần lưu ý rằng sự sụt giảm sẽ làm mất hiệu lực bất kỳ đối tượng nào phụ thuộc vào chuỗi đó và chúng sẽ phải được biên dịch lại.
Doug Porter

22
Bạn cũng sẽ phải cấp lại bất kỳ khoản tài trợ nào được đưa ra để chọn từ trình tự.
GreenGiant

37
alter sequence serial restart start with 1;

Tính năng này đã được thêm chính thức vào năm 18c nhưng không chính thức có sẵn trong 12.1.

Có thể sử dụng tính năng không có giấy tờ này trong 12.1. Mặc dù cú pháp không được bao gồm trong tài liệu chính thức , nó được tạo bởi gói Oracle DBMS_METADATA_DIFF . Tôi đã sử dụng nó nhiều lần trên các hệ thống sản xuất. Tuy nhiên, tôi đã tạo một yêu cầu Dịch vụ Oracle và họ đã xác minh rằng đó không phải là lỗi tài liệu, tính năng này thực sự không được hỗ trợ.

Trong 18c, tính năng này không xuất hiện trong Cú pháp ngôn ngữ SQL, nhưng được bao gồm trong Hướng dẫn của quản trị viên cơ sở dữ liệu .


Xin chào @Jon, tôi biết về tính năng không có giấy tờ, tuy nhiên, tôi không biết nó được nhìn thấy trong tập lệnh được tạo từ DBMS_METADATA_DIFF. Bạn có thể cho tôi biết làm thế nào bạn tạo ra kịch bản, thủ tục nào vv? Tôi cũng sẽ thử kiểm tra nó.
Lalit Kumar B

@LalitKumarB Tôi tình cờ thấy tính năng đó trong khi trả lời câu hỏi này .
Jon Heller

1
Aah, hiểu rồi Cảm ơn :-)
Lalit Kumar B

Tôi đoán điều này đã được triển khai để hỗ trợ "bảng thay đổi your_table sửa đổi (id được tạo theo mặc định trên null khi nhận dạng bắt đầu bằng giá trị giới hạn);". Rất vui khi biết nó hoạt động trên trình tự tiêu chuẩn, quá!
Oliver

1
Trong trường hợp giá trị tối thiểu của phần tiếp theo lớn hơn 0 hãy xem xét việc viết... RESTART START WITH 0 MINVALUE 0
conIGHTtdeluxe

33

Cách tiếp cận của tôi là một phần mở rộng thiếu niên cho ví dụ của Dougman .

Tiện ích mở rộng là ...

Truyền vào giá trị hạt giống như một tham số. Tại sao? Tôi muốn gọi điều đặt lại chuỗi trở lại ID tối đa được sử dụng trong một số bảng . Tôi cuối cùng đã gọi Proc này từ một tập lệnh khác thực thi nhiều lệnh gọi cho một loạt các chuỗi, đặt lại giá trị tiếp theo xuống một mức đủ cao để không gây ra vi phạm khóa chính trong đó tôi đang sử dụng giá trị của chuỗi cho một mã định danh duy nhất.

Nó cũng tôn vinh giá trị tối thiểu trước đó . Trên thực tế, nó có thể đẩy giá trị tiếp theo cao hơn bao giờ nếu giá trị p_val hoặc giá trị hiện tại mong muốn cao hơn giá trị tiếp theo hiện tại hoặc được tính.

Tuyệt vời nhất, nó có thể được gọi để thiết lập lại một giá trị được chỉ định và chỉ cần đợi cho đến khi bạn thấy quy trình "sửa tất cả các chuỗi của tôi" ở cuối.

create or replace
procedure Reset_Sequence( p_seq_name in varchar2, p_val in number default 0)
is
  l_current number := 0;
  l_difference number := 0;
  l_minvalue user_sequences.min_value%type := 0;

begin

  select min_value
  into l_minvalue
  from user_sequences
  where sequence_name = p_seq_name;

  execute immediate
  'select ' || p_seq_name || '.nextval from dual' INTO l_current;

  if p_Val < l_minvalue then
    l_difference := l_minvalue - l_current;
  else
    l_difference := p_Val - l_current;
  end if;

  if l_difference = 0 then
    return;
  end if;

  execute immediate
    'alter sequence ' || p_seq_name || ' increment by ' || l_difference || 
       ' minvalue ' || l_minvalue;

  execute immediate
    'select ' || p_seq_name || '.nextval from dual' INTO l_difference;

  execute immediate
    'alter sequence ' || p_seq_name || ' increment by 1 minvalue ' || l_minvalue;
end Reset_Sequence;

Bản thân quy trình đó rất hữu ích, nhưng bây giờ chúng ta hãy thêm một quy trình khác gọi nó và chỉ định mọi thứ theo chương trình với quy ước đặt tên theo trình tự và tìm kiếm giá trị tối đa được sử dụng trong bảng / trường hiện có ...

create or replace
procedure Reset_Sequence_to_Data(
  p_TableName varchar2,
  p_FieldName varchar2
)
is
  l_MaxUsed NUMBER;
BEGIN

  execute immediate
    'select coalesce(max(' || p_FieldName || '),0) from '|| p_TableName into l_MaxUsed;

  Reset_Sequence( p_TableName || '_' || p_Fieldname || '_SEQ', l_MaxUsed );

END Reset_Sequence_to_Data;

Bây giờ chúng tôi đang nấu ăn bằng gas!

Quy trình trên sẽ kiểm tra giá trị tối đa của một trường trong bảng, xây dựng tên chuỗi từ cặp bảng / trường và gọi "Reset_Sequence" với giá trị tối đa được cảm nhận đó.

Mảnh ghép cuối cùng trong câu đố này và lớp kem trên bánh tiếp theo ...

create or replace
procedure Reset_All_Sequences
is
BEGIN

  Reset_Sequence_to_Data( 'ACTIVITYLOG', 'LOGID' );
  Reset_Sequence_to_Data( 'JOBSTATE', 'JOBID' );
  Reset_Sequence_to_Data( 'BATCH', 'BATCHID' );

END Reset_All_Sequences;

Trong cơ sở dữ liệu thực tế của tôi, có khoảng một trăm trình tự khác được thiết lập lại thông qua cơ chế này, do đó, có thêm 97 cuộc gọi tới Reset_Sequence_to_Data trong quy trình đó ở trên.

Yêu nó? Ghét nó? Vô tư?


2
Tôi thích nó. Tôi sẽ thêm một biến để nhận và lưu mức tăng theo giá trị từ bảng user_ resultences. (Nó có thể không phải là 1). Lưu ý: có thể cần phải sử dụng bảng all_ resultences thay thế. Trong trường hợp này, bạn cũng có thể muốn vượt qua trong Sequ_owner.
Harvest

1
Không thể nâng cao bạn đủ. Đây là một vấn đề khá phổ biến khi bạn xử lý di chuyển dữ liệu và đây là cách tiếp cận tốt nhất AFAIK nếu bạn bị mắc kẹt với các chuỗi.
Dominique Eav

1
Nâng cao bởi vì đây là một cách tiếp cận tuyệt vời. Nhược điểm duy nhất là nó có thể dẫn đến hành vi không thể đoán trước trong một hệ thống RAC, trong đó l_currentcó thể là một trong những giá trị khác nhau, tùy thuộc vào nút nào mà tập lệnh được chạy; chạy lại tập lệnh có thể dẫn đến kết quả khác nhau. Tôi tìm thấy nếu tôi chạy nó nhiều lần thì cuối cùng nó cũng giải quyết được một giá trị cụ thể.
Jeffrey Kemp

10

Kịch bản sau đây đặt chuỗi thành giá trị mong muốn:

Đưa ra một chuỗi mới được tạo có tên là PCS_PROJ_KEY_SEQ và bảng PCS_PROJ:

BEGIN
   DECLARE
      PROJ_KEY_MAX       NUMBER := 0;
      PROJ_KEY_CURRVAL   NUMBER := 0;
   BEGIN

    SELECT MAX (PROJ_KEY) INTO PROJ_KEY_MAX FROM PCS_PROJ;
    EXECUTE IMMEDIATE 'ALTER SEQUENCE PCS_PROJ_KEY_SEQ INCREMENT BY ' || PROJ_KEY_MAX;
    SELECT PCS_PROJ_KEY_SEQ.NEXTVAL INTO PROJ_KEY_CURRVAL FROM DUAL;
    EXECUTE IMMEDIATE 'ALTER SEQUENCE PCS_PROJ_KEY_SEQ INCREMENT BY 1';

END;
END;
/

1
Bạn đã quên điểm trừ trong câu lệnh DDL đầu tiên của mình (đồng thời, có thêm một ENDtừ khóa).
Priidu Neemre

5

Thủ tục lưu trữ này khởi động lại trình tự của tôi:

Create or Replace Procedure Reset_Sequence  
  is
  SeqNbr Number;
begin
   /*  Reset Sequence 'seqXRef_RowID' to 0    */
   Execute Immediate 'Select seqXRef.nextval from dual ' Into SeqNbr;
   Execute Immediate 'Alter sequence  seqXRef increment by - ' || TO_CHAR(SeqNbr) ;
   Execute Immediate 'Select seqXRef.nextval from dual ' Into SeqNbr;
   Execute Immediate 'Alter sequence  seqXRef increment by 1';
END;

/


+1 - Bạn cũng có thể tham số hóa nó để chuyển trong tên chuỗi.
DCookie

4

Có một cách khác để thiết lập lại một chuỗi trong Oracle: đặt các thuộc tính maxvaluecycle. Khi nextvalchuỗi này chạm vào maxvalue, nếu thuộc cycletính được đặt thì nó sẽ bắt đầu lại từ minvaluechuỗi.

Ưu điểm của phương pháp này so với đặt âm increment bylà trình tự có thể tiếp tục được sử dụng trong khi quá trình đặt lại chạy, giảm khả năng bạn cần thực hiện một số hình thức ngừng hoạt động để thực hiện đặt lại.

Giá trị cho maxvaluephải lớn hơn hiện tại nextval, vì vậy quy trình bên dưới bao gồm một tham số tùy chọn cho phép bộ đệm trong trường hợp chuỗi được truy cập lại giữa việc chọn nextvaltrong thủ tục và đặt thuộc cycletính.

create sequence s start with 1 increment by 1;

select s.nextval from dual
connect by level <= 20;

   NEXTVAL
----------
         1 
...
        20

create or replace procedure reset_sequence ( i_buffer in pls_integer default 0)
as
  maxval pls_integer;
begin

  maxval := s.nextval + greatest(i_buffer, 0); --ensure we don't go backwards!
  execute immediate 'alter sequence s cycle minvalue 0 maxvalue ' || maxval;
  maxval := s.nextval;
  execute immediate 'alter sequence s nocycle maxvalue 99999999999999';

end;
/
show errors

exec reset_sequence;

select s.nextval from dual;

   NEXTVAL
----------
         1 

Quy trình dưới dạng đứng yên cho phép khả năng phiên khác sẽ lấy giá trị 0, điều này có thể hoặc không phải là vấn đề đối với bạn. Nếu có, bạn luôn có thể:

  • Đặt minvalue 1trong thay đổi đầu tiên
  • Loại trừ lần nextvaltải thứ hai
  • Di chuyển câu lệnh để đặt thuộc nocycletính vào một thủ tục khác, sẽ được chạy vào một ngày sau đó (giả sử bạn muốn làm điều này).

3

Jezus, tất cả các chương trình này chỉ để khởi động lại chỉ mục ... Có lẽ tôi là một thằng ngốc, nhưng đối với tiền truyện 12 (có tính năng khởi động lại), có gì sai với một simpel:

drop sequence blah;
create sequence blah 

?


2
Vấn đề chính với việc bỏ một chuỗi là nó mất các đặc quyền được cấp trên nó.
Jon Heller

1
Được rồi, Jon. Chủ yếu là khôi phục những thứ này sẽ tốn ít thời gian hơn nhiều so với tất cả các chương trình đó. Các DBA tốt thường có các tập lệnh nên không phải là vấn đề :-)
Lawrence

2

1) Giả sử bạn tạo một SEQUENCE như hiển thị bên dưới:

CREATE SEQUENCE TESTSEQ
INCREMENT BY 1
MINVALUE 1
MAXVALUE 500
NOCACHE
NOCYCLE
NOORDER

2) Bây giờ bạn lấy các giá trị từ SEQUENCE. Hãy nói rằng tôi đã lấy bốn lần như hình dưới đây.

SELECT TESTSEQ.NEXTVAL FROM dual
SELECT TESTSEQ.NEXTVAL FROM dual
SELECT TESTSEQ.NEXTVAL FROM dual
SELECT TESTSEQ.NEXTVAL FROM dual

3) Sau khi thực hiện bốn lệnh trên, giá trị của SEQUENCE sẽ là 4. Bây giờ giả sử tôi đã đặt lại giá trị của SEQUENCE thành 1 lần nữa. Các bước sau đây. Thực hiện theo tất cả các bước theo cùng một thứ tự như dưới đây:

  1. ALTER SEQUENCE TESTSEQ INCREMENT BY -3;
  2. SELECT TESTSEQ.NEXTVAL FROM dual
  3. ALTER SEQUENCE TESTSEQ INCREMENT BY 1;
  4. SELECT TESTSEQ.NEXTVAL FROM dual

2

Việc thay đổi giá trị TĂNG CƯỜNG của chuỗi, tăng nó và sau đó thay đổi lại là khá đau đớn, cộng với bạn có thêm lợi ích là không phải thiết lập lại tất cả các khoản trợ cấp như bạn đã bỏ / tạo lại chuỗi.


2

Tôi tạo một khối để thiết lập lại tất cả các chuỗi của mình:

DECLARE
    I_val number;
BEGIN
    FOR US IN
        (SELECT US.SEQUENCE_NAME FROM USER_SEQUENCES US)
    LOOP
        execute immediate 'select ' || US.SEQUENCE_NAME || '.nextval from dual' INTO l_val;
        execute immediate 'alter sequence ' || US.SEQUENCE_NAME || ' increment by -' || l_val || ' minvalue 0';
        execute immediate 'select ' || US.SEQUENCE_NAME || '.nextval from dual' INTO l_val;
        execute immediate 'alter sequence ' || US.SEQUENCE_NAME || ' increment by 1 minvalue 0';
    END LOOP;
END;

2

Đây là một quy trình mạnh mẽ hơn để thay đổi giá trị tiếp theo được trả về bởi một chuỗi, cộng với nhiều hơn nữa.

  • Trước hết, nó bảo vệ chống lại các cuộc tấn công tiêm nhiễm SQL vì không có chuỗi nào được truyền vào được sử dụng để trực tiếp tạo bất kỳ câu lệnh SQL động nào,
  • Thứ hai, nó ngăn giá trị chuỗi tiếp theo được đặt bên ngoài giới hạn của các giá trị chuỗi tối thiểu hoặc tối đa. Các next_valuesẽ được! = min_value, Giữa min_valuemax_value.
  • Thứ ba, nó đưa increment_bycài đặt hiện tại (hoặc được đề xuất) cũng như tất cả các cài đặt trình tự khác vào tài khoản khi dọn dẹp.
  • Thứ tư, tất cả các tham số ngoại trừ tham số đầu tiên là tùy chọn và trừ khi được chỉ định thực hiện cài đặt trình tự hiện tại làm mặc định. Nếu không có tham số tùy chọn được chỉ định, không có hành động được thực hiện.
  • Cuối cùng, nếu bạn cố gắng thay đổi một chuỗi không tồn tại (hoặc không thuộc sở hữu của người dùng hiện tại), nó sẽ gây ra ORA-01403: no data foundlỗi.

Đây là mã:

CREATE OR REPLACE PROCEDURE alter_sequence(
    seq_name      user_sequences.sequence_name%TYPE
  , next_value    user_sequences.last_number%TYPE := null
  , increment_by  user_sequences.increment_by%TYPE := null
  , min_value     user_sequences.min_value%TYPE := null
  , max_value     user_sequences.max_value%TYPE := null
  , cycle_flag    user_sequences.cycle_flag%TYPE := null
  , cache_size    user_sequences.cache_size%TYPE := null
  , order_flag    user_sequences.order_flag%TYPE := null)
  AUTHID CURRENT_USER
AS
  l_seq user_sequences%rowtype;
  l_old_cache user_sequences.cache_size%TYPE;
  l_next user_sequences.min_value%TYPE;
BEGIN
  -- Get current sequence settings as defaults
  SELECT * INTO l_seq FROM user_sequences WHERE sequence_name = seq_name;

  -- Update target settings
  l_old_cache := l_seq.cache_size;
  l_seq.increment_by := nvl(increment_by, l_seq.increment_by);
  l_seq.min_value    := nvl(min_value, l_seq.min_value);
  l_seq.max_value    := nvl(max_value, l_seq.max_value);
  l_seq.cycle_flag   := nvl(cycle_flag, l_seq.cycle_flag);
  l_seq.cache_size   := nvl(cache_size, l_seq.cache_size);
  l_seq.order_flag   := nvl(order_flag, l_seq.order_flag);

  IF next_value is NOT NULL THEN
    -- Determine next value without exceeding limits
    l_next := LEAST(GREATEST(next_value, l_seq.min_value+1),l_seq.max_value);

    -- Grab the actual latest seq number
    EXECUTE IMMEDIATE
        'ALTER SEQUENCE '||l_seq.sequence_name
            || ' INCREMENT BY 1'
            || ' MINVALUE '||least(l_seq.min_value,l_seq.last_number-l_old_cache)
            || ' MAXVALUE '||greatest(l_seq.max_value,l_seq.last_number)
            || ' NOCACHE'
            || ' ORDER';
    EXECUTE IMMEDIATE 
      'SELECT '||l_seq.sequence_name||'.NEXTVAL FROM DUAL'
    INTO l_seq.last_number;

    l_next := l_next-l_seq.last_number-1;

    -- Reset the sequence number
    IF l_next <> 0 THEN
      EXECUTE IMMEDIATE 
        'ALTER SEQUENCE '||l_seq.sequence_name
            || ' INCREMENT BY '||l_next
            || ' MINVALUE '||least(l_seq.min_value,l_seq.last_number)
            || ' MAXVALUE '||greatest(l_seq.max_value,l_seq.last_number)
            || ' NOCACHE'
            || ' ORDER';
      EXECUTE IMMEDIATE 
        'SELECT '||l_seq.sequence_name||'.NEXTVAL FROM DUAL'
      INTO l_next;
    END IF;
  END IF;

  -- Prepare Sequence for next use.
  IF COALESCE( cycle_flag
             , next_value
             , increment_by
             , min_value
             , max_value
             , cache_size
             , order_flag) IS NOT NULL
  THEN
    EXECUTE IMMEDIATE 
      'ALTER SEQUENCE '||l_seq.sequence_name
          || ' INCREMENT BY '||l_seq.increment_by
          || ' MINVALUE '||l_seq.min_value
          || ' MAXVALUE '||l_seq.max_value
          || CASE l_seq.cycle_flag
             WHEN 'Y' THEN ' CYCLE' ELSE ' NOCYCLE' END
          || CASE l_seq.cache_size
             WHEN 0 THEN ' NOCACHE'
             ELSE ' CACHE '||l_seq.cache_size END
          || CASE l_seq.order_flag
             WHEN 'Y' THEN ' ORDER' ELSE ' NOORDER' END;
  END IF;
END;

2

Trong dự án của tôi, một khi đã xảy ra việc ai đó nhập thủ công các bản ghi mà không sử dụng trình tự, do đó tôi phải đặt lại giá trị trình tự theo cách thủ công, mà tôi đã viết bên dưới đoạn mã sql:

declare
max_db_value number(10,0);
cur_seq_value number(10,0);
counter number(10,0);
difference number(10,0);
dummy_number number(10);

begin

-- enter table name here
select max(id) into max_db_value from persons;
-- enter sequence name here
select last_number into cur_seq_value from user_sequences where  sequence_name = 'SEQ_PERSONS';

difference  := max_db_value - cur_seq_value;

 for counter in 1..difference
 loop
    -- change sequence name here as well
    select SEQ_PERSONS.nextval into dummy_number from dual;
 end loop;
end;

Xin lưu ý, đoạn mã trên sẽ hoạt động nếu chuỗi bị trễ.


1

Bạn có thể sử dụng tùy chọn CYCLE, hiển thị bên dưới:

CREATE SEQUENCE test_seq
MINVALUE 0
MAXVALUE 100
START WITH 0
INCREMENT BY 1
CYCLE;

Trong trường hợp này, khi chuỗi đạt MAXVALUE (100), nó sẽ tái chế thành MINVALUE (0).

Trong trường hợp trình tự giảm dần, trình tự sẽ tái chế thành MAXVALUE.


1
Đối với các downvoters (những người sẽ không bao giờ thấy bình luận này): Thuộc tính CYCLE chính xác là những gì tôi đã sử dụng để thực hiện thiết lập lại trình tự. Thực tế là việc thiết lập lại là tự động không có nghĩa là nó không hoàn thành mục tiêu - OP không xác định rằng việc thiết lập lại phải dành cho một chuỗi có sẵn !
Jeromy Pháp

1

Đây là cách làm cho tất cả các chuỗi tăng tự động khớp với dữ liệu thực tế:

  1. Tạo một thủ tục để thực thi giá trị tiếp theo như đã được mô tả trong chuỗi này:

    CREATE OR REPLACE PROCEDURE Reset_Sequence(
        P_Seq_Name IN VARCHAR2,
        P_Val      IN NUMBER DEFAULT 0)
    IS
      L_Current    NUMBER                      := 0;
      L_Difference NUMBER                      := 0;
      L_Minvalue User_Sequences.Min_Value%Type := 0;
    BEGIN
      SELECT Min_Value
      INTO L_Minvalue
      FROM User_Sequences
      WHERE Sequence_Name = P_Seq_Name;
      EXECUTE Immediate 'select ' || P_Seq_Name || '.nextval from dual' INTO L_Current;
      IF P_Val        < L_Minvalue THEN
        L_Difference := L_Minvalue - L_Current;
      ELSE
        L_Difference := P_Val - L_Current;
      END IF;
      IF L_Difference = 0 THEN
        RETURN;
      END IF;
      EXECUTE Immediate 'alter sequence ' || P_Seq_Name || ' increment by ' || L_Difference || ' minvalue ' || L_Minvalue;
      EXECUTE Immediate 'select ' || P_Seq_Name || '.nextval from dual' INTO L_Difference;
      EXECUTE Immediate 'alter sequence ' || P_Seq_Name || ' increment by 1 minvalue ' || L_Minvalue;
    END Reset_Sequence;
  2. Tạo một quy trình khác để điều hòa tất cả các chuỗi với nội dung thực tế:

    CREATE OR REPLACE PROCEDURE RESET_USER_SEQUENCES_TO_DATA
    IS
      STMT CLOB;
    BEGIN
      SELECT 'select ''BEGIN'' || chr(10) || x || chr(10) || ''END;'' FROM (select listagg(x, chr(10)) within group (order by null) x FROM ('
        || X
        || '))'
      INTO STMT
      FROM
        (SELECT LISTAGG(X, ' union ') WITHIN GROUP (
        ORDER BY NULL) X
        FROM
          (SELECT CHR(10)
            || 'select ''Reset_Sequence('''''
            || SEQ_NAME
            || ''''','' || coalesce(max('
            || COL_NAME
            || '), 0) || '');'' x from '
            || TABLE_NAME X
          FROM
            (SELECT TABLE_NAME,
              REGEXP_SUBSTR(WTEXT, 'NEW\.(\S*) IS NULL',1,1,'i',1) COL_NAME,
              REGEXP_SUBSTR(BTEXT, '(\.|\s)([a-z_]*)\.nextval',1,1,'i',2) SEQ_NAME
            FROM USER_TRIGGERS
            LEFT JOIN
              (SELECT NAME BNAME,
                TEXT BTEXT
              FROM USER_SOURCE
              WHERE TYPE = 'TRIGGER'
              AND UPPER(TEXT) LIKE '%NEXTVAL%'
              )
            ON BNAME = TRIGGER_NAME
            LEFT JOIN
              (SELECT NAME WNAME,
                TEXT WTEXT
              FROM USER_SOURCE
              WHERE TYPE = 'TRIGGER'
              AND UPPER(TEXT) LIKE '%IS NULL%'
              )
            ON WNAME             = TRIGGER_NAME
            WHERE TRIGGER_TYPE   = 'BEFORE EACH ROW'
            AND TRIGGERING_EVENT = 'INSERT'
            )
          )
        ) ;
      EXECUTE IMMEDIATE STMT INTO STMT;
      --dbms_output.put_line(stmt);
      EXECUTE IMMEDIATE STMT;
    END RESET_USER_SEQUENCES_TO_DATA;

GHI CHÚ:

  1. Quy trình trích xuất tên từ mã kích hoạt và không phụ thuộc vào quy ước đặt tên
  2. Để kiểm tra mã được tạo trước khi thực hiện, hãy chuyển nhận xét trên hai dòng cuối cùng

1

Tôi thực hiện một thay thế mà người dùng không cần biết các giá trị, hệ thống nhận và sử dụng các biến để cập nhật.

--Atualizando sequence da tabela SIGA_TRANSACAO, pois está desatualizada
DECLARE
 actual_sequence_number INTEGER;
 max_number_from_table INTEGER;
 difference INTEGER;
BEGIN
 SELECT [nome_da_sequence].nextval INTO actual_sequence_number FROM DUAL;
 SELECT MAX([nome_da_coluna]) INTO max_number_from_table FROM [nome_da_tabela];
 SELECT (max_number_from_table-actual_sequence_number) INTO difference FROM DUAL;
IF difference > 0 then
 EXECUTE IMMEDIATE CONCAT('alter sequence [nome_da_sequence] increment by ', difference);
 --aqui ele puxa o próximo valor usando o incremento necessário
 SELECT [nome_da_sequence].nextval INTO actual_sequence_number from dual;
--aqui volta o incremento para 1, para que futuras inserções funcionem normalmente
 EXECUTE IMMEDIATE 'ALTER SEQUENCE [nome_da_sequence] INCREMENT by 1';
 DBMS_OUTPUT.put_line ('A sequence [nome_da_sequence] foi atualizada.');
ELSE
 DBMS_OUTPUT.put_line ('A sequence [nome_da_sequence] NÃO foi atualizada, já estava OK!');
END IF;
END;

-1

Thủ tục lưu trữ làm việc cho tôi

create or replace
procedure reset_sequence( p_seq_name in varchar2, tablename in varchar2 )
is
    l_val number;
    maxvalueid number;
begin
    execute immediate 'select ' || p_seq_name || '.nextval from dual' INTO l_val;
    execute immediate 'select max(id) from ' || tablename INTO maxvalueid;
    execute immediate 'alter sequence ' || p_seq_name || ' increment by -' || l_val || ' minvalue 0';
    execute immediate 'select ' || p_seq_name || '.nextval from dual' INTO l_val;
    execute immediate 'alter sequence ' || p_seq_name || ' increment by '|| maxvalueid ||' minvalue 0';  
    execute immediate 'select ' || p_seq_name || '.nextval from dual' INTO l_val;
    execute immediate 'alter sequence ' || p_seq_name || ' increment by 1 minvalue 0';
end;

Cách sử dụng thủ tục được lưu trữ:

execute reset_sequence('company_sequence','company');
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.