2016-04-15 31 views
0

カーソルを重複するテーブルを使用するタスクが与えられました。今私は3つのテーブルから重複している:会社、Person_Link &人。 1つの会社が複数の人を持つことができるので、「1対多」の関係です。SQL Server - カーソルで複数のテーブルを重複する

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 

人のリンク表

会社表:これは私のテーブル構造である

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 

この

は私のコードです:

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

そこだけ1人が1社に属していますが、同社は、上記の2人またはを持っている場合、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'に重複キーを挿入できません。

彼らはそれぞれの時間が重複し、新たなIDを生成するようにカーソルが始まった後、私はコメント--EXEC @PersonLinkId = crm_next_id 31 & --EXEC @PersonID = crm_next_id 13を削除することによってこの問題を解決することができます。しかし、それぞれが互いの外部キーを適用するのではなく、テーブル複製に基づいて独自の新しいIDを生成するため、Comp_PrimaryPersonID & Pers_PersonID & PeLi_PersonIDが集計されません。

私を助けてガイドしてください!あなたの時間をお寄せいただきありがとうございます&努力! Desmond

+2

なぜカーソルを使用するのですか?それは問題を過度に複写しているようですね? –

+0

こんにちは、私のコメントを参照してください。テーブル内には重複したレコードがたくさんあるので、カーソルを使用して行ごとに移動する必要があります。 –

答えて

1

現在、SQL-Serverにアクセスできません。

データを挿入するテーブル定義が表示されません。しかし、あなたのテーブル定義が正しくないように見えるエラーから。つまり、personおよびperson_linkテーブルのプライマリキーの選択が正しくありません。あなたのcurrectプライマリキーは、外部キーでなければなりません。

第2に、なぜカーソルですか?あるテーブルセットのデータを別のテーブルセットに複製するだけでよいのであれば、単にクエリを使用するのはなぜですか?カーソルを使用する特別な理由はありますか?

UPDATE: あなたの更新されたテーブルの構造から、主キーと外部キーは明確ではないですが、comp_companyidは人(pers_companyid)とPerson_Link(peli_companyidの外部キーとしてリンクされているあなたの会社のテーブルの主キーであるように見えます)テーブル。

会社表: comp_companyid(PK)

パーソン表: pers_personid(PK)とpers_companyid(FK)

は今、あなたのテーブルの構造は次のようにしている場合

人リンクテーブル: peli_personlinkid(PK)およびpeli_personid(FK)、peli_companyid(FK)

重複をPK列に挿入しない限り、重複の問題はありません。

あなたのコードを注意深く見て、peli_personlinkidを@c_PeLi_PersonLinkId変数にフェッチしています。

は@c_PeLi_PersonId、@c_PeLi_CompanyID、@c_PeLi_CreatedBy、@c_PeLi_CreatedDate、@c_PeLi_UpdatedBy、@c_PeLi_UpdatedDate、@c_PeLi_TimeStamp

しかし、あなたはデータを挿入しているときにこの値を挿入していない、次の@getPeLiID INTO @c_PeLi_PersonLinkIdからのフェッチ@PersonLinkIdを主キーに挿入しています。この値は別のストアドプロシージャから来ているので(このストアドプロシージャが何をしているのかはわかりませんが、次のIDを生成して返すように見えます)あなたが手順

EXEC @PersonLinkId = crm_next_idだから、31

の開始時に実行され、ループの中で、あなたはすべてのperson_linkため、この値を挿入し続けます。表に複数のperson_linkがある場合は、もちろんPK制約違反です。そしてまったく同じ問題はPersonテーブルでも同じです。

これは、プライマリキー違反エラーが発生する理由です。

毎回この値を挿入するのではなく、@c_PeLi_PersonLinkIdから取得した値を挿入して、行を取得する必要があります。

希望すると、これで問題は解決します。

正直言って、私はまだあなたのシニアと話すことができ、この状況では簡単にカーソルを避けることができ、簡単な挿入と選択のステートメントでこれを達成できます。しかし、カーソルを置き換える立場にない場合は、上で示したようにストアドプロシージャを修正するだけです。

+0

私の主キーを 'Person'と' PersonLink'で定義して、会社からの外部キーにする方法を教えてください。 私のシニアはこのケースでカーソルを使用する必要があります。これは、他の多くのテーブルを複製するためのものです。 1.会社電話番号(ファックス番号) 2.会社電話番号()3.会社電話番号ビジネス) 4.会社PhoneLink(ビジネス) 5人の電話番号(FAX番号) 6人PhoneLink(ファックス) 7人の電話番号(ビジネス) 8人PhoneLink(ビジネス) 9.住所 10 AddressLink + Person + PersonLink + Companyは合計で13個のテーブルを合計します。 –

+0

@DesmondChau社内テーブルの主キーがPerson&PersonLinkテーブルの外部キーである場合、一対一の関係が必要な場合を除き、これら2つのテーブルのPrimaryKeyとして使用しないでください。他のものを使用してください。これらの表の主キーとしてのIdentity列。 – Imran

+0

@DesmondChau多対多関係はどうですか?親切にテーブル構造を共有してください。最後に、多くのテーブルからリンクしていても、ここではカーソルの使用は見られません。 – Imran

関連する問題