0

2 つのテーブルがあります: 1. 従業員 2. バウチャー

Employees テーブルには 1 つの主キーがあります。Vouchers テーブルには、Employees テーブルを参照する 3 つの外部キー制約があります。

以下は、SQL Server でテーブルとそれらのリレーションシップの両方を作成するサンプル T-SQL スクリプト (実際のテーブル スクリプトではありません) です。

IF OBJECT_ID('dbo.Vouchers') IS NOT NULL
    DROP TABLE dbo.Vouchers
IF OBJECT_ID('dbo.Employees') IS NOT NULL
    DROP TABLE dbo.Employees
GO

CREATE TABLE Employees
(
  ObjectID     INT    NOT NULL   PRIMARY KEY    IDENTITY
)

CREATE TABLE Vouchers
(
  ObjectID     INT    NOT NULL   PRIMARY KEY    IDENTITY,
  IssuedBy     INT,
  ReceivedBy   INT,
  ApprovedBy   INT,

  CONSTRAINT fk_Vouchers_Employees_IssuedBy FOREIGN KEY (IssuedBy)
                                    REFERENCES Employees (ObjectID)
                                    ON UPDATE CASCADE
                                    ON DELETE NO ACTION,
 CONSTRAINT fk_Vouchers_Employees_ReceivedBy FOREIGN KEY (ReceivedBy)
                                    REFERENCES Employees (ObjectID)
                                    ON UPDATE CASCADE
                                    ON DELETE NO ACTION,
 CONSTRAINT fk_Vouchers_Employees_ApprovedBy FOREIGN KEY (ApprovedBy)
                                    REFERENCES Employees (ObjectID)
                                    ON UPDATE CASCADE
                                    ON DELETE NO ACTION 
)

しかし、エラーがスローされます:

Msg 1785, Level 16, State 0, Line 7
Introducing FOREIGN KEY constraint 'fk_Vouchers_Employees_ReceivedBy' on table 'Vouchers' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

ここで利用できる効率的なソリューションについてはわかりません。リレーションシップの要件は次のとおりです。従業員が削除されるたびに、従業員への列の一部を参照するバウチャーは削除されません (ON DELETE CASCADE はオプションではありません)。代わりに、削除された従業員を参照する列 (IssuedBy、ReceivedBy、および/または ApprovedBy) の値を NULL に設定する必要があります (列が NULLABLE であるため)。

どうもありがとう!

4

3 に答える 3

3

厳密に言えば、リレーショナル デザインの観点から、Vouchers テーブルは 3 つの外部キーです。CASCADE アサーションまたはその他の方法でそれらを強制するかどうかは実装上の問題ですが、リレーショナル設計は依然として存在します。おそらく、3 つのフィールドのいずれかが NULL でない場合、一致するレコードが存在する必要があることを強制したいとします。か否か。設計を強制するかどうかは、実装の問題です。

ただし、あなたが説明する違反は、あなたの危険にさらされていると想定されています。あなたがこの質問をしているという事実は、これらの選択が沼地につながる可能性があるすべての方法を十分に理解していない可能性があることを示唆しています.

エラーは、3 つのうちの 1 つ以上が同じ従業員を参照している可能性があるという事実の結果である可能性があると思います。

ところで、CASCADES が役立つような方法でレコードを削除する必要があるとわかったケースはほとんどありません。通常、これはデータベースが大きくなりすぎないようにするために使用されます。データベースの容量は、時間の経過とともにますます問題になりません。

于 2009-01-11T03:55:59.940 に答える
2

実際に従業員を削除するのではなく、トリガーを使用してフラグを設定し、従業員を削除済みとしてマークします。

通常、更新や削除のカスケードをオンにすることはありませんが、代わりに、アプリケーションでこれらのアクションを明示的に実行する必要があります。

于 2009-01-11T04:10:18.413 に答える
1

設計の観点からは、リストした 3 つの外部キーがあるとよいようです。取得しているエラー メッセージは、外部キーの ON UPDATE CASCADE オプションに関連しているようです (ただし、指定どおりにテーブルを作成することはできました)。とにかく、あなたが望んでいる動作を得るには、レコードを削除する前に発生する従業員テーブルのトリガーをお勧めします。このトリガーは、Vouchers テーブルで Employees.OjbectID のインスタンスを検索し、それらを NULL に設定します。

于 2009-01-11T04:03:15.743 に答える