Tengo una secuencia de Oracle definida así:
CREATE SEQUENCE "DALLAS"."X_SEQ"
MINVALUE 0
MAXVALUE 999999999999999999999999999
INCREMENT BY 1 START WITH 0 NOCACHE NOORDER NOCYCLE ;
Se utiliza en un procedimiento almacenado para insertar un registro:
PROCEDURE Insert_Record
(p_name IN VARCHAR2,
p_userid IN INTEGER,
cur_out OUT TYPES_PKG.RefCursor)
IS
v_id NUMBER := 0;
BEGIN
-- Get id value from sequence
SELECT x_seq.nextval
INTO v_id
FROM dual;
-- Line below is X_PKG line 40
INSERT INTO X
(the_id,
name,
update_userid)
VALUES
(v_id,
p_name,
p_userid);
-- Return new id
OPEN cur_out FOR
SELECT v_id the_id
FROM dual;
END;
Ocasionalmente, este procedimiento devuelve un error cuando se ejecuta desde el código de la aplicación.
ORA-01400: cannot insert NULL into ("DALLAS"."X"."THE_ID")
ORA-06512: at "DALLAS.X_PKG", line 40
ORA-06512: at line 1
Detalles que pueden o no ser relevantes:
- Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Producción de 64 bits
- El procedimiento se ejecuta a través de Microsoft.Practices.EnterpriseLibrary - Data.Oracle.OracleDatabase.ExecuteReader (comando DbCommand)
- La aplicación no ajusta la llamada en una transacción explícita.
- El inserto falla intermitentemente - menos del 1%
¿En qué circunstancias podría x_seq.nextval
ser nulo?
v_id
solo se hace referencia en la selección de secuencia, la inserción y el cursor final. Nuestro siguiente paso fue agregar el código de depuración. Es posible que tengamos que esperar los resultados, ya que solo ocurre en la producción y con muy poca frecuencia. Hay un disparador que se inserta en una tabla de auditoría. Lo he peinado sin una pistola humeante. El problema también ocurre ocasionalmente en otras tablas sin desencadenantes. Gracias por echar un vistazo.Respuestas:
Estoy bastante seguro de que esto terminará siendo un artefacto de su código, o el controlador .net que está utilizando. He creado una demostración rápida para usted usando SQL puro - PL / SQL y nunca obtengo un valor de secuencia perdido. Por cierto, el cursor de referencia que está utilizando es probablemente innecesario y probablemente afecte el rendimiento y la legibilidad del código: mi demostración incluye un procedimiento insert_record2 que realiza constantemente más del 10% más rápido, en aproximadamente 26 segundos en mi computadora portátil frente a 36 para la versión del cursor de referencia. Al menos también creo que es más fácil de entender. Obviamente, podría ejecutar una versión modificada en su base de datos de prueba completa con el disparador de auditoría.
fuente
:new.the_id
sido tocado. Entiendo que mi pregunta es una posibilidad remota. Es resistente a mi google-fu y tiene a varias personas rascándose la cabeza aquí. Me imaginé que alguien podría reconocer el síntoma (y el tratamiento) dado suficientes globos oculares. Gracias por echar un vistazo.Intenta hacer un caso de prueba. Haga una tabla ficticia e inserte 100,000 registros usando su secuencia de la base de datos. Apuesto a que no tendrás problemas. Luego intente insertar lo mismo desde su aplicación.
¿Podría esto ser causado por otros problemas, como una falta de coincidencia del cliente Oracle?
Otra solución que solucionaría el problema pero no el problema es agregar un activador en la tabla.
Antes de Insertar en la tabla en Dallas.X IF: the_id es nulo ENTONCES SELECCIONE x_seq.nextval INTO: the_id FROM dual; TERMINARA SI;
fuente
Todavía no tengo privilegios para hacer comentarios, así que escribe esto como respuesta: dado que estás utilizando la versión de Oracle> = 11.1, que permite secuencias en expresiones PL / SQL en lugar de en SQL, prueba esto:
En lugar de esto:
O bien, aunque he escuchado dudas / dificultades al usar ".currval", ¿tal vez omita la asignación separada de v_id y solo use este código ?:
Lo siento, no tengo una instancia de 11g a mano ahora para probar esto.
fuente
select into...
en 11 tanto como en 9i y 10g. El único beneficio de 11+ es poder referenciarlo explícitamente como lo has señalado.