我有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”。
你能帮助我实现这个目标吗?
编辑:无法保证[EmpBasic]表中的[名称] + [地址]是唯一的
答案 0 :(得分:2)
使用您的EmpProject连接表,您可能不希望上的主键约束 EmpID列
DECLARE @Count int DECLARE @NextEmpID int DECLARE @StartObjectID int DECLARE @EndObjectID int -- range of IDs to transfer (inclusive) SET @StartObjectID = 1 SET @EndObjectID = 105 BEGIN TRAN -- lock tables so IDENT_CURRENT is valid 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] ON INSERT [EmpBasic] ([EmpID], [Name], [Address]) SELECT @NextEmpID + ROW_NUMBER() OVER(ORDER BY ObjectID), [T1Name], [T1Address] FROM [EmpFull_Temp] WHERE [ObjectID] BETWEEN @StartObjectID AND @EndObjectID SET IDENTITY_INSERT [EmpBasic] OFF INSERT [EmpProject]([EmpID], [EmpProject]) SELECT @NextEmpID + ROW_NUMBER() OVER(ORDER BY ObjectID), [T1EmpProject] FROM [EmpFull_Temp] WHERE [ObjectID] BETWEEN @StartObjectID AND @EndObjectID COMMIT TRAN
答案 1 :(得分: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年是否有任何不同),不可能输出未插入的值。我过去通过使用其他字段之一(例如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,但我希望它能让您了解如何处理这个问题。
答案 2 :(得分:1)
将一个ObjectID列添加到EmpBasic表以便于数据传输,然后在完成后将其删除。我假设这是一次性操作,如果正在进行,我不建议添加和删除列
答案 3 :(得分:1)
我使用Stack Exchange Data Explorer来研究替代解决方案。目前唯一有承诺的人是here。它实际上是@ScotHauder的答案,除了使用具有ObjectID
列的临时表并使用IDENTITY_INSERT
将生成的EmpId
值移动到EmpBasic
之外。
如果您必须多次执行此操作,则需要将EmpBasic_Temp
EmpId IDENTITY
起始值设为Max(EmpBasic.EmpID)+1
。