Oracle
 sql >> Datenbank >  >> RDS >> Oracle

So verwenden Sie Fremdschlüssel in Oracle

Was ist ein Fremdschlüssel

Fremdschlüssel in Oracle sind eine Möglichkeit, mehrere Tabellen miteinander in Beziehung zu setzen. Es ist eine Vernetzung zwischen den Tabellen.

  • Ein Fremdschlüssel ist eine Spalte oder eine Gruppe von Spalten, die sich auf den Primärschlüssel oder eindeutigen Schlüssel in derselben Tabelle oder einer anderen Tabelle bezieht
  • Fremdschlüsselwerte basieren auf Datenwerten und sind rein logische Konstrukte, keine physischen Zeiger
  • Der Fremdschlüsselwert muss mit einem Primärschlüsselwert oder einem eindeutigen Schlüsselwert übereinstimmen oder er ist null.

Fremdschlüsseleinschränkungen werden als Einschränkungen der referenziellen Integrität bezeichnet. Die referenzierte Tabelle wird Elterntabelle genannt, während die Tabelle mit dem Fremdschlüssel Kindtabelle genannt wird.

Wie man Fremdschlüssel verwendet

Sehen wir uns das Beispiel von EMP und DEPT an.

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

Die EMP-Tabelle enthält die Spalte DEPT_NO. und die DEPT-Tabelle enthält auch die DEPT_NO-Spalte und ist der Primärschlüssel für die Tabelle.

Jetzt wollen wir keine Einträge in der Tabelle EMP, wo DEPT_NO nicht mit DEPT_NO in der Spalte DEPT übereinstimmt, da wir keinen Angestellten haben können, dessen Abteilungsnummer nicht existiert. Mal sehen, ob wir das mit dem aktuellen Setup machen können

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

Dies war jedoch erfolgreich und die Struktur hat ein Datenintegritätsproblem verursacht

Um diese Art von Datenproblemen zu vermeiden, können wir die Fremdschlüsseleinschränkungen für die EMP-Tabelle erzwingen.
Sehen wir noch einmal

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

Versuchen wir nun, dieselbe Zeile einzugeben

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

So hat es die Einträge der schlechten Daten vermieden.

Dasselbe gilt für das Szenario mit Löschen aus der DEPT-Tabelle. Wir sollten nicht die Zeilen der Abteilung löschen, in denen emp einige Datensätze hat. Ohne Fremdschlüsselbeschränkungen wird es passieren und schlechte Daten verursachen. Aber mit dem Fremdschlüssel wird dies vermieden

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

Fremdschlüsselklauseln bei Löschoption

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

Fall 1: Ohne ON DELETE-Option definierter Fremdschlüssel
Sie können keine Datensätze aus der übergeordneten Tabelle löschen, wenn Datensätze in der untergeordneten Tabelle gefunden werden

Fall -2 Fremdschlüssel definiert mit der Option ON DELETE SET NULL
Mal sehen, wie es funktioniert

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 

Beim Löschen der Zeilen aus der übergeordneten Tabelle wird die Fremdschlüsselspalte der untergeordneten Zeilen auf null gesetzt

Fall -3 Mit der Option ON DELETE CASCADE definierter Fremdschlüssel

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>

Beim Löschen der Zeilen aus der übergeordneten Tabelle werden also auch die untergeordneten Zeilen gelöscht

Tabellenfremdschlüssel ändern

Wir können auch nach der Tabellenerstellung einen Fremdschlüssel in Oracle erstellen

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

So löschen Sie die Fremdschlüsselbeschränkung

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

So deaktivieren Sie die Einschränkung

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

So aktivieren Sie die Einschränkung

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

Liest auch
Überprüfen Sie die Einschränkung in Oracle
Keine Null-Einschränkung in Oracle
So fügen Sie den Primärschlüssel in Oracle hinzu:Der Primärschlüssel identifiziert die Zeile in der Tabelle eindeutig. So fügen Sie Primärschlüssel in Oracle hinzu, wie Sie Primärschlüssel löschen, wie Sie einen zusammengesetzten Schlüssel erstellen wir identifizieren die Reihe schnell. Oracle erstellt den eindeutigen Index für den Schlüssel, wenn kein Index verfügbar ist
Abfrage in Oracle löschen
https://en.wikipedia.org/wiki/Foreign_key