sql >> Databáze >  >> RDS >> Oracle

Jak používat cizí klíč v oracle

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


  1. Obnovení hlavní databáze SQL Server

  2. Práce s daty v PostgreSQL

  3. Časté chyby DBA v MS SQL Server

  4. Jak zdravý je váš SQL Server? Proaktivní monitorování databáze je kritické