0

我有四个表,分别命名为 Task、ProjectTeamMemeber、Hierarchy 和 Assignment。
每个任务通过层次结构与一个项目相关,每个项目都有团队成员,可以通过 ProjectTeamMember 看到这些成员。

select 
    TH.TaskId As TaskID, P.PersonId As PersonID    
from 
    Task T
    Inner join Hierarchy TH on T.Id = TH.TaskId 
    Inner join ProjectTeamMemeber PTM on TH.ProjectId = P.TaskId
where 
    T.name = 'work' 

上述查询返回分配给任务名称为“工作”的某个项目的所有人员

TaskId      PersonId
1347        50  
1350        50  
3377        50  
3403        598  
3411        1450  
3411        1454  
3411        1472  

我还有另一个表Assigment,从中我可以看到分配给特定任务的人员的ID。

select 
    T.Id, A.PersonId
from
    Task T
    inner join Assignment A ON T.Id = A.TaskId
where 
    T.name = 'work'

上述查询返回分配给名为“工作”的任务的所有人员。

TaskId      PersonId
1347        50
1350        50
3411        1472

现在,我必须在这里实现的是将所有人分配给名称为“工作”的任务,该任务分配给任务名称为“工作”的项目。简单地说,我必须编写一些 sql 语句,之后我上面的第二个查询写出与我的第一个查询相同的结果。

到目前为止,我已经尝试用光标来做到这一点,但它不起作用。下面是代码

DECLARE @TaskId int
DECLARE @PersonId int
DECLARE @Id int

DECLARE db_cursor CURSOR FOR
select 
    TH.TaskId As TaskID, P.PersonId As PersonID    
from 
    Task T
    Inner join Hierarchy TH on T.Id = TH.TaskId 
    Inner join ProjectTeamMemeber PTM on TH.ProjectId = P.TaskId
where 
    T.name = 'work' 

OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @TaskId, @PersonId
BEGIN
    If not exists ( select 1 from Assignment where TaskId=@TaskId and PersonId=@PersonId)
    BEGIN
        EXEC GetUniqueIdentifier @Id OUTPUT;
        Insert INTO Assignment (Id, TaskId, PersonId) values (@Id, @TaskId, @PersonId)
    END
END 
CLOSE db_cursor  
DEALLOCATE db_cursor 

注意:我必须使用语句 EXEC GetUniqueIdentifier @Id OUTPUT; 来生成 Id。我知道可能有不同且更可靠的方法来生成 Id,但由于某些限制,我无法更改 Id 的生成方式。)

编辑 :

根据LAMAK 的回答,我运行了这个

DECLARE @ids int
INSERT INTO Assignment (Id, TaskId, PersonId) 
EXEC GetUniqueIdentifier @ids OUTPUT;
SELECT 
    @ids,
    TH.TaskId As TaskID, 
    P.PersonId As PersonID,
FROM 
    Task T
    INNER JOIN Hierarchy TH on T.Id = TH.TaskId 
    INNER JOIN ProjectTeamMember P on TH.ProjectId = P.TaskId
WHERE 
    T.name = 'Customer work' 
    AND NOT EXISTS( SELECT 1 FROM Assignment 
                WHERE TaskID = TH.TaskId
                AND PersonId = P.PersonId)
4

1 回答 1

2

您不需要CURSOR为此,您可以使用基于集合的解决方案:

INSERT INTO Assignment (Id, TaskId, PersonId)
SELECT 
    NEWID(),
    TH.TaskId As TaskID, 
    P.PersonId As PersonID    
FROM 
    Task T
    INNER JOIN Hierarchy TH on T.Id = TH.TaskId 
    INNER JOIN ProjectTeamMemeber PTM on TH.ProjectId = P.TaskId
WHERE 
    T.name = 'work' 
    AND NOT EXISTS( SELECT 1 FROM Assignment 
                    WHERE TaskID = T.TaskId
                    AND PersonId = P.PersonId)

关于NEWID(),你真的需要检查碰撞吗?,我认为可以安全地假设NEWID()如果它在同一台机器上运行它将是唯一的。即使在不同的服务器上,重复值的概率也非常小。

更新

好的,所以,你不需要 anUNIQUEIDENTIFIER并且你必须使用GetUniqueIdentifiersp (名字也很糟糕,因为UNIQUEIDENTIFIER它是一种数据类型,这会带来混乱)。然后我担心你需要使用CURSOR. 在大多数情况下,您的光标看起来不错,唯一可见的变化是您没有获取光标的下一个值:

DECLARE @TaskId int
DECLARE @PersonId int
DECLARE @Id int

DECLARE db_cursor CURSOR FOR
select 
    TH.TaskId As TaskID, P.PersonId As PersonID    
from 
    Task T
    Inner join Hierarchy TH on T.Id = TH.TaskId 
    Inner join ProjectTeamMemeber PTM on TH.ProjectId = P.TaskId
where 
    T.name = 'work' 

OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @TaskId, @PersonId
BEGIN
    If not exists (select 1 from Assignment where TaskId=@TaskId and PersonId=@PersonId)
    BEGIN
        EXEC GetUniqueIdentifier @Id OUTPUT;
        Insert INTO Assignment (Id, TaskId, PersonId) 
        values (@Id, @TaskId, @PersonId)
    END
    FETCH NEXT FROM db_cursor INTO @TaskId, @PersonId
END 
CLOSE db_cursor  
DEALLOCATE db_cursor 
于 2013-06-04T16:57:19.523 回答