Я предполагаю, что T1ID, T2ID, T3ID являются идентичностями с положительным приращением. Я использую два трюка:
1) при вставке новых значений в таблицу, чтобы отличать старые значения от новых, я использую значение столбца идентификаторов. Если это больше, чем последний увиденный максимум, то это вновь добавленное значение. Однако, чтобы это оставалось верным, нам нужно убедиться, что никакие другие значения не были добавлены в таблицу, поэтому я устанавливаю уровень изоляции транзакции в сериализуемый.
2) Я создаю временный столбец в таблице 2, чтобы я мог отслеживать старые 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