¿Cómo recuperar el valor actual de una secuencia de oráculo sin incrementarlo?

156

¿Existe una instrucción SQL para recuperar el valor de una secuencia que no la incrementa?

Gracias.

EDICIÓN Y CONCLUSIÓN

Como dijo Justin Cave, no es útil tratar de "guardar" el número de secuencia

select a_seq.nextval from dual;

es lo suficientemente bueno como para verificar un valor de secuencia.

Todavía mantengo a Ollie como la buena porque respondió la pregunta inicial. pero pregúntese sobre la necesidad de no modificar la secuencia si alguna vez quiere hacerlo.

frno
fuente
55
¿Por qué? ¿Cuál es el problema que estás tratando de resolver? Si está utilizando secuencias correctamente, nunca debería importarle qué valores de secuencia se han asignado a otras sesiones o qué valores podrían asignarse a sesiones posteriores.
Justin Cave
3
Es una verificación después de la migración de datos para asegurarse de que la secuencia se haya actualizado correctamente de acuerdo con los datos migrados
desde el
3
Entonces, ¿cuál es el inconveniente de simplemente obtener nextvalla secuencia de la prueba? No estás asumiendo que las secuencias estarán libres de huecos, ¿verdad? Por lo tanto, "perder" un valor de secuencia no debería ser un problema.
Justin Cave
Supongo que tienes razón, no quería cambiar el estado de la base de datos para esa verificación, pero para ser honesto, no sé por qué. gracias por tu perspicacia Sin embargo, aprendí tus cosas sobre la secuencia, ¡gracias a todos!
vie
Suponiendo que pueda obtener de manera confiable el valor de una secuencia, ¿cuál es su oráculo contra el cual está verificando que la secuencia se haya actualizado correctamente?
Shannon despido

Respuestas:

173
SELECT last_number
  FROM all_sequences
 WHERE sequence_owner = '<sequence owner>'
   AND sequence_name = '<sequence_name>';

Puede obtener una variedad de metadatos de secuencia de user_sequences, all_sequencesy dba_sequences.

Estas vistas funcionan a través de sesiones.

EDITAR:

Si la secuencia está en su esquema predeterminado, entonces:

SELECT last_number
  FROM user_sequences
 WHERE sequence_name = '<sequence_name>';

Si quieres todos los metadatos, entonces:

SELECT *
  FROM user_sequences
 WHERE sequence_name = '<sequence_name>';

Espero eso ayude...

EDIT2:

Una forma larga y sin aliento de hacerlo de manera más confiable si el tamaño de su caché no es 1 sería:

SELECT increment_by I
  FROM user_sequences
 WHERE sequence_name = 'SEQ';

      I
-------
      1

SELECT seq.nextval S
  FROM dual;

      S
-------
   1234

-- Set the sequence to decrement by 
-- the same as its original increment
ALTER SEQUENCE seq 
INCREMENT BY -1;

Sequence altered.

SELECT seq.nextval S
  FROM dual;

      S
-------
   1233

-- Reset the sequence to its original increment
ALTER SEQUENCE seq 
INCREMENT BY 1;

Sequence altered.

Solo tenga en cuenta que si otros usan la secuencia durante este tiempo, ellos (o usted) pueden obtener

ORA-08004: sequence SEQ.NEXTVAL goes below the sequences MINVALUE and cannot be instantiated

Además, es posible que desee establecer la memoria caché NOCACHEantes del restablecimiento y luego volver a su valor original para asegurarse de que no haya almacenado en la memoria caché muchos valores.

