1

私のテーブルにはこれらの値が含まれています

Name VARCHAR(50),
Program VARCHAR(50),
 Branch VARCHAR(30),
TotalP INT,
 TotalN INT)

名前がまだ存在しない場合、このテーブルにレコードを挿入しようとしました。これはおそらくここですでに回答されていますが、検索に何かを入力すると、7000以上の結果が表示され、100以上を調べてもまだ答えが見つかりません. ありとあらゆる助けをいただければ幸いです。

4

1 に答える 1

2

並行性について心配していない場合は、次のように動作します。

IF NOT EXISTS (
    SELECT 1
    FROM YourTable
    WHERE Name = @Name
)
BEGIN
    INSERT INTO YourTable (Name, Program, Branch, TotalP, TotalN)
    VALUES (@Name, @Program, @Branch, @TotalP, @TotalN)
END

ここでの問題は、2 つのプロセスが同時に同じものを追加しようとするとname...両方ともIF NOT EXISTSチェックに合格し、両方ともINSERT.

これを防ぐにnameは、挿入の 1 つが失敗する列に一意の制約を追加するか、または をNOT EXISTS使用してチェックでテーブルをロックすることができますWITH (UPDLOCK, HOLDLOCK)。これにより、同時実行性は低下しますが、エラーは発生しません。

編集:

必要な値がSELECTステートメントからのものである場合、次のように動作します。

INSERT INTO YourDestinationTable (Name, Program, Branch, TotalP, TotalN)
SELECT st.Name, st.Program, st.Branch, st.TotalP, st.TotalN
FROM 
    YourSourceTable st
    LEFT JOIN YourDestinationTable dt
        ON dt.Name = st.Name
WHERE 
    dt.Name IS NULL
    -- Add in any other conditions for YourSourceTable here...

YourSourceTableこれは、行が見つからない場合に行を挿入します ... andチェックYourDestinationTableを使用して実装されます。LEFT JOINIS NULL

これには以前と同じ注意事項があります... 2 つのプロセスがこのステートメントを同時に実行すると、name値が重複する可能性があります。に一意の制約を追加するか、トランザクション内に存在するかどうかをテストしている宛先テーブルの行で をname実行します。(UPDLOCK, HOLDLOCK)

BEGIN TRANSACTION
    IF NOT EXISTS (
        SELECT 1
        FROM 
            YourSourceTable st
            JOIN YourDestinationTable dt WITH (UPDLOCK, HOLDLOCK) 
                ON dt.Name = st.Name
        -- WHERE 
            -- Add in any other conditions for YourSourceTable here...
    )
    BEGIN
        INSERT INTO YourDestinationTable (Name, Program, Branch, TotalP, TotalN)
        SELECT Name, Program, Branch, TotalP, TotalN
        FROM YourSourceTable st
        -- WHERE 
        -- Add in any other conditions for YourSourceTable here...
    END
COMMIT
于 2013-01-23T19:57:08.007 に答える