2010-01-13 2 views
5

Sto provando ad inserire una singola riga che può o non può già esistere. Mi piacerebbe evitare di selezionarlo prima e/o di ottenere un -803 se esiste. Ho fatto qualche ricerca e ho provato sia l'ignora che l'istruzione di fusione, ma continuo a ricevere errori di sintassi su entrambi. In ogni caso, non sto provando a copiare i dati da un'altra tabella, quindi l'unione non è propriamente appropriata.
Non c'è un modo in DB2 SQL per creare un inserto a prova di errore e non dover codificare questo? In altre parole, c'è qualche sintassi dell'inserto che garantisce che i dati verranno aggiunti se non esistono o restituiranno lo stato zero anche se lo fa?Cercando di evitare -803 in DB2 insert

risposta

2

In breve, la risposta è no. A lungo, tutto dipende dai vincoli che hai impostato sul tuo tavolo. Se si tenta di eseguire un inserimento su una tabella che ha un vincolo univoco su una colonna e i dati esistono già che si sta tentando di inserire, si verificherà un errore in DB2 (e qualsiasi altro RDBMS).

In questo caso, l'opzione migliore è probabilmente scrivere una stored procedure che verifica se il record esiste già prima di crearlo.

+2

Meglio ancora: non perdere tempo a fare il controllo dell'esistenza, fare in modo che la stored procedure faccia l'inserto, e basta gestire l'errore -803 (SQL0803N). Ancora meglio: basta che l'applicazione controlli il codice di ritorno dall'inserto e gestisca l'errore -803. –

+0

Grazie per la rapida risposta. Speravo che DB2 avesse qualche equivalente al parametro "ignora", ma non così fortunato. Mike –

+0

Ho provato a gestire l'803 e a fare un aggiornamento, ma questo lascia una traccia di stack nel registro anche quando il processo complessivo ha esito positivo, il che fa sì che gli altri facciano domande.Quindi, sto cambiando il codice per fare un controllo di esistenza prima. Grazie per tutti i suggerimenti. –

7

MERGE è appropriato, poiché è possibile fornire in modo dinamico valori nella clausola USING (vedere l'esempio 5 in http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?topic=/com.ibm.db2.udb.admin.doc/doc/r0010873.htm).

Ma MERGE è una funzionalità DB2 V8.2! Probabilmente sei sulla V8.1, vero?

Se si implementa la verifica dell'esistenza in questo modo:

SELECT 
if (found) UPDATE else INSERT 

attenzione dei problemi di concorrenza: due thread simultanei possono sia trovare alcuna colonna e poi entrambi cercare di inserire, anche se c'è una transazione attorno al codice di cui sopra. Per garantire che ciò non accada, è necessario acquisire un blocco di aggiornamento con ripetibile Leggi nell'istruzione SELECT sopra riportata usando WITH RR USE AND KEEP UPDATE LOCKS.

+0

I problemi di concorrenza sono ancora un problema se si esegue un 'INSERT', si cattura' -803' e quindi si esegue 'UPDATE'? –

2

È possibile eseguire l'istruzione di aggiornamento, se restituisce 0 risultati aggiornati, quindi eseguire l'istruzione di inserimento.

2

È possibile eseguire questa operazione utilizzando la tabella sysibm.sysdummy (o la migliore denominata doppia da Oracle o versioni successive di DB2). Questo funzionerà molto bene per il caso in cui si desidera inserire una riga che non esiste ma restituire 0 se esiste. AFAIK, non è possibile aggiornare una riga utilizzando questo metodo, sarà necessario utilizzare l'unione per quello.

Per eseguire questa operazione, è necessaria una chiave primaria o univoca sul tavolo. Si inserisce nella tabella, selezionando tutti i valori da duale nel processo in cui una riga non esiste nella tabella corrispondente all'indice principale o univoco.

insert into table (column1, column2, column3, column4, column5) 
select 'A', 'B', 'C', 'D', 'E' from dual where not exists (select * from table where column1 = 'A'); 

Ho trovato questo molto utile per i casi in cui ho più processi inserendo un tavolo e non posso garantire l'ordine di tali inserti. È possibile rilevare se l'inserimento ha avuto successo o meno con il valore di ritorno, che sarà 1 se ha avuto successo o 0 se non è