Co je cizí klíč
Cizí klíč v Oracle je způsob, jak spojit více tabulek. Jde o křížové propojení mezi tabulkami.
- Cizí klíč je sloupec nebo sada sloupců, která odkazuje na primární klíč nebo jedinečný klíč ve stejné nebo jiné tabulce
- Hodnoty cizích klíčů jsou založeny na hodnotách dat a jsou čistě logickou konstrukcí, nikoli fyzickými ukazateli
- Hodnota cizího klíče musí odpovídat hodnotě primárního klíče nebo jedinečné hodnotě klíče, jinak je nulová.
Omezení cizího klíče se nazývají omezení referenční integrity. Odkazovaná tabulka se nazývá nadřazená tabulka, zatímco tabulka s cizím klíčem se nazývá podřízená tabulka.
jak používat cizí klíč
Podívejme se na příklad EMP a 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
Tabulka EMP obsahuje sloupec DEPT_NO. a DEPT Table obsahuje také sloupec DEPT_NO a je to primární klíč v tabulce.
Nyní nechceme žádné položky v tabulce EMP, kde DEPT_NO neodpovídá DEPT_NO ve sloupci DEPT, protože nemůžeme mít EMP, jehož číslo oddělení neexistuje. Podívejme se, zda to dokážeme s aktuálním nastavením
SQL> insert into emp values( 7790, 'TOM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, 50); 1 row created.
To se však podařilo a struktura způsobila problém s integritou dat
Abychom se vyhnuli těmto typům problémů s daty, můžeme u tabulky EMP vynutit omezení cizího klíče.
Podívejme se znovu
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 );
Nyní zkusme zadat stejný řádek
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
Vyhnulo se tedy zadávání špatných dat.
Stejný je scénář s Delete from the DEPT table. Neměli bychom mazat řádky oddělení, kde má emp nějaké záznamy. Bez omezení cizího klíče se to stane a způsobí špatná data. Ale s cizím klíčem se tomu vyhnete
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
Zahraniční klíčové klauzule u možnosti smazání
CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO") REFERENCES "DEPT" ("DEPTNO") ENABLE ON DELETE [CASCADE |SET NULL]
Případ 1: Cizí klíč definovaný bez možnosti ON DELETE
Nebudete moci odstranit záznamy z nadřazené tabulky, pokud jsou záznamy nalezeny v podřízené tabulce
Případ -2 Cizí klíč definovaný pomocí možnosti ON DELETE SET NULL
Podívejte se, jak to funguje
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
Takže při smazání řádků z nadřazené tabulky se sloupec cizího klíče podřízených řádků změní na null
Případ -3 Cizí klíč definovaný pomocí možnosti ON DELETE CASCADE
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>
Takže při smazání řádků z nadřazené tabulky se odstraní i podřízené řádky
Změnit cizí klíč tabulky
Můžeme také vytvořit cizí klíč v Oracle po vytvoření tabulky
alter table emp add CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO") REFERENCES "DEPT" ("DEPTNO") ;
Jak zrušit omezení cizího klíče
SQL> alter table emp drop constraint "FK_DEPTNO"; Table altered.
Jak deaktivovat omezení
SQL> alter table emp disable constraint "FK_DEPTNO"; Table altered.
Jak povolit omezení
SQL> alter table emp enable constraint "FK_DEPTNO"; Table altered. SQL>
Také čte
Zkontrolujte omezení v Oracle
Není to nulové omezení v Oracle
Jak přidat primární klíč v oracle:primární klíč jednoznačně identifikuje řádek v tabulce. Jak přidat primární klíč do oracle, jak zrušit primární klíč, jak vytvořit složený klíč
zrušit omezení cizího klíče oracle
jedinečný klíč v oracle :Jedinečný klíč vynucuje jedinečný ve sloupci v tabulce a pomáhá rychle identifikujeme řádek. Oracle vytvoří jedinečný index pro klíč, pokud není k dispozici žádný index
smazat dotaz v oracle
https://en.wikipedia.org/wiki/Foreign_key