2017-06-25 6 views
0

私は2つのテーブル、従業員とタスク(これは単に重要なものを列挙され、もちろん実際のSQLコードではありません)がありますので、作業テーブルにはいくつかのタスクが含まれてい2つの外部キー列をnullまたは両方ともOracleの他の表の一部の行を指すように強制する方法はありますか?

CREATE TABLE Employees (
    employee_id  NUMBER(6) NOT NULL, 
    is_boss   NUMBER(1) DEFAULT 0 NOT NULL, 
    name    VARCHAR2(32) NOT NULL, 

    CHECK (is_boss IN (0,1)), 
    UNIQUE (is_boss, employee_id) 
); 

CREATE TABLE Tasks (
    task_id   NUMBER(6) NOT NULL, 
    name    VARCHAR2(32) NOT NULL, 
    is_boss   NUMBER(1), 
    employee_id  NUMBER(6), 
    finish_date  DATE, 

    CHECK (is_boss IN (1)), 
    FOREIGN KEY (employee_id) REFERENCES Employees (employee_id), 
    FOREIGN KEY (is_boss) REFERENCES Employees (is_boss) 
); 

を。それらがテーブルに追加されるときには、名前とIDだけが必要です。そのため、他のフィールドはnullableです。ある時点では、すべてのタスクが「上司」によって確認されなければならないので、is_boss == 1とそれに続いてfinish_dateの従業員が配置されます。

これらのチェック制約と外部/ユニークキーは、タスクがis_bossemployee_idの両方で更新された場合にうまく機能します。従業員が上司でない場合、その従業員もいない場合はエラーをスローします。しかし、それらのいずれかがnullの場合、すべてが間違っています。だから私は何とかそれらの2つのフィールドがnullでないか両方のnullのいずれかになるようにデータベースをチェックするように強制します。実際には、3つのフィールド(finish_dateも)がすべてnullまたはすべてnullでないようにします。

おそらくトリガーはオプションですが、私のデータベースの教師は、別のより簡単な可能性がある場合、それらを使用することに非常に反対です。だから私の質問は、トリガなしでそれを強制する方法はありますか? DBMSはOracle 11gです。

ありがとうございます。

+1

Employeesテーブルの主キーがちょうど 'employee_id'であるべき、とタスクテーブルは' is_boss'列を必要としないかのように思え:あなたのタスクテーブルのようなものである必要があります。 –

+0

明らかに両方のテーブルにプライマリキーがあります。従業員の 'employee_id'とTasksの' task_id'ですが、私の質問には関係しませんでした。なぜなら、タスクの外来キーは従業員。そして、私は、タスクが通常の従業員ではなく "ボス"によって受け入れられたことを確認するために 'is_boss'カラムが必要です。 – tuptus

+0

「employee_id」と「is_boss」の関係が「Tasks」表内でEmployee表内の表と異なる場合を除き、「Tasks」表をEmployee表に結合することで、タスクに関連付けられた従業員が上司であることを確認できます。 'employee_id'だけで' boss'フラグをチェックします。 –

答えて

1

あなたは2つの外部キーを1つの外部キーに結合する必要があります。そうでなければ、彼らは自分が行っていると思っていることをしていないと思います。また、3つのフィールドがすべて設定されていること、または3つすべてがNULLであることを確認するには、チェック制約が必要です。

CREATE TABLE TASKS (
    TASK_ID   NUMBER(6) NOT NULL, 
    NAME    VARCHAR2(32) NOT NULL, 
    IS_BOSS   NUMBER(1), 
    EMPLOYEE_ID  NUMBER(6), 
    FINISH_DATE  DATE, 

    CONSTRAINT TASKS_CK1 
     CHECK (is_boss IN (1)), 
    CONSTRAINT TASKS_FK1 
     FOREIGN KEY (IS_BOSS, EMPLOYEE_ID) 
     REFERENCES EMPLOYEES (IS_BOSS, EMPLOYEE_ID), 
    CONSTRAINT TASKS_CK2 
     CHECK((IS_BOSS IS NULL AND 
       EMPLOYEE_ID IS NULL AND 
       FINISH_DATE IS NULL) 
      OR 
      (IS_BOSS IS NOT NULL AND 
       EMPLOYEE_ID IS NOT NULL AND 
       FINISH_DATE IS NOT NULL)) 
); 
+0

私の質問でコードを間違えました。実際のテーブルには、あなたが言ったような2つの列を持つ1つの外部キーがあるので、それは必要なように動作します。しかし、これらの小切手の制約については非常に感謝します。 – tuptus

関連する問題