1

以下の構造に似た3つのテーブルがあります

    CREATE TABLE [dbo].[EmpBasic](
        [EmpID] [int] IDENTITY(1,1) NOT NULL Primary Key,
        [Name] [varchar](50),
        [Address] [varchar](50)
        )


    CREATE TABLE [dbo].[EmpProject](
        [EmpID] [int] NOT NULL primary key,  // referencing column with EmpBasic
        [EmpProject] [varchar](50)  )



    CREATE TABLE [dbo].[EmpFull_Temp](
        [ObjectID] [int] IDENTITY(1,1) NOT NULL Primary Key,
        [T1Name] [varchar](50) ,
        [T1Address] [varchar](50) ,
        [T1EmpProject] [varchar](50) 
            )

EmpFull_Temp テーブルには、ダミーのオブジェクト ID 列を持つレコードがあります...最初の 2 つのテーブルにこのテーブルのレコードを入力したいのですが、最初の 2 つのテーブル間の参照として EmpID を使用します。

ストアドプロシージャでこれを試しました...

    Create Table #IDSS (EmpID bigint, objID bigint)

    Insert into EmpBasic
        output Inserted.EmpID, EmpFull_Temp.ObjectID
        into #IDSS
        Select T1Name, T1Address from EmpFull_Temp
            Where ObjectID < 106


    Insert into EmpProject
        Select A.EmpID, B.T1EmpProject from #IDSS as A, EmpFull_Temp as B
            Where A.ObjID = B.ObjectID

しかし、それは言う..マルチパート識別子「EmpFull_Temp.ObjectID」をバインドできませんでした。

これを達成するために私を助けてください...

編集: [名前] + [アドレス]が[EmpBasic]テーブル全体で一意であるという保証はありません

4

4 に答える 4

2

EmpProject 結合テーブルでは、おそらくEmpID 列だけに主キー制約を適用したくないでしょう。

DECLARE @Count int
DECLARE @NextEmpID int
DECLARE @StartObjectID int
DECLARE @EndObjectID int

-- 転送する ID の範囲 (包括的)
SET @StartObjectID = 1
SET @EndObjectID = 105

トラン開始
    -- IDENT_CURRENT が有効になるようにテーブルをロックします。
    SELECT @Count = COUNT(*) FROM [EmpBasic] WITH (TABLOCKX, HOLDLOCK)
    SELECT @Count = COUNT(*) FROM [EmpProject] WITH (TABLOCKX, HOLDLOCK)

    SELECT @NextEmpID = IDENT_CURRENT('EmpBasic')

    SET IDENTITY_INSERT [EmpBasic] オン
    INSERT [EmpBasic] ([EmpID]、[名前]、[アドレス])
    SELECT @NextEmpID + ROW_NUMBER() OVER(ORDER BY ObjectID), [T1Name], [T1Address]
    FROM [EmpFull_Temp]
    WHERE [ObjectID] @StartObjectID と @EndObjectID の間
    SET IDENTITY_INSERT [EmpBasic] オフ

    INSERT [EmpProject]([EmpID], [EmpProject])
    SELECT @NextEmpID + ROW_NUMBER() OVER(ORDER BY ObjectID), [T1EmpProject]
    FROM [EmpFull_Temp]
    WHERE [ObjectID] @StartObjectID と @EndObjectID の間

コミットトラン

于 2010-06-17T16:28:24.837 に答える
1

Stack Exchange Data Explorer を使用して、代替ソリューションを調査しました。現時点で有望な唯一のものをここに示しますObjectID列を持つ一時テーブルを使用IDENTITY_INSERTし、生成されたEmpId値をに移動するために使用することを除いて、これは事実上@ScotHauderの答えEmpBasicです。

これを複数回行う必要がある場合は、EmpBasic_Temp EmpId IDENTITY開始値を にする必要がありますMax(EmpBasic.EmpID)+1

于 2010-06-17T02:41:54.187 に答える
1

この問題の解決策は、「親」テーブル (つまり、IDENTITY 列を持つテーブル) が自然キー (つまり、組み合わせたときに一意であることが保証される 1 つ以上のフィールド) を持つかどうかによって異なります .

たとえば、この場合、Name と Address の組み合わせは一意になるでしょうか。

答えが「はい」の場合は、生成された ID を出力して保存する手間をかけずに、単に EmpBasic に挿入できます。次に、自然キー (名前とアドレスなど) を使用して EmpBasic に結合し直す EmpProject に挿入し、正しい EmpID を見つけることができます。

Insert into EmpBasic 
    Select T1Name, T1Address from EmpFull_Temp 
        Where ObjectID < 106 

Insert into EmpProject 
    Select A.EmpID, B.T1EmpProject from EmpBasic as A, EmpFull_Temp as B 
        Where A.Name = B.Name And A.Address = B.Address

答えが「いいえ」の場合、私が知っている簡単な解決策はありません。SQL Server 2005 では (これが 2008 年と異なるかどうかはわかりません)、挿入されていない値を出力することはできません。過去に、他のフィールドの 1 つ (Name など) を使用して元の ID (この場合は ObjectID) を一時的に保存し、それを使用して、上記のように子レコードを挿入するときに結合してから、この問題を回避しました。親レコードを更新するために戻る o 一時的な値を削除/置換します。それはいいことではありませんが、私はより良い方法を見つけていません。

Insert into EmpBasic 
    Select cast(ObjectID as varchar(50)) as name, T1Address from EmpFull_Temp 
        Where ObjectID < 106 

Insert into EmpProject 
    Select A.EmpID, B.T1EmpProject from EmpBasic as A, EmpFull_Temp as B 
        Where A.Name = cast(B.ObjectID as varchar(50))

Update EmpBasic 
    Set Name = B.T1Name
    from EmpBasic as A, EmpFull_Temp as B 
        Where A.Name = cast(B.ObjectID as varchar(50))

注: 上記のサンプル SQL はまだテストしていませんが、これによってどのようにアプローチするかについてのアイデアが得られることを願っています。

于 2010-06-16T07:21:38.997 に答える
1

ObjectID 列を EmpBasic テーブルに追加してデータ転送を容易にし、完了したら削除します。これは 1 回限りの操作であると想定しています。これが進行中の場合、列の追加と削除はお勧めしません

于 2010-06-16T21:26:17.273 に答える