Oracle
 sql >> Database >  >> RDS >> Oracle

Come usare la chiave esterna in Oracle

Cos'è la chiave esterna

La chiave esterna in Oracle è un modo per mettere in relazione più tabelle. È un collegamento incrociato tra le tabelle.

  • Una chiave esterna è una colonna o un insieme di colonne che fa riferimento alla chiave primaria o alla chiave univoca nella stessa tabella o in un'altra tabella
  • I valori delle chiavi esterne si basano sui valori dei dati e sono costrutti puramente logici, non puntatori fisici
  • Il valore della chiave esterna deve corrispondere a un valore di chiave primaria o un valore di chiave univoco oppure è nullo.

I vincoli di chiave esterna sono chiamati vincoli di integrità referenziale. La tabella di riferimento è chiamata tabella padre mentre la tabella con la chiave esterna è chiamata tabella figlio.

come usare la chiave esterna

Verifichiamo con l'esempio di EMP e 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

La tabella EMP contiene la colonna DEPT_NO. e DEPT Table contiene anche la colonna DEPT_NO ed è la chiave primaria della tabella.

Ora non vogliamo voci nella tabella EMP in cui DEPT_NO non corrisponde a DEPT_NO nella colonna DEPT poiché non possiamo avere un emp il cui numero di reparto non esiste. Vediamo se riusciamo a farlo con la configurazione corrente

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

Ma questo è riuscito e la struttura ha causato un problema di integrità dei dati

Per evitare questo tipo di problemi con i dati, possiamo applicare i vincoli della chiave esterna alla tabella EMP.
Ci rivediamo

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 );

Ora proviamo a inserire la stessa riga

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

Quindi ha evitato le voci dei dati errati.

Lo stesso è lo scenario con Elimina dalla tabella DEPT. Non dovremmo eliminare le righe del reparto in cui emp ha alcuni record. Senza vincoli di chiave esterna, accadrà e causerà dati errati. Ma con la chiave esterna, questo sarà evitato

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

Clausole chiave esterne sull'opzione di eliminazione

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

Caso 1: Chiave esterna definita senza l'opzione ON DELETE
Non sarai in grado di eliminare i record dalla tabella padre se i record vengono trovati nella tabella figlio

Caso -2 Chiave esterna definita con l'opzione ON DELETE SET NULL
Vediamo come funziona

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 

Quindi, eliminando le righe dalla tabella padre, la colonna della chiave esterna delle righe figlio viene resa nulla

Caso -3 Chiave esterna definita con l'opzione 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>

Quindi, eliminando le righe dalla tabella padre, vengono eliminate anche le righe figlio

Alterare la chiave esterna della tabella

Possiamo creare una chiave esterna in Oracle anche dopo la creazione della tabella

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

Come eliminare il vincolo di chiave esterna

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

Come disabilitare il vincolo

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

Come abilitare il vincolo

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

Legge anche
Verifica vincolo in Oracle
vincolo Not Null in Oracle
Come aggiungere la chiave primaria in Oracle:la chiave primaria identifica in modo univoco la riga nella tabella. Come aggiungere la chiave primaria in Oracle, come eliminare la chiave primaria, come creare una chiave composita
rilascia il vincolo della chiave esterna oracle
Chiave univoca in Oracle:la chiave univoca impone l'univocità nella colonna della tabella e aiuta identifichiamo rapidamente la riga. Oracle crea l'indice univoco per la chiave se non è disponibile alcun indice
elimina la query in Oracle
https://en.wikipedia.org/wiki/Foreign_key