我有以下数据库结构
Table1
============
T1ID
Fld1
Table2
============
T2ID
T1ID(Foreign Key from Table1)
Fld1
Table3
============
T3ID
T2ID(Foreign Key from Table2)
Fld1
现在我首先根据Table2
过滤Table3
和T1ID
数据。
之后我需要在同一个表中复制这些过滤后的记录。我想用存储过程来完成这个。我看过一些示例,其中数据在一个表中重复,但我不知道如何在这两个主要详细信息表中实现这一点。
答案 0 :(得分:1)
declare @T1ID int = 1
declare @T table(OldT2ID int, NewT2ID int)
merge Table2 as T
using (select T2ID, Fld1
from Table2
where T1ID = @T1ID) as S
on (0 = 1)
when not matched then
insert (T1ID, Fld1) values (@T1ID, S.Fld1)
output S.T2ID, inserted.T2ID into @T;
insert into Table3(T2ID, Fld1)
select T.NewT2ID, T3.Fld1
from Table3 as T3
inner join @T as T
on T3.T2ID = T.OldT2ID
答案 1 :(得分:0)
我假设T1ID,T2ID,T3ID是具有正增量的身份。我正在使用两个技巧:
1)当将新值插入表中以区分旧值和新值时,我正在使用标识列的值。如果它超过最后看到的最大值,那么它是一个新插入的值。但是为了使其保持正确,我们需要确保没有向表中添加其他值,因此我将事务的隔离级别设置为可序列化。
2)我正在table2中创建一个临时列,以便我可以跟踪新插入的旧t2id。我在操作结束时删除了列。
现在代码:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[DoIt]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[DoIt]
GO
CREATE PROCEDURE [dbo].[DoIt]
@T1ID int
AS
BEGIN
declare @T1IDString nvarchar(10) = cast(@T1ID as nvarchar(10))
declare @sql nvarchar(255)
declare @Table2max nvarchar(10)
set transaction isolation level serializable
begin transaction
select @Table2max = cast(max(T2ID) as nvarchar(10)) from Table2
exec dbo.sp_executesql @statement = N'alter table Table2 add [oldT2ID] [int] null'
set @sql = N'insert into Table2 (T1ID,fld1,oldT2ID) select T1ID,fld1,T2ID from Table2 where T1ID = ' + @T1IDString
EXEC dbo.sp_executesql @statement = @sql
set @sql = N'insert into Table3 select t2.T2ID, t3.fld1 from Table3 t3 join Table2 t2 on t3.T2ID = t2.oldT2ID where t2.T1ID = '
+ @T1IDString + ' and t2.T2ID > ' + @Table2max
exec dbo.sp_executesql @statement = @sql
exec dbo.sp_executesql @statement = N'alter table Table2 drop column [oldT2ID]'
commit transaction
END
GO