Ollie
fuente
Lo probé pero no tengo acceso a una tabla 'all_sequences'. ¿Es un objeto especial que solo se ve con credenciales de administrador?
vie
1
ALL_SEQUENCESEs una vista. Si no tiene acceso a él, intente seleccionar USER_SEQUENCESsi la secuencia está en su esquema predeterminado. (No necesitará la sequence_owner = '<sequence_owner>'cláusula para USER_SEQUENCES).
Ollie
15
El LAST_NUMBERen ALL_SEQUENCESno será el último número que una sesión se da realmente y no será el número que se devuelve desde una llamada a sequence_name.nextvalen general. Suponiendo que haya configurado la secuencia en CACHEmás de 1 (el valor predeterminado es 20), LAST_NUMBERserá el último número que está en la memoria caché. No hay garantía de que este número se otorgue realmente a ninguna sesión.
Justin Cave
2
ALTER SEQUENCE seq INCREMENT BY -1;va a ser un problema a menos que se pueda garantizar que ninguna otra sesión llame seq.nextval. De lo contrario, la secuencia entregará valores duplicados, que generalmente no es lo que uno quiere.
Shannon Cesantía
1
El OP dijo "Es una verificación después de la migración de datos", por lo que no es difícil suponer que la base de datos no es de uso general, pero podría ser un problema si este no fuera el caso.
Ollie
122

select MY_SEQ_NAME.currval from DUAL;

Tenga en cuenta que solo funciona si se ejecutó select MY_SEQ_NAME.nextval from DUAL;en las sesiones actuales.

RonK
fuente
1
Muchas gracias por tu respuesta. Tengo que usar esto dentro de Boomi y estaba buscando una solución de arriba a abajo
aprendiendo ...
0

Mi respuesta original fue objetivamente incorrecta y me alegro de que se haya eliminado. El siguiente código funcionará en las siguientes condiciones a) usted sabe que nadie más modificó la secuencia b) la secuencia fue modificada por su sesión. En mi caso, encontré un problema similar en el que estaba llamando a un procedimiento que modificó un valor y estoy seguro de que la suposición es cierta.

SELECT mysequence.CURRVAL INTO v_myvariable FROM DUAL;

Lamentablemente, si no modificó la secuencia en su sesión, creo que otros tienen razón al afirmar que NEXTVAL es el único camino a seguir.

georgejo
fuente
0

Esto no es una respuesta, realmente y lo habría ingresado como un comentario si la pregunta no hubiera sido bloqueada. Esto responde a la pregunta:

¿Por qué lo quieres?

Suponga que tiene una tabla con la secuencia como clave principal y la secuencia es generada por un activador de inserción. Si desea tener la secuencia disponible para actualizaciones posteriores del registro, debe tener una forma de extraer ese valor.

Para asegurarse de obtener el correcto, es posible que desee ajustar la consulta INSERT y RonK en una transacción.

La consulta de RonK:

select MY_SEQ_NAME.currval from DUAL;

En el escenario anterior, la advertencia de RonK no se aplica ya que la inserción y la actualización sucederían en la misma sesión.

Ainsworth
fuente
0

También intenté usar CURRVAL, en mi caso para averiguar si algún proceso insertó nuevas filas en alguna tabla con esa secuencia como Clave primaria. Mi suposición fue que CURRVAL sería el método más rápido. Pero a) CurrVal no funciona, solo obtendrá el valor anterior porque está en otra sesión de Oracle, hasta que haga un NEXTVAL en su propia sesión. Y b) a select max(PK) from TheTabletambién es muy rápido, probablemente porque una PK siempre está indexada. O select count(*) from TheTable. Todavía estoy experimentando, pero ambos SELECT parecen rápidos.

No me importa una brecha en una secuencia, pero en mi caso estaba pensando en sondear mucho, y odiaría la idea de brechas muy grandes. Especialmente si un SELECT simple sería igual de rápido.

Conclusión:

  • CURRVAL es bastante inútil, ya que no detecta NEXTVAL de otra sesión, solo devuelve lo que ya sabía de su anterior NEXTVAL
  • SELECT MAX (...) FROM ... es una buena solución, simple y rápida, suponiendo que su secuencia esté vinculada a esa tabla
Roland
fuente