2011-09-27 19 views
12

Estoy intentando crear una nueva fila en una tabla. Hay dos restricciones en la tabla: una está en el campo clave (DB_ID), la otra restringe un valor para ser uno de varios, el campo ENV. Cuando hago una inserción, no incluyo el campo clave como uno de los campos que estoy tratando de insertar, sin embargo, yo estoy recibiendo este error:Violación de restricción única durante la inserción: ¿por qué? (Oracle)

unique constraint (N390.PK_DB_ID) violated 

Aquí está el SQL que provoca el error:

insert into cmdb_db 
    (narrative_name, db_name, db_type, schema, node, env, server_id, state, path) 
values 
    ('Test Database', 'DB', 'TYPE', 'SCH', '', 'SB01', 381, 'TEST', '') 

Lo único que he podido encontrar es la posibilidad de que Oracle intente asignar un DB_ID ya en uso si las filas se insertan manualmente. Los datos en esta base de datos fueron de alguna manera restaurados/movidos de una base de datos de producción, pero no tengo los detalles sobre cómo se hizo eso.

¿Alguna idea?

Respuesta

34

Presumiblemente, ya que no está proporcionando un valor para la columna de DB_ID, ese valor se está poblada por un nivel de fila antes de desencadenador de inserción definida en la tabla. Ese disparador, presumiblemente, es seleccionar el valor de una secuencia.

Dado que los datos se movieron (presumiblemente recientemente) de la base de datos de producción, mi apuesta sería que, cuando se copiaron los datos, la secuencia no se modificó también. Supongo que la secuencia está generando valores que son mucho más bajos que el mayor DB_ID que se encuentra actualmente en la tabla que conduce al error.

Se podría confirmar esta sospecha mirando el gatillo para determinar qué secuencia se está utilizando y haciendo un

SELECT <<sequence name>>.nextval 
    FROM dual 

y la comparación de que a

SELECT MAX(db_id) 
    FROM cmdb_db 

Si, como sospecho, la secuencia está generando valores que ya existen en la base de datos, puede incrementar la secuencia hasta que esté generando valores no utilizados o puede modificarlo para establecer INCREMENT en algo muy grande, obtener el nextval una vez y establecer INCREMENT de vuelta a 1.

+9

+1 Adivinación razonable – APC

1

Parece que no proporciona un valor para el campo de clave principal DB_ID. Si esa es una clave principal, debe proporcionar un valor único para esa columna. La única forma de no proporcionarlo sería crear un desencadenador de base de datos que, al insertar, proporcionaría un valor, muy probablemente derivado de una secuencia.

Si se trata de una restauración desde otra base de datos y hay una secuencia en esta nueva instancia, podría estar intentando reutilizar un valor. Si los datos antiguos tenían claves únicas de 1 a 1000 y su secuencia actual está en 500, generaría valores que ya existen. Si existe una secuencia para esta tabla y está tratando de usarla, necesitaría reconciliar los valores en su tabla con el valor actual de la secuencia.

Puede utilizar SEQUENCE_NAME.CURRVAL para ver el valor actual de la secuencia (si es que existe, por supuesto) se ve

+0

Mi información en la base de datos dice que la clave debe generarse automáticamente cuando se inserta una nueva fila, es por eso que no proporciono valor para DB_ID. Además, esta misma técnica funciona en otras tablas de la base de datos que son similares: tienen una clave de ID generada automáticamente. – Sean

+0

¿Puede consultar el diccionario de datos para ver si existen los desencadenadores/secuencias necesarios en el nuevo entorno? Tal vez no todo salió del viejo entorno. –

1

Su error como está duplicando una clave principal que ya existe en su base de datos. Debe modificar su código sql para implementar su propia clave principal usando algo como la palabra clave IDENTITY.

CREATE TABLE [DB] (
    [DBId] bigint NOT NULL IDENTITY, 
    ... 

    CONSTRAINT [DB_PK] PRIMARY KEY ([DB] ASC), 

); 
+1

IDENTIDAD no es una palabra clave válida en Oracle. –

+0

Esa es una declaración inválida para Oracle –

+1

Usted, señor, está en lo correcto. Mi solución funciona en SQL, no en Oracle. Si desea duplicar la identidad de SQL en Oracle, le recomendamos utilizar Sequences [link] (http://www.techonthenet.com/oracle/sequences.php) @Justin_Cave tiene una buena implementación en su respuesta. –

Cuestiones relacionadas