2011-11-11 6 views
0

CASE句内のフィールドにnew_idを割り当てる必要があります。T-SQL:CASE句内のINSERT INTO&OUTPUTの使用

INSERT INTO [table1] 
    (field1, field2, field3, field4, field5, field6) 
SELECT @someID1, field1_from_table2, @someID2, field2_from_table2, 
CASE 
    WHEN field3_from_table2 IS NULL 
    THEN INSERT INTO [table3] 
     OUTPUT inserted.some_new_id 
     DEFAULT VALUES 
    ELSE field3_from_table2 
END 
FROM [table2] 

コードフラグメント

INSERT INTO [table3] 
OUTPUT inserted.some_new_id 
DEFAULT VALUES 
CASE句の外で使用される場合、正常に動作

:ここ

は一例です。

主な問題は、field3_from_table2がtable1 IS NULLに挿入しようとしているときに、table3から取得したnew_idを割り当てる必要があるということです。
table3は単なるIDディスパッチャーです。

この問題の考え方または回避策はありますか?

ありがとうございます。

+2

あなたは 'CASE'内のステートメントを持つことができない - それが唯一の**戻り値**(' ....ここTHEN(いくつかの値) ') –

+0

@Chorinator、' field3_from_table2'場合は設計されていますあなたの例でtable1に 'INSERT'される行は' NULL'ですか? – gonsalu

+0

@Gonsaluいいえ、この例ではありませんが、かなり単純な表です。それは1つの列だけを含み、それは同一性です。私はそのテーブルをIdディスパッチャとしてのみ使用します。 – Chorinator

答えて

1

marc_sが指すように、あなたはaの場合を使用してこれを行うことはできません。 ケースの正しい構文はhereです。

問題を解決するには、cursorを使用することをお勧めします。

spのコード例は、カーソルhereで確認できます。

0

table3に生成された値をINGの値が1ずつとIDENTITY性ように、あなたはROW_NUMBER()を用いたものを自分で生成することができ、table3シーケンシャル整数値を生成すると仮定すると、次にINSERT

しかし、自分で値を生成しているので、ステートメントの実行中に変更が発生しないように、table3をロックする必要があります。

テストケースを設定しましょう。

USE tempdb 
GO 

IF OBJECT_ID('table1', 'U') IS NOT NULL DROP TABLE table1; 
IF OBJECT_ID('table2', 'U') IS NOT NULL DROP TABLE table2; 
IF OBJECT_ID('table3', 'U') IS NOT NULL DROP TABLE table3; 

CREATE TABLE table1 (
    field1 int, 
    field2 int, 
    field3 int, 
    field4 int, 
    field5 int 
); 

CREATE TABLE table2 (
    field1_from_table2 int, 
    field2_from_table2 int 
); 

CREATE TABLE table3 (
    field1_from_table3 int IDENTITY(1,1) 
); 

INSERT INTO table2 
VALUES (1000, 2000) 
    , (1001, NULL); 
GO 

-- INSERT 20 records to generate some IDENTITY increments. 
INSERT INTO table3 DEFAULT VALUES 
GO 20 

次に、順次値を生成するコードの例を示します。

BEGIN TRANSACTION; 

SET IDENTITY_INSERT table3 ON; 
GO 

DECLARE @someID1 int = 100 
     , @someID2 int = 200; 
DECLARE @output table (field4 int, field5 int); 

-- Lock table3 exclusively to prevent INSERTs that spoil IDENTITY values. 
SELECT TOP(0) 1 FROM table3 WITH (HOLDLOCK, TABLOCKX); 

-- INSERT into table1, generating sequential integers 
-- and saving the output in @output. 
INSERT INTO table1 
OUTPUT inserted.field4 
    , inserted.field5 
    INTO @output(field4, field5) 
SELECT @someID1 
    , field1_from_table2 
    , @someID2 
    , field2_from_table2 
    , CASE 
     WHEN field2_from_table2 IS NOT NULL THEN field2_from_table2 
     ELSE (ROW_NUMBER() OVER (PARTITION BY field2_from_table2 
            ORDER BY field2_from_table2)) 
       + (SELECT MAX(field1_from_table3) FROM table3) 
     END 
    FROM table2; 

-- INSERT generated integer values. 
INSERT INTO table3 (field1_from_table3) 
SELECT field5 
    FROM @output 
WHERE field4 IS NULL; 

SET IDENTITY_INSERT table3 OFF; 
GO 

COMMIT; 

SELECT * FROM table1; 
SELECT * FROM table2; 
SELECT * FROM table3;