Tratando de crear una secuencia de Oracle que se inicia con el valor máximo de una tabla específica. ¿Por qué esto no funciona?

CREATE SEQUENCE transaction_sequence
  MINVALUE 0
  START WITH (SELECT MAX(trans_seq_no)
     FROM TRANSACTION_LOG) 
  INCREMENT BY 1
  CACHE 20;
InformationsquelleAutor Amar Patel | 2009-04-28

7 Comentarios

  1. 19

    es posible que desee comenzar con max(trans_seq_no) + 1.

    reloj:

    SQL> create table my_numbers(my_number number not null primary key);
    
    Table created.
    
    SQL> insert into my_numbers(select rownum from user_objects);
    
    260 rows created.
    
    SQL> select max(my_number) from my_numbers;
    
    MAX(MY_NUMBER)
    --------------
               260
    
    SQL> create sequence my_number_sn start with 260;
    
    Sequence created.
    
    SQL> insert into my_numbers(my_number) values (my_number_sn.NEXTVAL);
    insert into my_numbers(my_number) values (my_number_sn.NEXTVAL)
    *
    ERROR at line 1:
    ORA-00001: unique constraint (NEIL.SYS_C00102439) violated

    Cuando se crea una secuencia con un número, usted tiene que recordar que la primera vez que seleccione en contra de la secuencia, Oracle devolverá el valor inicial que se ha asignado.

    SQL> drop sequence my_number_sn;
    
    Sequence dropped.
    
    SQL> create sequence my_number_sn start with 261;
    
    Sequence created.
    
    SQL>  insert into my_numbers(my_number) values (my_number_sn.NEXTVAL);
    
    1 row created.

    Si usted está tratando de hacer el «sin espacio» cosa, les aconsejo que

    1 no hacerlo, y #2 no utilizar una secuencia de él.

    • +1 para la captura en el punto de partida de la secuencia. También, tengo que suponer que si él la configuración de la CACHÉ de parámetro a un valor distinto de 1, que no está en cuestión sobre los vacíos!
    • yo iba a hablar de la caché de ser baja, pero pensaba que estaba fuera del alcance de la pregunta. Ahora, si el usuario está esperando sin pausas números, por medio de una secuencia, tenemos otra de las cosas que vienen. La reversión no ‘disminuir’ una secuencia 😉
    • Hmm, ese consejo en negrita en la parte inferior de llamadas para un enfoque alternativo y/o una explicación…
    • Mientras que esto es información útil (señalar un error en el autor de la pregunta de enfoque), esto no es una respuesta a la pregunta. Siento decir esto, pero esto no debería ser aceptado solución. La respuesta real que trabajó para mí, Ivan.
    • Este es un comentario válido para la pregunta, pero definitivamente no es una respuesta.
  2. 36

    Si se puede usar PL/SQL, probar (EDIT: Incorpora Neil el excelente sugerencia para empezar en el siguiente valor más alto):

    SELECT 'CREATE SEQUENCE transaction_sequence MINVALUE 0 START WITH '||MAX(trans_seq_no)+1||' INCREMENT BY 1 CACHE 20'
      INTO v_sql
      FROM transaction_log;
    
    EXECUTE IMMEDIATE v_sql;

    Otro punto a tener en cuenta: Por la configuración de los parámetros de CACHÉ a 20, se corre el riesgo de perder hasta el 19 de valores en su secuencia, si la base de datos va hacia abajo. Valores almacenados en caché se pierden en la base de datos se reinicia. A menos que usted está golpeando la secuencia muy a menudo, o, no se preocupan mucho acerca de los vacíos, me gustaría establece a 1.

    Una final nit: los valores especificados para la CACHÉ y el INCREMENTO POR los que están por defecto. Usted puede salir de ellos y obtener el mismo resultado.

    • Puedo obtener ORA-00905: missing keyword para la primera instrucción…
  3. 29

    Aquí tengo mi ejemplo que funciona bien:

    declare
     ex number;
    begin
      select MAX(MAX_FK_ID)  + 1 into ex from TABLE;
      If ex > 0 then
        begin
                execute immediate 'DROP SEQUENCE SQ_NAME';
          exception when others then
            null;
        end;
        execute immediate 'CREATE SEQUENCE SQ_NAME INCREMENT BY 1 START WITH ' || ex || ' NOCYCLE CACHE 20 NOORDER';
      end if;
    end;
    • Esto funciona muy bien! @unidas-exression esta es la forma en que se puede automatizar. Debe ser aceptado respuesta. No sé por qué una no-respuesta es el aceptado la respuesta…
  4. 16

    Usted no puede utilizar una subselección dentro de un CREATE SEQUENCE declaración. Usted tendrá que seleccionar el valor de antemano.

    • +1 buena captura..
    • Cierto, Pero ¿alguien tiene una alternativa sencilla para la automatización de este ?
  5. 12

    Oso en medio, el valor máximo sólo será el máximo de comprometido valores. Es posible que devuelva 1234, y usted puede necesitar considerar que alguien ya ha insertado 1235 pero no comprometidos.

    • +1 para señalar la condición de carrera. Todo esto es realmente sólo es seguro si usted asegúrese de que nadie está escrito a la base de datos al mismo tiempo.
  6. 4

    Basado en Ivan Laharnar con menos código y más simple:

    declare
        lastSeq number;
    begin
        SELECT MAX(ID) + 1 INTO lastSeq FROM <TABLE_NAME>;
        if lastSeq IS NULL then lastSeq := 1; end if;
        execute immediate 'CREATE SEQUENCE <SEQUENCE_NAME> INCREMENT BY 1 START WITH ' || lastSeq || ' MAXVALUE 999999999 MINVALUE 1 NOCACHE';
    end;
    • De niza. Sólo quiero agregar la siguiente línea entre la selección y la ejecución en caso de que no hay filas aún: if lastSeq is null then lastSeq := 0; end if;
    • Gracias, buen consejo!
    • Sí buen ejemplo, pero en mi script recrea la secuencia, porque tengo caer en la secuencia de comandos.
  7. 0
    DECLARE
        v_max NUMBER;
    BEGIN
        SELECT (NVL (MAX (<COLUMN_NAME>), 0) + 1) INTO v_max FROM <TABLE_NAME>;
        EXECUTE IMMEDIATE 'CREATE SEQUENCE <SEQUENCE_NAME> INCREMENT BY 1 START WITH ' || v_max || ' NOCYCLE CACHE 20 NOORDER';
    END;
    • Evite sólo el código de respuesta. Por favor elaborados.

Dejar respuesta

Please enter your comment!
Please enter your name here