他の 2 つのテーブルを参照する 3 番目のテーブルに挿入するときに、2 つのテーブル間の制約を確認するにはどうすればよいですか?
-
20-08-2019 - |
質問
次のスキーマ例を考えてみましょう。
Customer ( int CustomerId pk, .... )
Employee ( int EmployeeId pk,
int CustomerId references Customer.CustomerId, .... )
WorkItem ( int WorkItemId pk,
int CustomerId references Customer.CustomerId,
null int EmployeeId references Employee.EmployeeId, .... )
基本的に、次の 3 つのテーブルがあります。
- 主キーと追加の列を持つ顧客テーブル
- 主キーを持つ従業員テーブル、顧客の従業員を表す顧客テーブルの主キーへの外部キー制約参照。
- 作業項目テーブル。顧客のために行われた作業と、作業が行われた特定の従業員に関する情報も保存されます。
私の質問は。新しい作業項目を追加するときに、従業員が実際に顧客に関連付けられているかどうかをデータベース レベルでテストするにはどうすればよいですか。
たとえば、Scott (従業員) が Microsoft (顧客) で働いており、Jeff (従業員) が StackOverflow (顧客) で働いている場合、顧客 = Microsoft、従業員 = Jeff として、誰かがデータベースに作業項目を追加できないようにするにはどうすればよいですか。どちらが意味がありませんか?
チェック制約や外部キーを使用してそれを実行できますか、それとも手動でテストするためのトリガーが必要ですか?
SQL Server 2008 を使用していることを言及しておきます。
アップデート: WorkItem.EmployeeId は null になる可能性があることを付け加えておきます。
ありがとう、エギル。
解決
複合列(CustomerIdの、社員)の外部キーが動作しないでしょうか?
ALTER TABLE WorkItem
ADD CONSTRAINT FK_Customer_Employee FOREIGN KEY (CustomerId, EmployeeId)
REFERENCES Employee (CustomerId, EmployeeId);
他のヒント
あなたはこれらのテーブルにまたがると、個々のテーブルの集合的な制約を強制する「SCHEMABINDING WITH」ビューを作成することによって、これを行うことができるかもしれません。
なぜあなたは、社員がnull int型作業項目になりたいですか?たぶん、あなたはその特定の風変わりを避けるために、別のテーブルを追加する必要があります。私が一番簡単な方法を見ることができるものから、それはあなたが望むものである場合にはcustomerIdに多分独特のworkItemに社員にユニーク制約を追加し、することです。
多くのテーブルにまたがる制約を追加するために、より一般的な方法は、常に空でなければなりませんビューを定義し、それが空であるという制約を追加することです。
ここで何をモデル化しようとしているのでしょうか?
あなたは請負代理店などで、顧客に (一定期間) 割り当てられる多数の請負業者を抱えています。
実際には、他の会社の従業員に関する情報を保存していることになります (たとえば、給与計算サービスをアウトソーシングして提供している可能性があります)。
(1) の場合は、次の点に問題があるようです。 Employee
テーブル。特に、Scott と MS の契約が終了し、他の人と契約した場合、履歴データを保持できなくなります。 CustomerId
. 。これにより、すべてのものも無効になります WorkItem
s.代わりに、次のような 4 番目のテーブルを用意する必要があります。 CustomerEmployee
それを保管するために。それから WorkItem
そのテーブルを参照する必要があります。
ケース (2) の場合、Employee の主キーは実際には次のようにする必要があります。 CustomerId
, EmployeeId
. 。2 人の顧客が同じ従業員 ID 番号を持つ可能性があります。そうすれば Kieron の外部キーが機能します。
私は最近、似たような状況に渡す、スキーマを考えてみます。 表製品(FK id_cia会社、id_groupのPKへの)表会社(id_cia PK)テーブルproduct_group(FKは、id_productのPK、id_used_by_the_clientのヌルをproduct_groupするid_group)
規則:データベースは、企業の各製品の一つだけid_used_by_the_clientを許可する必要がありますが、提出され、これはnullにすることができます。例:
会社に挿入し(1)=許可
会社に挿入します(2)=許可
product_group挿入(1,1)=
許さ(1,2)product_group挿入=許可
(2,3)product_group挿入=許可
製品値(1、1、NULL)=許可
に挿入製品値(1、2、NULL)=許可
に挿入製品値への挿入(1、3、1)=
許さ製品値への挿入(1、4、1)= 1 id_used_by_the_clientが存在既に会社1に属するグループ1に、許可されていない=
製品値への挿入(2、4、1)= 1 id_used_by_the_clientが存在既に会社1に属するグループ2に、許可されていない=
製品値への挿入(3、4、1)= 1ないid_used_by_the_clientがない会社2に属するグループ3に、許可=
私はこの整合性を制御するためにトリガーを使用することを決定します。
どちらか:
- EmployeeID 列を従業員の主キー (場合によっては自動 ID) にし、従業員 ID と顧客 ID を WorkItem に保存する代わりに、WorkItem レコードに外部キーとして EmployeeID を保存します。Employee テーブルを介して Customer テーブルに結合することで、WorkItem の顧客の詳細を取得できます。
または:
- WorkItem の EmployeeID 列と CustomerID 列を Employee への複合外部キーにします。
個人的には最初のアプローチを好みます。