web-dev-qa-db-ja.com

SQL Serverでのトリガーの使用

sQLの新機能として、新しい行がテーブルAに挿入されたときにテーブルBを更新するトリガーを設定する方法を探しています。基本的な理解のために、ここにテーブルのいくつかの列を示します。

TABLE A:
+--------------+--------------+
|order_id (PK) |order_details |
+--------------+--------------+

Table B:
+-------------+--------------+-------------+
|item_id (PK) |item_details  |order_id (FK)|
+-------------+--------------+-------------+

このようなストアドプロシージャを使用してデータをテーブルAに挿入しています。明らかにこのプロシージャは機能しませんが、問題の発生場所を示したいと思います。トリガー以外にもっと良い方法があるかもしれません。問題はorder_id 2番目のINSERT内で使用します。

/*Parameters for the first Insert Statement*/
@customer_id INT,
@track_num NVARCHAR(50),
@pckg_num NUMERIC,

/*Parameters for the second Insert Statement*/
@manuf_name NVARCHAR(50),
@model_name NVARCHAR(50),
@qty NUMERIC,
@notes NVARCHAR(MAX)

/*Parameter I need for the second statement that doesn't exist until the first statement is committed*/
@order_id INT

AS

BEGIN
/*First Insert*/
INSERT INTO Orders
    (customer_id, track_num, pckg_num)
VALUES
    (@customer_id, @track_num, @pckg_num)
/*Second Insert*/
INSERT INTO Items
    (manuf, model, qty, notes, order_id)
VALUES
    (@manuf_name, @model_name, @qty, @notes, @order_id)

END

同じ手順内でトリガーを起動して、Webアプリからプロシージャに渡されたアイテムの詳細でテーブルBを更新し、テーブルAで新しく作成された行のPK(order_id)をテーブルBのFKとして含めます。

私はこれを他の方法で運なしに試してみましたが、トリガーに出くわし、それが良い選択のように思えました。他の方法について他に提案がある場合は、お気軽に! :) 前もって感謝します!

2
Kalen Kaczor

トリガーを含まない2つの主な方法(通常、トリガーはできるだけ回避することをお勧めします)-

1)最初のOUTPUTステートメントでINSERT句を使用して、生成されたID値を取り出します。

DECLARE @NewOrder TABLE (order_id INT);

INSERT INTO Orders
    (customer_id, track_num, pckg_num)
OUTPUT
    inserted.order_id INTO @NewOrder
VALUES
    (@customer_id, @track_num, @pckg_num);

INSERT INTO Items
    (manuf_name, model_name, qty, notes, order_id)
SELECT
    @manuf_name, @model_name, @qty, @notes, order_id
FROM @NewOrder;

2)Orders.order_idをID属性で宣言するのではなく、シーケンスオブジェクトを作成して使用します(SQL Server 2012以降が必要です)。

CREATE SEQUENCE OrderIDSeq AS INT
    START WITH 1;

CREATE TABLE Orders (
    order_id INT
        PRIMARY KEY
        DEFAULT (NEXT VALUE FOR OrderIDSeq),
    //... other columns as before
);

GO

CREATE OR ALTER PROCEDURE AddOrder(
    @customer_id INT, @track_num NVARCHAR(50), @pckg_num NUMERIC,
    @manuf_name NVARCHAR(50), @model_name NVARCHAR(50),
    @qty NUMERIC, @notes NVARCHAR(MAX)) AS
BEGIN
    DECLARE @order_id INT = NEXT VALUE FOR OrderIDSeq;

    INSERT INTO Orders
        (order_id, customer_id, track_num, pckg_num)
    VALUES
        (@order_id, @customer_id, @track_num, @pckg_num);

    INSERT INTO Items
        (order_id, manuf_name, model_name, qty, notes)
    VALUES
        (@order_id, @manuf_name, @model_name, @qty, @notes);
END;
1
Chris Rolliston