将值从一个表复制到另一个表(如果它尚不存在)

时间:2013-06-04 16:48:46

标签: sql sql-server-2008 cursor

我有四个名为Task,ProjectTeamMemeber,Hierarchy和Assignment的表 每个任务都通过Heirarchy与项目相关,每个项目都有团队成员,可以通过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' 

上述查询返回分配给任务名称为“work”

的特定项目的所有人员
TaskId      PersonId
1347        50  
1350        50  
3377        50  
3403        598  
3411        1450  
3411        1454  
3411        1472  

我有另一张表格Assigment,我可以从中看到分配给特定任务的人员的身份。

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

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

到目前为止,我已尝试用cusrsors做到这一点,但它不起作用。以下是

的代码
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)

1 个答案:

答案 0 :(得分: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()在同一台机器上运行时是唯一的。即使在不同的服务器上,重复值的可能性也非常小。

<强>已更新

好的,所以,您不需要UNIQUEIDENTIFIER 要使用GetUniqueIdentifier sp(名称也很严重,因为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