Какво е външния ключ
Външният ключ в Oracle е начин за свързване на множество таблици. Това е кръстосана връзка между таблиците.
- Външният ключ е колона или набор от колони, които се отнасят до първичния ключ или уникален ключ в същата таблица или друга таблица
- Стойностите на външния ключ се базират на стойности на данни и са чисто логическа конструкция, а не физически указатели
- Стойността на външния ключ трябва да съвпада със стойност на първичен ключ или уникален ключ или е нула.
Ограниченията на външния ключ се наричат ограничения за референтна цялост. Реферираната таблица се нарича родителска таблица, докато таблицата с външния ключ се нарича дъщерна таблица.
как да използвам външен ключ
Нека проверим с примера на 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 и това е първичният ключ в таблицата.
Сега не искаме никакви записи в таблицата EMP, където DEPT_NO не съвпада с DEPT_NO в колоната DEPT, тъй като не можем да имаме emp, чийто dept Number не съществува. Нека видим дали можем да направим това с текущата настройка
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 DELETE SET NULL
Да видим как работи
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
Така че при изтриване на редовете от родителската таблица, колоната с външния ключ на дъщерните редове се прави нула
Случай -3 Външен ключ, дефиниран с опция 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>
Така че при изтриване на редовете от родителската таблица, дъщерните редове също се изтриват
Промяна на външния ключ на таблицата
Можем да създадем и външен ключ в 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
Как да добавите първичен ключ в oracle:първичният ключ уникално идентифицира реда в таблицата. Как да добавите първичен ключ в oracle, как да махнете първичния ключ, как да създадете съставен ключ
изпуснете ограничението на външния ключ oracle
уникален ключ в oracle :Уникалният ключ налага уникален ключ в колоната в таблицата и помага бързо идентифицираме реда. Oracle създава уникалния индекс за ключа, ако няма наличен индекс
изтриване на заявка в oracle
https://en.wikipedia.org/wiki/Foreign_key