2009-09-15 8 views

Respuesta

14

Si el ID es el nombre de la columna de PK y PK_SEQ es el nombre de la secuencia:

  1. encontrar el valor de la más alta PK por SELECT MAX (ID) DE nombreTabla

  2. encontrar el valor de la siguiente PK_SEQ por SELECT FROM DUAL PK_SEQ.NEXTVAL

  3. Si # 2> # 1 entonces nada es necesario que haya hecho, suponiendo que el tratamiento de estas como valores verdaderos claves sustitutas
  4. De lo contrario, alteran la secuencia a salto a la ID max por ALTER SEQUENCE INCREMENTO PK_SEQ por [1 valor # - # 2 valor]
  5. Bump la secuencia por SELECT PK_SEQ.NEXTVAL FROM DUAL

  6. Cambiar el valor de incremento secuencia a 1 por ALTER SEQUENCE PK_SEQ incrementan en 1

Todo esto asume que usted no tiene nuevas inserciones en la tabla, mientras que usted está haciendo esto ...

+0

Estoy luchando con la forma de hacer el paso 3, he probado varias sintaxis diferentes pero no puedo hacer que funcione – AJM

+2

La intención del paso 3 es simplemente comparar el valor de PK más grande con el siguiente valor de secuencia. Entonces, por ejemplo, si el SELECT del paso 1 resultó en un resultado de 100, y el SELECT del paso 2 resultó en un resultado de 90, lo que significa que tiene 11 secuencias de "jump". Cuando modifique la secuencia en el paso 4, SELECCIONAR en el paso 5 moverá los valores de la secuencia 10 a 100. Después de reiniciar el incremento en el paso 6, el siguiente "SELECCIONAR PK_SEQ.NEXTVAL DE DUAL" le dará 101. – dpbradley

+0

In paso 4 No puedo obtener la sintaxis para hacer una resta en la cláusula Incrementar por. Probé [a-b] a-b y selecr a-b desde dual, pero no con éxito. – AJM

11

En resumen, el juego es:

-- 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. 

Usted puede obtener el valor de secuencia máximo se utiliza dentro de su mesa, hacer los cálculos, y actualizar la secuencia en consecuencia.

+0

¿Cómo es esto de ayuda? Si el ID máximo en la tabla es 624. ¿Cómo va a configurar lo de arriba correctamente? – ginalster

0

En algunos casos, puede que le resulte más fácil simplemente obtener el valor máximo actual y luego

drop sequence x; 
create sequence x start with {current max + 1}; 

La aplicación se romperá después de hacer la caída. Pero eso evitará que nadie inserte filas durante ese período, y la creación de una secuencia es rápida. Asegúrese de recrear cualquier concesión en la secuencia, ya que se eliminarán cuando la secuencia sea. Y es posible que desee recompilar manualmente cualquier plsql que dependa de la secuencia.

+2

@Jim - Evitaría dejar caer cualquier objeto db si hay una alternativa. Dejar caer la secuencia no impedirá necesariamente las inserciones en la tabla que no hacen referencia a la secuencia. Como usted señala, también tiene el trabajo adicional de capturar las concesiones y recompilar objetos dependientes. – dpbradley

8
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; 
+1

Esto lo pone 1 arriba donde debería estar ... – Worthy7

+0

Creo que es por 'seleccionar YOURSEQUENCE.NEXTVAL en sequenceValue from dual; 'en la línea 7, puede verificar una alternativa en mi respuesta en [https://stackoverflow.com/a/45542069/1737973](https://stackoverflow.com/a/45542069/1737973), que obtiene 'all_sequences.last_number WHERE sequence_name = 'YOURSEQUENCE'' en lugar de' YOURSEQUENCE.NEXTVAL', probablemente consiguiendo el valor deseado _ dado que el almacenamiento en caché de valor de secuencia está deshabilitado_. – uprego

4

hice este script como no he encontrado un script de línea fija que dinámicamente todos mis secuencias a la corriente más alta de identificación. Probado en Oracle 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; 
0

la adición de hasta https://stackoverflow.com/a/15929548/1737973, pero sin recurrir a SEQUENCENAME.NEXTVAL por lo tanto no resulta en una posición sobre él debe ser:

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; 

exención de responsabilidad: si la secuencia está utilizando el almacenamiento en caché (all_sequences.cache_size conjunto a más grande que 0) probablemente desee tenerlo en cuenta en el Calcule la diferencia paso.

Oracle documentation for all sequences....

+0

Oh, bien, siento que esto sea para Oracle 11, no sé si puede funcionar en Oracle 9 sin cambios. – uprego

Cuestiones relacionadas