sql >> データベース >  >> RDS >> Oracle

Oracleで外部キーを使用する方法

    外部キーとは

    Oracleの外部キーは、複数のテーブルを関連付ける方法です。これは、テーブル間のクロスリンクです。

    • 外部キーは、同じテーブルまたは別のテーブルの主キーまたは一意キーを参照する列または列のセットです
    • 外部キー値はデータ値に基づいており、物理的なポインターではなく、純粋に論理的な構成です。
    • 外部キー値は、主キー値または一意キー値と一致する必要があります。一致しない場合、nullになります。

    外部キー制約は、参照整合性制約と呼ばれます。参照されるテーブルは親テーブルと呼ばれ、外部キーを持つテーブルは子テーブルと呼ばれます。

    外部キーの使用方法

    EMPとDEPTの例で確認しましょう。

    SQL>CREATE TABLE "DEPT"
     ( "DEPTNO" NUMBER(2,0),
     "DNAME" VARCHAR2(14),
     "LOC" VARCHAR2(13),
     CONSTRAINT "PK_DEPT" PRIMARY KEY ("DEPTNO")
     )
     SQL>CREATE TABLE "EMP"
     ( "EMPNO" NUMBER(4,0),
     "ENAME" VARCHAR2(10),
     "JOB" VARCHAR2(9),
     "MGR" NUMBER(4,0),
     "HIREDATE" DATE,
     "SAL" NUMBER(7,2),
     "COMM" NUMBER(7,2),
     "DEPTNO" NUMBER(2,0),
     CONSTRAINT "PK_EMP" PRIMARY KEY ("EMPNO")
     );
     SQL> desc emp
     Name Null? Type
     
     EMPNO NOT NULL NUMBER(4)
     ENAME VARCHAR2(10)
     JOB VARCHAR2(9)
     MGR NUMBER(4)
     HIREDATE DATE
     SAL NUMBER(7,2)
     COMM NUMBER(7,2)
     DEPTNO NUMBER(2)
     SQL>
     SQL> desc dept
     Name Null? Type
     
     DEPTNO NOT NULL NUMBER(2)
     DNAME VARCHAR2(14)
     LOC VARCHAR2(13)
     SQL>
     insert into DEPT values(10, 'ACCOUNTING', 'NEW YORK');
     insert into dept values(20, 'RESEARCH', 'DALLAS');
     insert into dept values(30, 'RESEARCH', 'DELHI');
     insert into dept values(40, 'RESEARCH', 'MUMBAI');
     insert into emp values( 7698, 'Blake', 'MANAGER', 7839, to_date('1-5-2007','dd-mm-yyyy'), 2850, null, 10 );
     insert into emp values( 7782, 'Clark', 'MANAGER', 7839, to_date('9-6-2008','dd-mm-yyyy'), 2450, null, 10 );
     insert into emp values( 7788, 'Scott', 'ANALYST', 7566, to_date('9-6-2012','dd-mm-yyyy'), 3000, null, 20 );
     insert into emp values( 7789, 'TPM', 'ANALYST', 7566, to_date('9-6-2017','dd-mm-yyyy'), 3000, null, null );
     insert into emp values( 7560, 'T1OM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, 20 );
     insert into emp values( 7790, 'TOM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, null );
     SQL> select  from emp;
     EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
     
     7698 BLAKE MANAGER 7839 01-MAY-07 2850 10
     7782 CLARK MANAGER 7839 09-JUN-08 2450 10
     7788 SCOTT ANALYST 7566 09-JUN-12 3000 20
     7789 TPM ANALYST 7566 09-JUN-17 3000
     7790 TOM ANALYST 7567 09-JUL-17 4000
     7560 T1OM ANALYST 7567 09-JUL-17 4000 20

    EMPテーブルには、DEPT_NO列が含まれています。また、DEPTテーブルにはDEPT_NO列も含まれており、これはテーブルの主キーです。

    ここで、DEPT番号が存在しないempを使用できないため、DEPT_NOがDEPT列のDEPT_NOと一致しないテーブルEMPのエントリは必要ありません。現在のセットアップでこれを実行できるかどうかを見てみましょう

    SQL> insert into emp values( 7790, 'TOM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, 50);
     1 row created.

    しかし、これは成功し、構造がデータの整合性の問題を引き起こしました

    これらのタイプのデータの問題を回避するために、EMPテーブルに外部キー制約を適用できます。
    もう一度見てみましょう

    drop table emp;
     drop table dept;
     SQL>CREATE TABLE "DEPT"
     ( "DEPTNO" NUMBER(2,0),
     "DNAME" VARCHAR2(14),
     "LOC" VARCHAR2(13),
     CONSTRAINT "PK_DEPT" PRIMARY KEY ("DEPTNO")
     )
     SQL>CREATE TABLE "EMP"
     ( "EMPNO" NUMBER(4,0),
     "ENAME" VARCHAR2(10),
     "JOB" VARCHAR2(9),
     "MGR" NUMBER(4,0),
     "HIREDATE" DATE,
     "SAL" NUMBER(7,2),
     "COMM" NUMBER(7,2),
     "DEPTNO" NUMBER(2,0),
     CONSTRAINT "PK_EMP" PRIMARY KEY ("EMPNO"),
     CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO")
     REFERENCES "DEPT" ("DEPTNO") ENABLE
     );
     SQL> desc emp
     Name Null? Type
     
     EMPNO NOT NULL NUMBER(4)
     ENAME VARCHAR2(10)
     JOB VARCHAR2(9)
     MGR NUMBER(4)
     HIREDATE DATE
     SAL NUMBER(7,2)
     COMM NUMBER(7,2)
     DEPTNO NUMBER(2)
     SQL>
     SQL> desc dept
     Name Null? Type
     DEPTNO NOT NULL NUMBER(2)
     DNAME VARCHAR2(14)
     LOC VARCHAR2(13)
     SQL>
     insert into DEPT values(10, 'ACCOUNTING', 'NEW YORK');
     insert into dept values(20, 'RESEARCH', 'DALLAS');
     insert into dept values(30, 'RESEARCH', 'DELHI');
     insert into dept values(40, 'RESEARCH', 'MUMBAI');
     insert into emp values( 7698, 'Blake', 'MANAGER', 7839, to_date('1-5-2007','dd-mm-yyyy'), 2850, null, 10 );
     insert into emp values( 7782, 'Clark', 'MANAGER', 7839, to_date('9-6-2008','dd-mm-yyyy'), 2450, null, 10 );
     insert into emp values( 7788, 'Scott', 'ANALYST', 7566, to_date('9-6-2012','dd-mm-yyyy'), 3000, null, 20 );
     insert into emp values( 7789, 'TPM', 'ANALYST', 7566, to_date('9-6-2017','dd-mm-yyyy'), 3000, null, null );
     insert into emp values( 7560, 'T1OM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, 20 );
     insert into emp values( 7790, 'TOM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, null );

    それでは、同じ行を入力してみましょう

    SQL> insert into emp values( 7790, 'TOM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, 50);
     insert into emp values( 7790, 'TOM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, 50)
     *
     ERROR at line 1:
     ORA-02291: integrity constraint (SCOTT.FK_DEPTNO) violated - parent key
     not found

    そのため、不正なデータの入力を回避しました。

    DEPTテーブルから削除するシナリオも同じです。 empにいくつかのレコードがある部門の行を削除するべきではありません。外部キーの制約がないと、それが発生し、不正なデータが発生します。ただし、外部キーを使用すると、これは回避されます

    SQL>  delete from dept where deptno=10;
      delete from dept where deptno=10
     *
     ERROR at line 1:
     ORA-02292: integrity constraint (SCOTT.FK_DEPTNO) violated - child record found

    削除オプションの外部キー句

    CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO")
     REFERENCES "DEPT" ("DEPTNO") ENABLE
     ON DELETE [CASCADE |SET NULL]

    ケース1: ON DELETEオプションなしで定義された外部キー
    レコードが子テーブルで見つかった場合、親テーブルからレコードを削除することはできません

    ケース-2 ON DELETESETNULLオプションで定義された外部キー
    どのように機能するか見てみましょう

    SQL> alter table emp add CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO") REFERENCES "DEPT" ("DEPTNO") ON DELETE SET NULL;
     Table altered.
     SQL> select * from emp where empno=7698;
       EMPNO     DEPTNO
      -------  ----      
       7698      10
     SQL>  delete from dept where deptno=10;
     1 row deleted.
     SQL> commit;
     Commit complete.
     SQL> select * from emp where empno=7698;
       EMPNO     DEPTNO
      -------  ----      
       7698 

    したがって、親テーブルから行を削除すると、子行の外部キー列がnullになります

    ケース-3 ONDELETECASCADEオプションで定義された外部キー

    SQL> alter table emp add CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO") REFERENCES "DEPT" ("DEPTNO") ON DELETE cascade;
     Table altered.
     SQL> delete from dept where deptno=10;
     1 row deleted.
     SQL> commit;
     Commit complete.
     SQL> select * from emp where  deptno=10; ;
     no rows selected
     SQL>

    したがって、親テーブルから行を削除すると、子行も削除されます

    テーブル外部キーの変更

    テーブルの作成後にOracleで外部キーを作成することもできます

     alter table emp add CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO") REFERENCES "DEPT" ("DEPTNO") ; 

    外部キー制約を削除する方法

    SQL> alter table emp drop constraint "FK_DEPTNO";
     Table altered.

    制約を無効にする方法

    SQL> alter table emp  disable   constraint "FK_DEPTNO";
     Table altered.

    制約を有効にする方法

    SQL>  alter table emp   enable  constraint "FK_DEPTNO";
     Table altered.
     SQL>

    また読む
    Oracleで制約を確認します
    OracleでNULL制約ではありません
    Oracleで主キーを追加する方法:主キーはテーブル内の行を一意に識別します。 Oracleで主キーを追加する方法、主キーを削除する方法、複合キーを作成する方法
    外部キー制約を削除するOracle
    Oracleで一意キー:一意キーは、テーブルの列に一意キーを適用し、役立ちます行をすばやく識別します。使用可能なインデックスがない場合、Oracleはキーの一意のインデックスを作成します
    oracleでクエリを削除します
    https://en.wikipedia.org/wiki/Foreign_key


    1. 最後に挿入された行から値を取得するにはどうすればよいですか?

    2. OracleでさまざまなタイプのPL/SQLコレクションを使用する目的

    3. MySQLテーブルにインデックスを追加するにはどうすればよいですか?

    4. OracleLISTAGG関数の使用方法