UPDATE INSERT duplicare chiave primaria in Oracle?
Domanda
Ho una semplice query di inserimento in cui ho bisogno di usare UPDATE invece quando la chiave primaria è un duplicato. In MySQL questo sembra più facile, in Oracle sembra che ho bisogno di utilizzare MERGE.
Tutti gli esempi che ho trovato di MERGE aveva una sorta di "fonte" e le tabelle "target", nel mio caso, l'origine e la destinazione è la stessa tabella. Non ero in grado di dare un senso degli esempi per creare la mia propria query.
Merge è l'unico modo, o forse c'è una soluzione migliore?
INSERT INTO movie_ratings
VALUES (1, 3, 5)
E 'fondamentalmente questo e la chiave primaria è i primi 2 valori, quindi un aggiornamento sarebbe come questo:
UPDATE movie_ratings
SET rating = 8
WHERE mid = 1 AND aid = 3
Ho pensato di utilizzare un trigger che esegue automaticamente l'istruzione UPDATE quando l'inserto è stato chiamato, ma solo se la chiave primaria è un duplicato. C'è qualche problema facendo in questo modo? Ho bisogno di aiuto con i trigger anche se, come sto avendo qualche difficoltà cercando di capire loro e fare la mia.
Soluzione
Merge è il 'fare INSERT o UPDATE come appropriato' dichiarazione standard SQL, e, probabilmente, quindi in Oracle SQL troppo.
Sì, avete bisogno di un 'tavolo' per unione da, ma si può quasi certamente creare quel tavolo al volo:
MERGE INTO Movie_Ratings M
USING (SELECT 1 AS mid, 3 AS aid, 8 AS rating FROM dual) N
ON (M.mid = N.mid AND M.aid = N.aid)
WHEN MATCHED THEN UPDATE SET M.rating = N.rating
WHEN NOT MATCHED THEN INSERT( mid, aid, rating)
VALUES(N.mid, N.aid, N.rating);
(sintassi non verificato).
Altri suggerimenti
Un modo tipico per farlo è
- eseguire l'inserto e prendere un DUP_VAL_ON_INDEX e quindi eseguire un UPDATE invece
- eseguire l'aggiornamento prima e se SQL% Righe = 0 eseguono un INSERT
Non è possibile scrivere un trigger su una tabella che fa un'altra operazione nella stessa tabella. Che sta causando un errore di Oracle (mutando tabelle).
Sono un ragazzo T-SQL, ma un trigger in questo caso non è una buona soluzione. La maggior parte dei trigger non sono buone soluzioni. In T-SQL, vorrei semplicemente eseguire un IF EXISTS (SELECT * FROM WHERE dbo.Table ...), ma in Oracle, è necessario selezionare il numero di ...
DECLARE
cnt NUMBER;
BEGIN
SELECT COUNT(*)
INTO cnt
FROM mytable
WHERE id = 12345;
IF( cnt = 0 )
THEN
...
ELSE
...
END IF;
END;
Sembrerebbe che si fondono è quello che serve in questo caso:
MERGE INTO movie_ratings mr
USING (
SELECT rating, mid, aid
WHERE mid = 1 AND aid = 3) mri
ON (mr.movie_ratings_id = mri.movie_ratings_id)
WHEN MATCHED THEN
UPDATE SET mr.rating = 8 WHERE mr.mid = 1 AND mr.aid = 3
WHEN NOT MATCHED THEN
INSERT (mr.rating, mr.mid, mr.aid)
VALUES (1, 3, 8)
Come ho detto, io sono un ragazzo T-SQL, ma l'idea di base è quella di "join" il tavolo movie_rating contro se stessa. Se non c'è alcun calo di prestazioni utilizzando l'esempio "se esiste", lo userei per migliorare la leggibilità.