2011-09-27 20 views
12

Sto provando a creare una nuova riga in una tabella. Ci sono due vincoli sulla tabella: uno è sul campo chiave (DB_ID), l'altro vincola un valore per essere uno dei vari il campo ENV. Quando faccio un inserto, che non includono il campo chiave come uno dei campi che sto cercando di inserire, ma sto ottenendo questo errore:Violazione del vincolo univoco durante l'inserimento: perché? (Oracle)

unique constraint (N390.PK_DB_ID) violated 

Ecco il codice SQL che causa l'errore:

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', '') 

L'unica cosa che sono riuscito a visualizzare è la possibilità che Oracle stia tentando di assegnare un DB_ID già in uso se le righe sono state inserite manualmente. I dati in questo database sono stati in qualche modo ripristinati/spostati da un database di produzione, ma non ho i dettagli su come è stato fatto.

Qualche idea?

risposta

34

Presumibilmente, dal momento che non sta fornendo un valore per la colonna DB_ID, tale valore è popolato da una a livello di riga prima di trigger di inserimento definito sul tavolo. Questo trigger, presumibilmente, sta selezionando il valore da una sequenza.

Poiché i dati sono stati spostati (presumibilmente di recente) dal database di produzione, la mia scommessa sarebbe che quando i dati sono stati copiati, anche la sequenza non è stata modificata. Direi che la sequenza sta generando valori molto più bassi del più grande DB_ID attualmente nella tabella che porta all'errore.

Si potrebbe confermare questo sospetto, cercando in trigger per determinare quale sequenza viene utilizzato e facendo un

SELECT <<sequence name>>.nextval 
    FROM dual 

e il confronto che a

SELECT MAX(db_id) 
    FROM cmdb_db 

Se, come sospetto, la sequenza sta generando valori già esistenti nel database, è possibile incrementare la sequenza fino a generare valori inutilizzati o modificarla per impostare INCREMENT su qualcosa di molto grande, ottenere il valore successivo una volta e impostare INCREMENT torna a 1.

+9

+1 ipotesi ragionevole – APC

1

Sembra che tu non stia fornendo un valore per il campo chiave primaria DB_ID. Se quella è una chiave primaria, devi fornire un valore univoco per quella colonna. L'unico modo per non fornirlo sarebbe quello di creare un trigger di database che, inserendo, fornirebbe un valore, molto probabilmente derivato da una sequenza.

Se si tratta di un ripristino da un altro database e c'è una sequenza su questa nuova istanza, potrebbe tentare di riutilizzare un valore. Se i vecchi dati avevano chiavi univoche da 1 a 1000 e la sequenza corrente è a 500, genererebbe valori già esistenti. Se esiste una sequenza per questa tabella e sta tentando di usarla, è necessario riconciliare i valori nella tabella con il valore corrente della sequenza.

È possibile utilizzare SEQUENCE_NAME.CURRVAL a vedere il valore corrente della sequenza (se esiste ovviamente)

+0

Le mie informazioni sul database dicono che la chiave dovrebbe essere generata automaticamente quando viene inserita una nuova riga - ecco perché non fornisco valore per DB_ID. Inoltre, questa stessa tecnica funziona su altre tabelle nel database che sono simili - hanno una chiave ID generata automaticamente. – Sean

+0

Sei in grado di interrogare il dizionario dei dati per vedere se i trigger/sequenze necessari esistono nel nuovo ambiente? Forse non tutto è stato portato dal vecchio ambiente. –

1

vostro errore sembra che si sta duplicando una chiave primaria già esistente nel DB. È necessario modificare il codice SQL per implementare la propria chiave primaria utilizzando qualcosa come la parola chiave IDENTITY.

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

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

); 
+1

IDENTITY non è una parola chiave valida in Oracle. –

+0

Questa è una dichiarazione non valida per Oracle –

+1

Lei, signore, è corretto. La mia soluzione funziona in SQL, non in Oracle. Se si desidera duplicare l'identità di SQL in Oracle, si vorrebbe usare Sequenze [collegamento] (http://www.techonthenet.com/oracle/sequences.php) @Justin_Cave ha una buona implementazione nella sua risposta. –

Problemi correlati