2009-07-28 10 views
1

新しい行を作成するために値を使用するのと同時に擬似ID値を更新するために、次の操作を実行しようとしましたが、APPLYはUPDATE文を右テーブルソース。単純にID列を使用する以外の最もエレガントな代替手段は何ですか?UPDATE文を行ソースとして使用してAPPLYを使用します。

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

もあなたのクエリは私には意味を作っていない、APPLYを占めて...「T2.IDはNULL IS」問題を解決する必要があります。あなたは "どこにt2.idがnullであるか"をあなたのinsert..selectに持っていますが、Temp2のidカラムは絶対にnullにすることはできません。そのため、決して結果を挿入するべきではありません。 – RBarryYoung

答えて

1

あなたはSQL Server 2005に1つのステートメントで2つの異なるテーブルの上にINSERTUPDATEを行うことはできません。

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として

SQL Server 2005でテーブルにパイプラインUPDATE出力句を、指摘しますが、実際にできます。

しかし、JOINでもCROSS APPLYでもOUTPUTの結果は他のクエリの結果と同じように見えます。

+0

実際には、OUTPUT句を使用してSQL Server 2005の2つのテーブルに対してINSERTとUPDATEを実行できますが、OUTPUT句はあまり柔軟性がありません。あなたは確かにAPPLY演算子でUPDATEを使用することはできません。 – RBarryYoung

+0

@RBarryYoung:あなたは 'INSERT INTO SELECT * FROM(UPDATE ... OUTPUT INSERTED。*)'のような意味ですか?それは 'SQL Server 2008'でしか利用できないのですか? – Quassnoi

+0

@Quassnoi:UPDATE出力をINSERTに連結することができます。http://rusanu.com/2008/04/09/chained-updates/ –

0

これはそれを行うだろうが、あなたは

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 
+0

ラット、私はQuassoniが本質的に同じ答えを持っていると思います。 – RBarryYoung

関連する問題