我尝试执行以下操作以便在使用值创建新行的同时更新伪标识值,但APPLY不喜欢将UPDATE语句作为正确的表源。除了使用标识列之外,最优雅的选择是什么?
create table Temp1(
id int not null identity(1,1) primary key
,data nvarchar(max) null)
create table Temp2(
id int not null primary key
,fkTemp1 int not null references Temp1(id)
,data nvarchar(max) null)
create table Numbering(
ObjectCode int not null primary key
,AutoKey int)
insert into Temp1(data) values('test string')
insert into Temp1(data) values('another test string')
insert into Numbering(ObjectCode, AutoKey) values(4, 1)
insert into Temp2(id, fkTemp1, data)
select n.AutoKey, t1.id, t1.data
from Temp1 t1
left join Temp2 t2 on t2.fkTemp1 = t1.id
cross apply (update Numbering set AutoKey = AutoKey + 1 output inserted.AutoKey where ObjectCode = 4) n
where t2.id is null -- only insert where a target row does not already exist
答案 0 :(得分:1)
您无法在INSERT
的一个语句中对两个不同的表执行UPDATE
和SQL Server 2005
。
在SQL Server 2008
中有MERGE
构造,但是,它仅适用于单个表格。
只需在事务中运行两个语句:
BEGIN TRANSACTION
DECLARE @AutoKey INT
SELECT @AutoKey = AutoKey
FROM Numbering WITH (UPDLOCK)
WHERE ObjectCode = 4
INSERT
INTO temp2
SELECT @AutoKey + ROW_NUMBER() OVER (ORDER BY id), id, data
FROM temp1
WHERE id NOT IN
(
SELECT fkTemp1
FROM temp2
)
UPDATE Numbering
SET AutoKey = AutoKey + @@ROWCOUNT
WHERE ObjectCode = 4
COMMIT
<强>更新
正如@Remus Rusanu
指出的那样,您实际上可以将UPDATE
输出子句传递到SQL Server 2005
中的表中。
但是,您似乎JOIN
和CROSS APPLY
OUTPUT
结果集都不能查看其他查询的结果。
答案 1 :(得分:0)
这样做,但你必须解决“T2.ID IS NULL”问题...
Declare @Key as int
Declare @cnt as int
Begin Transaction
Set @cnt = (Select count(*)
from Temp1 t1 left join Temp2 t2 on t2.fkTemp1 = t1.id
--where t2.id is null -- note: does not work, not sure what is intended
)
update Numbering set @Key = AutoKey = AutoKey + @cnt where ObjectCode = 4
insert into Temp2(id, fkTemp1, data)
select @Key+ROW_NUMBER() over (Order By t1.id)
, t1.id, t1.data
from Temp1 t1
left join Temp2 t2 on t2.fkTemp1 = t1.id
--where t2.id is null -- note: does not work,
Commit Transaction