2016-04-15 33 views
0

我被授予使用游标来复制表格的任务。现在说我有3张表复制自:Company,Person_Link & Person。这是一个“一对多”的关系,因为一个公司可以有多个人。SQL Server - 使用游标复制多个表格

这是我的代码:

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER PROCEDURE [dbo].[DuplicateCompanyInfo] 
    @Comp_CompanyId NVARCHAR(80) 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @CompanyID NVARCHAR(30), 
      @PersonID NVARCHAR(30), 
      @PersonLinkID NVARCHAR(30), 
      @AddressLinkID NVARCHAR(30), 
      @AddressID NVARCHAR(30), 
      @PhoneLinkID NVARCHAR(30), 
      @PhoneID NVARCHAR(30) 

    EXEC @companyId = crm_next_id 5 
    EXEC @PersonId = crm_next_id 13 
    EXEC @PersonLinkId = crm_next_id 31 
    EXEC @AddressLinkId = crm_next_id 21 
    EXEC @AddressId = crm_next_id 1 
    EXEC @PhoneLinkId = crm_next_id 10208 
    EXEC @PhoneId = crm_next_id 14 

    -- Add Company 
    INSERT INTO Company 
    (
     Comp_CompanyId, Comp_PrimaryPersonId, Comp_PrimaryAddressId, Comp_Name, Comp_Type, Comp_Status, Comp_CreatedBy, 
     Comp_CreatedDate, Comp_UpdatedBy, Comp_UpdatedDate, Comp_TimeStamp, Comp_SecTerr, Comp_WebSite 
    ) 
    SELECT @companyId, @PersonId, @AddressId, Comp_Name, Comp_Type, Comp_Status, Comp_CreatedBy, 
      Comp_CreatedDate, '1', GETDATE(), Comp_TimeStamp, Comp_SecTerr, Comp_WebSite 

    FROM Company 
    WHERE Comp_CompanyId = @comp_companyid 


------- PersonLink Cursor --------------------------------------------- 
    -- Declare Variables 
    DECLARE @c_PeLi_PersonLinkId NVARCHAR(30) 
    DECLARE @c_PeLi_PersonId NVARCHAR(30) 
    DECLARE @c_PeLi_CompanyID NVARCHAR(30) 
    DECLARE @c_PeLi_CreatedBy NVARCHAR(30) 
    DECLARE @c_PeLi_CreatedDate NVARCHAR(30) 
    DECLARE @c_PeLi_UpdatedBy NVARCHAR(30) 
    DECLARE @c_PeLi_UpdatedDate NVARCHAR(30) 
    DECLARE @c_PeLi_TimeStamp NVARCHAR(30) 


    --Declare Cursor 
    DECLARE @getPeLiID CURSOR 
    SET @getPeLiID= CURSOR FOR 
    SELECT PeLi_PersonLinkId, PeLi_PersonId, PeLi_CompanyID, PeLi_CreatedBy, PeLi_CreatedDate, PeLi_UpdatedBy, 
     PeLi_UpdatedDate, PeLi_TimeStamp 
    FROM Person_Link 
    INNER JOIN Person 
    ON PeLi_PersonId = Pers_PersonId 
    AND PeLi_CompanyID = @comp_companyid 

    --Open Cursor & fetch 1st row into variables 
    OPEN @getPeLiID 
    FETCH NEXT FROM @getPeLiID INTO @c_PeLi_PersonLinkId, @c_PeLi_PersonId, @c_PeLi_CompanyID, @c_PeLi_CreatedBy, 
            @c_PeLi_CreatedDate, @c_PeLi_UpdatedBy, @c_PeLi_UpdatedDate, @c_PeLi_TimeStamp 


    --Fetch successful 
    --Check for a new row 
    WHILE @@FETCH_STATUS = 0 
    BEGIN 

     --EXEC @PersonLinkId = crm_next_id 31 


    INSERT INTO Person_Link 
    (
     PeLi_PersonLinkId, PeLi_PersonId, PeLi_CompanyID, PeLi_CreatedBy, PeLi_CreatedDate, PeLi_UpdatedBy, 
     PeLi_UpdatedDate, PeLi_TimeStamp 
    ) 
    VALUES 
    (
     @PersonLinkId, @PersonId, @CompanyId, @c_PeLi_CreatedBy, @c_PeLi_CreatedDate, '1', GETDATE(), @c_PeLi_TimeStamp 
    ) 


    --Get next available row into variables 
    FETCH NEXT FROM @getPeLiID INTO @c_PeLi_PersonLinkId, @c_PeLi_PersonId, @c_PeLi_CompanyID, @c_PeLi_CreatedBy, 
            @c_PeLi_CreatedDate, @c_PeLi_UpdatedBy, @c_PeLi_UpdatedDate, @c_PeLi_TimeStamp 

    END 

    CLOSE @getPeLiID 
    DEALLOCATE @getPeLiID 


