Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Como usar chave estrangeira no oracle

O que é chave estrangeira


Chave estrangeira no Oracle é uma forma de relacionar várias tabelas. É uma ligação cruzada entre as tabelas.
  • Uma chave estrangeira é uma coluna ou conjunto de colunas que se refere à chave primária ou chave única na mesma tabela ou em outra tabela
  • Os valores de chave estrangeira são baseados em valores de dados e são construções puramente lógicas e não ponteiros físicos
  • O valor da chave estrangeira deve corresponder a um valor de chave primária ou a um valor de chave exclusivo ou é nulo.

As restrições de chave estrangeira são chamadas de restrições de integridade referencial. A tabela referenciada é chamada de tabela pai, enquanto a tabela com a chave estrangeira é chamada de tabela filho.

como usar a chave estrangeira


Vamos verificar com o exemplo de 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

A tabela EMP contém a coluna DEPT_NO. e DEPT Table contém a coluna DEPT_NO também e é a chave primária na tabela.

Agora, não queremos nenhuma entrada na tabela EMP onde DEPT_NO não corresponda a DEPT_NO na coluna DEPT, pois não podemos ter um emp cujo número dept não exista. Vamos ver se podemos fazer isso com a configuração atual
SQL> insert into emp values( 7790, 'TOM', 'ANALYST', 7567, to_date('9-7-2017','dd-mm-yyyy'), 4000, null, 50);
 1 row created.

Mas isso deu certo e a estrutura causou um problema de integridade de dados

Para evitar esses tipos de problemas de dados, podemos aplicar as restrições de chave estrangeira na tabela EMP.
Vamos ver novamente
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 );

Agora vamos tentar entrar na mesma linha
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

Assim evitou as entradas dos dados ruins.

O mesmo é o cenário com Excluir da tabela DEPT. Não devemos excluir as linhas do dept onde emp tem alguns registros. Sem restrições de chave estrangeira, isso acontecerá e causará dados incorretos. Mas com chave estrangeira, isso será evitado
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

Cláusulas de chave estrangeira na opção de exclusão

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

Caso 1: Chave estrangeira definida sem a opção ON DELETE
Você não poderá excluir registros da tabela pai se os registros forem encontrados na tabela filho

Caso -2 Chave estrangeira definida com a opção ON DELETE SET NULL
Vamos ver como funciona
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 

Portanto, ao excluir as linhas da tabela pai, a coluna de chave estrangeira das linhas filhas é tornada nula

Caso -3 Chave estrangeira definida com a opção 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>

Portanto, ao excluir as linhas da tabela pai, as linhas filhas também são excluídas

Alterar chave estrangeira da tabela


Podemos criar uma chave estrangeira no Oracle após a criação da tabela também
 alter table emp add CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO") REFERENCES "DEPT" ("DEPTNO") ; 

Como eliminar a restrição de chave estrangeira

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

Como desativar a restrição

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

Como habilitar a restrição

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

Também lê
Verificar restrição no Oracle
Restrição não nula no Oracle
Como adicionar chave primária no oracle:chave primária identifica exclusivamente a linha na tabela. Como adicionar chave primária no oracle, como descartar a chave primária, como criar uma chave composta
descartar a restrição de chave estrangeira oracle
chave única no oracle :A chave exclusiva impõe a exclusividade na coluna na tabela e ajuda identificamos a linha rapidamente. O Oracle cria o índice exclusivo para a chave se nenhum índice estiver disponível
excluir consulta no oracle
https://en.wikipedia.org/wiki/Foreign_key