2009-04-28 18 views

Respuesta

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 

Al crear una secuencia con un número, hay que recordar que la primera vez que se selecciona en contra de la secuencia, Oracle volverá el valor inicial que le asignó.

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 lo que es 'sin espacios en blanco', te aconsejamos que

1 no hacerlo, y # 2 no utilizar una secuencia para ello.

+0

+1 para la captura en el punto inicial de la secuencia. Además, tengo que suponer que si está configurando el parámetro CACHE a algo que no sea 1, ¡no le preocupan las brechas! – DCookie

+2

iba a mencionar que el caché era bajo, pero pensé que estaba fuera del alcance de la pregunta. Ahora, si el usuario está esperando números sin intervalo, por medio de una secuencia, tienen otras cosas por venir. Rollback no 'decrementa' una secuencia;) –

+1

Hmm, ese consejo en negrita en la parte inferior requiere un enfoque alternativo y/o una explicación ... –

15

No puede usar una subselección dentro de una declaración CREATE SEQUENCE. Deberá seleccionar el valor de antemano.

+1

+1 retén agradable .. – raksja

+0

verdad - pero ¿Alguien tiene una alternativa simple para automatizar esto? –

33

Si puede utilizar PL/SQL, intente (EDIT: Incorpora sugerencia xlnt de Neil para comenzar 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 considerar: Al establecer el parámetro CACHE a 20, se corre el riesgo de perder hasta 19 valores en su secuencia si la base de datos deja de funcionar. Los valores de CACHEd se pierden en los reinicios de la base de datos. A menos que esté siguiendo la secuencia muy a menudo, o si no le interesan demasiado las brechas, lo configuré en 1.

Una última afirmación: los valores que ha especificado para CACHE y INCREMENT BY son los predeterminados . Puedes dejarlos y obtener el mismo resultado.

+0

Obtengo 'ORA-00905: palabra clave que falta' para la primera declaración ... – ADTC

12

Teniendo en medio, el valor MAX solo será el máximo de valores comprometidos. Puede devolver 1234, y es posible que deba considerar que alguien ya ha insertado 1235 pero no confirmado.

+1

+1 para señalar la condición de carrera. Todo esto es realmente seguro si se asegura de que nadie escriba al DB al mismo tiempo. – sleske

25

Aquí tengo mi ejemplo, que funciona muy 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; 
+0

¡Esto funciona genial! @ united-exression así es como puedes automatizarlo. Debe ser la respuesta aceptada. No sé por qué una no respuesta es la respuesta aceptada ... – ADTC

3

Sobre la base de 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; 
+1

Nice. Solo agregaría la siguiente línea entre la selección y la ejecución en caso de que aún no haya filas: 'si lastSeq es null luego lastSeq: = 0; terminar si; ' –

+0

¡Gracias, buen consejo! – dmonti

+0

Sí, buen ejemplo, pero mi secuencia de comandos recrea la secuencia, porque he soltado el guión. –

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; 
+2

Evitar solo el código de respuesta. Por favor elabora. – aloisdg

Cuestiones relacionadas