我需要一个游标来在SQL中完成这项工作吗?

时间:2013-09-18 19:02:41

标签: sql sql-server

我有3个表,MovieMovieRoleActorMovieRole是一个涉及电影和演员的多对多表,但它也定义了演员在桌面上的角色。因为actor可能在电影中有多个角色,MovieRole是一个包含3列的表:

MovieId int
ActorId int
RoleName varchar(100)

我们不是仅对MovieIdActorId设置唯一约束,而是在所有三个字段中都有。因此,不可能有一部电影,其中Eddie Murphy在其中并具有相同的角色。但如果Eddie Murphy扮演不同的角色(“Klump教授”,“The Nutty Professor”中的“Buddy Love”),他可以两次联合同一部电影。

问题是我们在表Actor中有很多重复项。所以可能有一个名为“爱德华墨菲”的参与者和另一个名为“艾迪墨菲”的参与者,他们两个都可以与“克伦普教授”相同的电影联系在一起。而“爱德华墨菲”可能与“诺比特”有关,但与“来到美国”无关,反之亦然“艾迪墨菲”。

我需要创建一个存储过程,将actor和它们的影片角色关联合并在一起。它应该做的是发送两个演员ID,一个是主要演员记录,一个是删除。 slated-for-delete actor中的电影角色关联必须与主要角色相关联。

存储过程只有在slated-for-delete actor与主actor没有任何角色冲突时才有效。因此,如果s-f-d演员在电影B中并且主要演员在电影A中,那么它很好。或者如果s-f-d演员在电影A中但是角色不同,我们都很好。但是如果两个演员都在同一个角色中扮演同一个角色,那么我会遇到这个约束。

如何构建解决该意外事件的查询或存储过程? 我一直在寻找完成这项工作的方法,看起来像使用游标会做到这一点虽然每个人都说尽量避免使用游标。有没有办法在不使用游标的情况下完成我想要的东西?

现在,sproc的基本要点是这样的:

alter procedure RoleMerge @ActorA int, @ActorB int as

update MovieRole set ActorId=@ActorA where ActorId=@ActorB

delete from Actor where Id=@ActorB

2 个答案:

答案 0 :(得分:2)

首先,如果ActorId@ActorB更改为@ActorA,则会删除违反约束的行:

alter procedure RoleMerge @ActorA int, @ActorB int as
begin
    delete MovieRole
    from MovieRole as M
    where
        ActorId = @ActorB and
        exists (
            select *
            from MovieRole as M1
            where
                M1.ActorId = @ActorA and M1.MovieId = M.MovieId and
                M1.RoleName = M.RoleName
        )

    update MovieRole set ActorId = @ActorA where ActorId = @ActorB

    delete from Actor where Id = @ActorB
end

答案 1 :(得分:0)

你不需要光标。只是MovieID的附加条款。像这样的东西:

update MovieRole set ActorId=@ActorA where ActorId=@ActorB
  and MovieID not in (select MovieID from MovieRole where ActorId=@ActorA)

希望这会有所帮助

编辑:

我终于有了这个工作:)。 我注意到它已被回答,但以防万一有人对替代解决方案感兴趣:)。 以下是我提出的建议:

update a set a.ActorId = b.ActorId
from MovieRole a
left join MovieRole b
    on a.MovieId = b.MovieId and a.ActorID = @ActorB and b.ActorID = @ActorA
where a.RoleName <> b.RoleName