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.

È stato utile?

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à.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top