Co to jest klucz obcy
Klucz obcy w Oracle to sposób na powiązanie wielu tabel. Jest to połączenie między tabelami.
- Klucz obcy to kolumna lub zestaw kolumn, który odnosi się do klucza podstawowego lub klucza unikalnego w tej samej lub innej tabeli
- Wartości klucza obcego są oparte na wartościach danych i są konstrukcją czysto logiczną, a nie fizycznymi wskaźnikami
- Wartość klucza obcego musi być zgodna z wartością klucza podstawowego lub unikalną wartością klucza lub ma wartość NULL.
Ograniczenia klucza obcego są nazywane ograniczeniami integralności referencyjnej. Tabela, do której się odwołuje, nazywana jest tabelą nadrzędną, podczas gdy tabela z kluczem obcym nazywana jest tabelą podrzędną.
jak używać klucza obcego
Sprawdźmy na przykładzie EMP i 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
Tabela EMP zawiera kolumnę DEPT_NO. Tabela DEPT zawiera również kolumnę DEPT_NO i jest to klucz podstawowy w tabeli.
Teraz nie chcemy żadnych wpisów w tabeli EMP, gdzie DEPT_NO nie pasuje do DEPT_NO w kolumnie DEPT, ponieważ nie możemy mieć emp, którego numer dept nie istnieje. Zobaczmy, czy możemy to zrobić z bieżącą konfiguracją
SQL> insert into emp values( 7790, 'TOM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, 50); 1 row created.
Ale to się udało i struktura spowodowała problem z integralnością danych
Aby uniknąć tego typu problemów z danymi, możemy wymusić ograniczenia klucza obcego w tabeli EMP.
Zobaczmy jeszcze raz
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 );
Teraz spróbujmy wpisać ten sam wiersz
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
Dzięki temu uniknięto wpisów złych danych.
To samo dotyczy scenariusza z Usuń z tabeli DEPT. Nie powinniśmy usuwać wierszy działu, w którym emp ma jakieś rekordy. Bez ograniczeń klucza obcego to się wydarzy i spowoduje złe dane. Ale w przypadku klucza obcego można tego uniknąć
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
Klauzule kluczy obcych w opcji usuwania
CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO") REFERENCES "DEPT" ("DEPTNO") ENABLE ON DELETE [CASCADE |SET NULL]
Przypadek 1: Klucz obcy zdefiniowany bez opcji ON DELETE
Nie będzie można usunąć rekordów z tabeli nadrzędnej, jeśli rekordy zostaną znalezione w tabeli podrzędnej
Sprawa -2 Klucz obcy zdefiniowany opcją ON DELETE SET NULL
Zobaczmy, jak to działa
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 więc po usunięciu wierszy z tabeli nadrzędnej kolumna klucza obcego wierszy podrzędnych jest pusta
Przypadek -3 Klucz obcy zdefiniowany opcją 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 więc po usunięciu wierszy z tabeli nadrzędnej usuwane są również wiersze podrzędne
Zmień klucz obcy tabeli
Możemy również utworzyć klucz obcy w Oracle po utworzeniu tabeli
alter table emp add CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO") REFERENCES "DEPT" ("DEPTNO") ;
Jak usunąć ograniczenie klucza obcego
SQL> alter table emp drop constraint "FK_DEPTNO"; Table altered.
Jak wyłączyć ograniczenie
SQL> alter table emp disable constraint "FK_DEPTNO"; Table altered.
Jak włączyć ograniczenie
SQL> alter table emp enable constraint "FK_DEPTNO"; Table altered. SQL>
Też czyta
Sprawdź ograniczenie w Oracle
Ograniczenie Not Null w Oracle
Jak dodać klucz podstawowy w Oracle :klucz podstawowy jednoznacznie identyfikuje wiersz w tabeli. Jak dodać klucz podstawowy w oracle, jak usunąć klucz podstawowy, jak utworzyć klucz złożony
upuść ograniczenie klucza obcego oracle
unikalny klucz w oracle :Unikalny klucz wymusza unikalność w kolumnie w tabeli i pomaga szybko identyfikujemy wiersz. Oracle tworzy unikalny indeks dla klucza, jeśli żaden indeks nie jest dostępny
usuń zapytanie w oracle
https://en.wikipedia.org/wiki/Foreign_key