質問

PostgreSQL, んでいて思ったこと。

ALTER SEQUENCE serial RESTART WITH 0;

はありまOracle等?

役に立ちましたか?

解決

この手続きのリセット用のあらゆるシークエンスは0からOracleグ Tom Kyte.シミュレーションに是非、以下のリンクです。

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;
/

このページ: 動的SQLをリセットシーケンス値
これからも議論もここにあります: どのようにリセット配列か?

他のヒント

真の再起動はできません AFAIK.(修正してくださいばん違います。).

しかし、したい場合はセットで0できるため、削除、再作成します。

したい場合に設定しても構いませんが特定の値を設定することができ値に負の値を次の値です。

ある場合、シーケンスが500設定することができます100によ

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

これが私のアプローチ:

  1. ドロップで配列
  2. を再現で

例:

--Drop sequence

DROP SEQUENCE MY_SEQ;

-- Create sequence 

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

私のアプローチはteensyへの拡張 Dougmanの例.

拡張子は---

パス種としての価値パラメータとします。なぜですか?私はかつてのものをリセットの配列に戻る 最大IDの使用についテーブル.私はこの演からスクリプトを実行する複数の電話用のビバップからハードバップの配列をリセットnextvalがあり一部のレベルが高いのに十分な主キー違反がんのシーケンスの値を目的とした独自の識別子です。

また表彰前 minvalue.れする可能性があるという を押して次の値より高い 希望通りの p_val または 既存のminvalue より高く、現行もしくは次の計算値です。

すべてのベストで呼び出すことができるリセットを指定された値で見えますラッパー"fix全ての配列"にて手続します。

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;

この手続きはすべて、もう一つと同じものを見ることができないを指定しまョンと命名規則配列の最大値を使用して、既存のテーブル/野---

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;

てきましたお料理とガス!

は、上記手順確認のためのフィールドの最大値でのテーブル、列の名前からのテーブル/フィールドのペアやソッドを呼び出し "Reset_Sequence" と感じ最大値です。

最後のピースはこのパズルの着氷のケーキ付...

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;

私の実際のデータベースにある百その他の配列がリセットを通じてこのメカニズムであ97以上の通話を Reset_Sequence_to_Data この手順です。

愛のですか?嫌いなのですか?無関心?

alter sequence serial restart start with 0;

この特集では、新しいOracle12c.であ ない に含まれ 公式文書.なかなスクリプトでは発生するOracleパッケージ DBMS_METADATA_DIFF.

警告: 私はこの機能を複数回生産システムは、私の意見ではこのコマンドアドホックのイントロダクションです。で入手できるかもしれませんが、いまでの手続きにより一部アプリケーションの一部。また、Oracleサービスご依頼いてこの機能;単なる文書のバグで未サポートします。が可能で、コマンドがなくないように WM_CONCAT.(私は必要なものだけを購入できるよう考-Oracleの構文なが消えるすべきと思うかもしれないが、簡単な特徴は内部的に使用される少なくとも二つの場所)

以下のスクリプト設定のシーケンスを所望の値:

与えられ出来たて作成した列の名前PCS_PROJ_KEY_SEQ表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;
/

この 格納手続き 再私の列:

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;

/

もう一つの方法がありリセット配列Oracle:の設定 maxvaluecycle ます。場合に nextval の並び順のシーケンスにぶつかることから、 maxvalue, 場合、 cycle 宿泊施設はその始まりから minvalue のシーケンスです。

この方法の利点と比べて設定負 increment by は、シーケンスをつくり続けることができます。を利用してのリセット処理、削減の機会を取る必要があり何らかの障害のリセットします。

の値 maxvalue れ以上の電流 nextval, ので、下記の手続きを含むオプションのパラメータをバッファの場合、シーケンスが再度アクセス間の選択 nextval の手順で設定する cycle 物件です。

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 

の手順として動作をする可能性別セッションを取得する値0を示すものではありませんが問題です。であれば、常に

  • セット minvalue 1 最初の変更
  • を除く第二 nextval フェッチ
  • 移動の決定 nocycle 物件別の手続きに実行される後日と仮定しています。

Jezus、本プログラミングのためだけ指数の再...もって新作ゲーム更新おつでも事前oracle12(再起動機能は、何が間違っているsimpel:

drop sequence blah;
create sequence blah 

?

1)仮に自分の好きな名前を付けて配列下図のよう:

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

2)現在のフェッチの値のシーケンスです。でも私は取得時として以下に示します。

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

3)を実行した後、上記の四つのコマンドの値のシーケンス4.今私はリセットの値のシーケンス1ました。には、次の方法で行ってください。すべての手順と同じ順序は以下の通りです。

  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

を変えるのは、シーケンスの増加価値incrementingで、その後の変更では痛みのない方、プラスの付加給付なの再構築の助成としていただ落とし/に再現シーケンスです。

私が作成したブロックをリセット全ての配列は:

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;

こちらはより強固な手続きを変えるのは、次の値によって返された配列、全体の多くです。

  • まずれを防ぐSQLインジェクション攻撃てなしの文字列で渡されているものを直接作成の動的SQLステートメント,
  • 第二に防いでくれるので、次のシーケンス値から設定されているの範囲外のmin又は最配列の値です。の next_value ます!= min_value との間に min_valuemax_value.
  • 第三ので、現状の提案) increment_by 設定などすべての配列の設定を考慮す。
  • 第四にすべてのパラメータ以外のオプションは、特に記載がある場合を除き、現在のシーケンス設定がデフォルトするない場合はオプションパラメータは指定しない実行されます。
  • 最後に使ってみれば改変、配列が存在しない(または有しないものがあり、現在のユーザ)では、 ORA-01403: no data found エラーになります。

こちらのコード:

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;

私のプロジェクトでは、一度この人の手の記録を使用せずに配列しているリセットシーケンス値を手動で、書いた以下の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;

ご注意ください、上記のコードする場合、シーケンスが遅れています。

利用できるサイクルのオプションを以下に示す。

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

この場合、配列がMAXVALUE(100)、リサイクル、MINVALUE(0)です。

の場合には減配列の配列がリサイクルのMAXVALUE.

こちらはどうすべて自動的に配列の実際のデータ

  1. 作成手順を実施次の値として記載のこのスレッド:

    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. を別の手続きはどうすべての配列と実際のコンテンツ:

    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;
    

注記:

  1. 手順抽出物の名前からトリガーコードに依存しないネーミング規約
  2. 確認コード生成される前に実行、スイッチのコメント先

この代替とは、ユーザかを知る必要がある値は、システムを取得、利用の変数を更新してしまいました。

--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;
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top