ОБНОВЛЕНИЕ на ВСТАВИТЬ дубликат первичного ключа в Oracle? - PullRequest
1 голос
/ 04 января 2011

У меня есть простой запрос INSERT, где мне нужно вместо этого использовать UPDATE, когда первичный ключ является дубликатом. В MySQL это кажется проще, в Oracle - мне нужно использовать MERGE.

У всех примеров, которые я мог найти для MERGE, были какие-то таблицы «исходная» и «целевая», в моем случае исходная и целевая - это одна и та же таблица. Я не смог разобраться в примерах, чтобы создать собственный запрос.

Является ли MERGE единственным способом или, может быть, есть лучшее решение?

INSERT INTO movie_ratings
VALUES (1, 3, 5)

В основном это так, и первичный ключ - это первые 2 значения, поэтому обновление будет выглядеть так:

UPDATE movie_ratings
SET rating = 8
WHERE mid = 1 AND aid = 3

Я думал об использовании триггера, который будет автоматически выполнять инструкцию UPDATE при вызове INSERT, но только если первичный ключ является дубликатом. Есть ли какие-либо проблемы с этим? Мне нужна помощь с триггерами, так как я испытываю трудности с их пониманием и выполнением своих действий.

Ответы [ 3 ]

10 голосов
/ 04 января 2011

MERGE - это оператор do INSERT или UPDATE соответственно, в стандартном SQL и, возможно, поэтому в Oracle SQL.

Да, вам нужен «стол» для объединения, но вы почти наверняка можете создать эту таблицу на лету:

 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);

(Синтаксис не проверен.)

1 голос
/ 04 января 2011

Типичный способ сделать это -

  • , выполнив INSERT и перехватить DUP_VAL_ON_INDEX, а затем вместо этого выполнить UPDATE
  • сначала выполнив UPDATE, и если SQL% Rows = 0, выполнитьINSERT

Вы не можете написать триггер для таблицы, которая выполняет другую операцию в той же таблице.Это вызывает ошибку Oracle (изменяющиеся таблицы).

0 голосов
/ 04 января 2011

Я парень по T-SQL, но триггер в этом случае не является хорошим решением.Большинство триггеров не являются хорошими решениями.В T-SQL я бы просто выполнял IF EXISTS (SELECT * FROM dbo.Table WHERE ...), но в Oracle вы должны выбрать количество ...

DECLARE 
  cnt NUMBER;
BEGIN
  SELECT COUNT(*)
   INTO cnt
    FROM mytable
  WHERE id = 12345;

  IF( cnt = 0 )
  THEN
    ...
  ELSE
    ...
  END IF;
END;

Может показаться, чтоMERGE - это то, что вам нужно в этом случае:

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) 

Как я уже сказал, я парень по T-SQL, но основная идея здесь состоит в том, чтобы «присоединиться» к таблице movie_rating против себя.Если при использовании примера «если существует» производительность не падает, я бы использовал его для удобства чтения.

...