我有一个简单的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
我想过使用一个触发器,它会在调用INSERT时自动执行UPDATE语句,但前提是主键是重复的。这样做有什么问题吗?我需要一些关于触发器的帮助,因为我在尝试理解它们并完成自己的工作时遇到了一些困难。
答案 0 :(得分:10)
MERGE是标准SQL中的'执行INSERT或UPDATE'语句,因此也可能在Oracle SQL中。
是的,你需要一个'table'来合并,但你几乎可以肯定地创建那个表:
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 :(得分:1)
这样做的典型方法是
您无法在同一个表上执行其他操作的表上编写触发器。这导致了Oracle错误(变异表)。
答案 2 :(得分:0)
我是一个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表“加入”自己。如果使用“if exists”示例没有性能影响,我会将其用于可读性。