------- Person Cursor ------------------------------------------------- 
    -- Declare Variables 
    DECLARE @c_Pers_PersonId NVARCHAR(30) 
    DECLARE @c_Pers_CompanyId NVARCHAR(30) 
    DECLARE @c_Pers_PrimaryUserId NVARCHAR(30) 
    DECLARE @c_Pers_FirstName NVARCHAR(30) 
    DECLARE @c_Pers_SecTerr NVARCHAR(30) 
    DECLARE @c_Pers_CreatedBy NVARCHAR(30) 
    DECLARE @c_Pers_CreatedDate NVARCHAR(30) 
    DECLARE @c_Pers_UpdatedBy NVARCHAR(30) 
    DECLARE @c_Pers_UpdatedDate NVARCHAR(30) 
    DECLARE @c_Pers_TimeStamp NVARCHAR(30) 


    --Declare Cursor 
    DECLARE @getPersID CURSOR 
    SET @getPersID= CURSOR FOR 
    SELECT Pers_PersonId, Pers_CompanyId, Pers_PrimaryUserId, Pers_FirstName, Pers_SecTerr, Pers_CreatedBy, 
      Pers_CreatedDate, Pers_UpdatedBy, Pers_UpdatedDate, Pers_TimeStamp 
    FROM Person 
    INNER JOIN Person_Link 
    ON Pers_PersonId = PeLi_PersonId 
    AND PeLi_CompanyID = @comp_companyid  


    --Open Cursor & fetch 1st row into variables 
    OPEN @getPersID 
    FETCH NEXT FROM @getPersID INTO @c_Pers_PersonId, @c_Pers_CompanyId, @c_Pers_PrimaryUserId, @c_Pers_FirstName, 
            @c_Pers_SecTerr, @c_Pers_CreatedBy, @c_Pers_CreatedDate, @c_Pers_UpdatedBy, 
            @c_Pers_UpdatedDate, @c_Pers_TimeStamp 


    --Fetch successful 
    --Check for a new row 
    WHILE @@FETCH_STATUS = 0 
    BEGIN 

    --EXEC @PersonId = crm_next_id 13 


    INSERT INTO Person 
    (
     Pers_PersonId, Pers_CompanyId, Pers_PrimaryUserId, Pers_FirstName, Pers_SecTerr, Pers_CreatedBy, 
     Pers_CreatedDate, Pers_UpdatedBy, Pers_UpdatedDate, Pers_TimeStamp 
    ) 
    VALUES 
    (
     @PersonId, @companyId, @c_Pers_PrimaryUserId, @c_Pers_FirstName, @c_Pers_SecTerr, @c_Pers_CreatedBy, 
     @c_Pers_CreatedDate, '1', GETDATE(), @c_Pers_TimeStamp 
    ) 


    --Get next available row into variables 
    FETCH NEXT FROM @getPersID INTO @c_Pers_PersonId, @c_Pers_CompanyId, @c_Pers_PrimaryUserId, @c_Pers_FirstName, 
            @c_Pers_SecTerr, @c_Pers_CreatedBy, @c_Pers_CreatedDate, @c_Pers_UpdatedBy, 
            @c_Pers_UpdatedDate, @c_Pers_TimeStamp 

    END 

    CLOSE @getPersID 
    DEALLOCATE @getPersID 

这是我的表结构:

公司表:

comp_companyid | comp_primarypersonid | comp_primaryaddressid | comp_name 
------------------------------------------------------------------------- 
2    | 2     | 2      | company 2 
3    | 3     | 3      | company 3 

人表:

pers_personid | pers_companyid  | pers_primaryaddressid | pers_name 
------------------------------------------------------------------------- 
2    | 2     | 2      | person 2 
3    | 3     | 3      | person 3 
4    | 2     | 2      | person 4 

人链接表:

peli_personlinkid | peli_personid  | peli_companyid 
------------------------------------------------------------------------- 
2     | 2     | 2     
3     | 3     | 3         

