使用带有UPDATE语句的APPLY作为行源

时间:2009-07-28 15:38:28

标签: sql sql-server sql-server-2005 tsql

我尝试执行以下操作以便在使用值创建新行的同时更新伪标识值,但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

2 个答案:

答案 0 :(得分:1)

您无法在INSERT的一个语句中对两个不同的表执行UPDATESQL 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中的表中。

但是,您似乎JOINCROSS 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