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 个表...但以 EmpID 作为前 2 个表之间的引用。

我在存储过程中试过这个......

    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”。

你能帮我实现这个目标吗...

编辑:不保证 [Name]+[Address] 在 [EmpBasic] 表中是唯一的

4

4 回答 4

2

使用 EmpProject 连接表,您可能不希望EmpID 列上的主键约束

声明 @Count int
声明 @NextEmpID int
声明 @StartObjectID 整数
声明 @EndObjectID 整数

-- 要传输的 ID 范围(包括)
设置@StartObjectID = 1
设置@EndObjectID = 105

开始传输
    -- 锁定表,使 IDENT_CURRENT 有效
    SELECT @Count = COUNT(*) 从 [EmpBasic] WITH (TABLOCKX, HOLDLOCK)
    SELECT @Count = COUNT(*) 从 [EmpProject] WITH (TABLOCKX, HOLDLOCK)

    选择 @NextEmpID = IDENT_CURRENT('EmpBasic')

    SET IDENTITY_INSERT [EmpBasic] ON
    插入 [EmpBasic]([EmpID]、[名称]、[地址])
    SELECT @NextEmpID + ROW_NUMBER() OVER(ORDER BY ObjectID), [T1Name], [T1Address]
    来自 [EmpFull_Temp]
    @StartObjectID 和 @EndObjectID 之间的 [ObjectID]
    SET IDENTITY_INSERT [EmpBasic] 关闭

    插入 [EmpProject]([EmpID], [EmpProject])
    SELECT @NextEmpID + ROW_NUMBER() OVER(ORDER BY ObjectID), [T1EmpProject]
    来自 [EmpFull_Temp]
    @StartObjectID 和 @EndObjectID 之间的 [ObjectID]

提交翻译

于 2010-06-17T16:28:24.837 回答
1

此问题的解决方案取决于“父”表(即具有 IDENTITY 列的表)是否具有自然键(即,一个或多个字段在组合时保证是唯一的,而不是代理主键) .

例如,在这种情况下,名称和地址的组合是否会是唯一的?

如果答案是肯定的,那么您可以简单地插入 EmpBasic,而无需输出和存储生成的 ID。然后您可以插入到 EmpProject 中,使用自然键(例如姓名和地址)重新加入 EmpBasic 以找到正确的 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 年是否有任何不同),不可能输出未插入的值。过去我通过使用其他字段之一(例如名称)来临时存储原始 ID(在本例中为 ObjectID)来解决此问题,在插入子记录时使用它来加入如上所述然后消失返回以更新父记录或删除/替换临时值。这不是很好,但我还没有找到更好的方法。

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 表以促进数据传输,然后在完成后将其删除。我假设这是一次性操作,如果这是持续的,我不建议添加和删除一列

于 2010-06-16T21:26:17.273 回答
1

我使用 Stack Exchange Data Explorer 来研究替代解决方案。目前唯一有希望的就是这里。这实际上是@ScotHauder 的答案,除了使用具有该ObjectID列的临时表并使用IDENTITY_INSERT将生成的EmpId值移动到EmpBasic.

如果您必须多次执行此操作,则需要将EmpBasic_Temp EmpId IDENTITY起始值设为Max(EmpBasic.EmpID)+1.

于 2010-06-17T02:41:54.187 回答