我执行存储过程只有1人属于1家公司时,有没有问题,但是当公司有2人或以上,第二人行不会被复制,只有第一个。

错误消息将弹出:

消息2627,级别14,状态1,过程DuplicateCompanyInfo,行80
违反PRIMARY KEY约束 'PK__Person_L__BCD268642CF2ADDF' 的。不能在对象'dbo.Person_Link'中插入重复键。

消息2627,级别14,状态1,过程DuplicateCompanyInfo,PRIMARY KEY约束 'PK__Person__381A5AC529221CFB' 的线141
冲突。不能在对象'dbo.Person'中插入重复键。

我可以通过删除注释--EXEC @PersonLinkId = crm_next_id 31 & --EXEC @PersonID = crm_next_id 13后光标就开始,这样就会产生一个新的ID每次复制解决这个问题。但它会导致不会记录,因为它们中的每一个都将基于其表重复生成自己的新ID,而不是应用彼此的外键。

请帮助或引导我通过!预先感谢您的时间&努力! Desmond

+2

为什么使用游标?这似乎是过度复杂的问题? –

+0

嗨,先生,请参阅我的评论,回复伊姆兰的答案下面的解释。表格中可能有很多重复的记录,所以我想用游标一行一行地浏览。 –

回答

1

抱歉现在无法访问SQL-Server。

我无法在插入数据的位置看到您的表格定义。但是从错误看起来你的表格定义不正确。即您的主键选择对于person和person_link表格不正确。你的正确的主键应该是一个外键。

二,为什么要使用游标?如果你只是需要将数据从一组表中复制到另一个表中,为什么不使用查询呢?有什么具体的理由使用光标?

UPDATE: 从更新后的表结构,主键和外键都不清楚,不过貌似comp_companyid是在人(pers_companyid)和Person_Link(peli_companyid链接为外键在你的公司表的主键)表。

现在,如果你的表的结构是这样的:

公司表: comp_companyid(PK)

人表: pers_personid(PK)和pers_companyid(FK)

Person Link Table: peli_personlinkid(PK)and peli_personid(FK),peli_companyid(FK)

我没有看到任何重复问题,除非您在PK列中插入重复项。

现在仔细查看代码后,您将peli_personlinkid提取到@c_PeLi_PersonLinkId变量中。

NEXT FROM @getPeLiID提取到@c_PeLi_PersonLinkId,@c_PeLi_PersonId,@c_PeLi_CompanyID,@c_PeLi_CreatedBy,@c_PeLi_CreatedDate,@c_PeLi_UpdatedBy,@c_PeLi_UpdatedDate,@c_PeLi_TimeStamp

但是当你插入数据不插入这个值,相反,您要在主键中插入@PersonLinkId。由于这个值来自另一个存储过程,(我不知道这个存储过程正在做什么,但看起来像生成下一个ID并返回)。您在该过程

EXEC @PersonLinkId = crm_next_id 31

所以开始执行,在循环中,您继续为每person_link插入此值。如果表中有多个person_link,那当然会违反PK约束。 Person表也是一样的问题。

这就是为什么你会得到主键违规错误。

而不是每次插入此值,您应该插入从@c_PeLi_PersonLinkId获取检索行的值。

希望这会帮助你,现在你将能够解决这个问题。

老实说,我仍然相信你可以跟你的老大说话,在这种情况下可以很容易地避免游标,你可以用简单的插入和选择语句实现所有这些,而且这样做会更好,更快。但是如果你不能替换游标,你可以修正上面确定和建议的存储过程。

+0

请教我如何在'Person'和'PersonLink'中定义我的主键,以便它可以成为公司的外键? 我的前辈说,必须在这种情况下使用游标,因为它是一个许多人,因为我有几个其他表重复多关系: 1.公司电话(传真) 2.公司PhoneLink(传真) 3.联系电话(业务) 4.公司PhoneLink(业务) 5.人电话(传真) 6.人PhoneLink(传真) 7.人电话(业务) 8.人PhoneLink(业务) 9.地址 10. AddressLink + Person + PersonLink + Company,总计总计13个表格。可能有很多重复的记录withint –

+0

@DesmondChau如果公司表中的主键是Person和PersonLink表中的外键,那么除非您需要一对一关系,否则请不要将它用作这两个表中的PrimaryKey。使用任何其他例如某些标识列作为这些表的主键。 – Imran

+0

@DesmondChau它是多对多的关系吗?请分享表格结构。最后,即使你连接了很多表格,我仍然没有看到这里使用游标。 – Imran