0

私のアプリケーションでは、フォームから SQL Server 2005 データベースにデータ (「要求」) を送信し、後で監督者が確認して承認する必要があります。ユーザーは、新しいリクエストを挿入する権限を持っている必要がありますが、既に送信したリクエストを変更することはできません。

テーブルが 1 つの場合、これは簡単です。UPDATE 権限なしで、INSERT 権限のみを付与します。しかし、リクエストは実際には 1 対多の関係で 2 つのテーブルにまたがっています。ユーザーが既存のリクエストに追加の子行を挿入できないようにする必要があります。理想的には、これはデータベース レベルで実施する必要があります。親行と 1 つ以上の子行を同じトランザクションに挿入できるようにしますが、トランザクションがコミットされると、その外部キーを使用して新しい子行が挿入されるのを防ぎます。

これを達成するための最良の方法は何ですか?トリガーなしで「参照整合性」のこの特別なフレーバーを強制する方法はありますか? また、トリガーが唯一の方法である場合、親行が現在のトランザクション内に挿入されたことをどのようにテストできますか?

4

3 に答える 3

3

ストアド プロシージャまたはトリガー

子テーブルに権限を付与すると、書き込みが可能になります。

トリガーは書き込みを禁止し、ストアド プロシージャは、ストアド プロシージャのみがテーブルに書き込むため、そもそも書き込みを防止できます。

状況に合わせたカスタムであるため、ビジネスロジックをキャプチャできる「ネイティブ」な参照整合性はありません。

于 2010-01-21T08:15:14.730 に答える
1

次の例は、トリガーを使用してこの動作を実現する方法を示しています。INSERT単一のステートメントではなく、トランザクション内で子行が一度に 1 つずつ挿入される場合、これは機能しないことに注意してください。

CREATE TABLE parent1
(id INT PRIMARY KEY)

CREATE TABLE child1
(id INT
,parent_id INT
)
GO

ALTER TABLE child1 ADD CONSTRAINT chilld1fk FOREIGN KEY (parent_id)
REFERENCES parent1 (id)
GO


CREATE TRIGGER trg_child1
ON child1
INSTEAD OF INSERT
AS

        SELECT parent_id
        FROM child1 AS c
        WHERE EXISTS (SELECT 1
                      FROM inserted AS i
                      WHERE i.parent_id = c.parent_id
                     )

        IF @@ROWCOUNT > 0
            BEGIN
                RAISERROR('You cannot amend this request',16,1)
            END
        ELSE        
            BEGIN
                INSERT child1
                SELECT id
                       ,parent_id
                FROM inserted
            END
GO                                                            

BEGIN TRAN
        INSERT parent1
        VALUES (1)

        INSERT child1 
        (id
        ,parent_id
        )
        SELECT 10,1
        UNION SELECT 11,1        
COMMIT

-- attempting to insert another child outside the transaction
-- will result in an error
INSERT child1
SELECT 12,1

SELECT * FROM child1
于 2010-01-21T08:33:05.123 に答える
1

ストアド プロシージャを使用してデータを挿入します。

  • 最初のストアド プロシージャは親行を挿入します。ユーザーの挿入に関する情報を自動的に追加し、ステータス フィールドを設定します。

  • 2 番目のストアド プロシージャは、親行を確認した後に子行を挿入します。呼び出し元のユーザーが特定の親行に項目を追加する権限を持っていない場合、または親行のステータスが新しい位置の追加を許可していない場合、エラーが発生します。

または、トリガーを使用してチェックを行うこともできます。ただし、これはストアド プロシージャを明示的に呼び出すよりもややこしい場合があります。また、トリガーを忘れがちな人もいます。

于 2010-01-21T08:29:14.250 に答える