Proiectarea de baze de date

este reflexiv. Nu putem intra această relație declarativ (cu constrângerea PRIMARY KEY), deoarece Oracle? suportă numai modurile RESTRICT (implicit) și ON DELETE CASCADE. Prin urmare, dezvoltăm cel de-al treilea mod, pe DELETE NULLIFY, pe care o acceptă și alte sisteme DBMS relative. Rețineți că de fiecare dată când nu specificăm (sau nu putem specifica) constrângerile pentru a defini relațiile, trebuie să ne scriem propriul cod care introduce toate regulile.







Să luăm mai întâi o soluție evidentă și să vedem de ce nu funcționează. Un exemplu care ilustrează această soluție este prezentat mai jos. Trigger emp BDR nu a încărcat din cauza unei erori referitoare la masa mutant: nu se poate avea acces la masa care a cauzat declanșare la foc (în acest caz, tabela EMP).

CREATE TABLE emp (număr NUME (4) NU NULL

deptno NUMBER (4) NU NULL

CONSTRAINT emp pk CHEIE PRIMARĂ (empno));

INTRODUCEȚI LA VALOAREA ACTIVELOR (111, 10, Big Boss, Manager, NULL); INTRODUCEȚI ÎN ACESTE VALORI (123, 11, Little Guy, Janitor, 111);

CREAȚI SAU ÎNLOCAȚI TRIGGER emp bdr BEFOR DELETE ON emp

UPDATE emp SET-ul mgr = NULL WHERE mgr =: old.empno; END;

DELETE emp WHERE empno = 111;

/ * Apare următoarea eroare: EROARE la rândul 1:

ORA-04091: masa SCOTT.EMP mutantă, declanșarea / funcția poate să nu-l vadă ORA-06512: în rândul 2

ORA-04088: eroare în timpul executării declanșatorului SCOTT.EMP BDR * /

Care sunt cauzele erorii? Operatorul SET și operatorii care lucrează cu mai multe rânduri au o proprietate comună și destul de teoretică. SQL nu garantează ordinea procesării liniilor specificate într-un astfel de operator. Din aceasta rezultă că, dacă știți că mutates masă în timpul instrucțiunea SET, orice ssshka pe masa din declanșator poate fi administrat înainte sau după faptul gfoizoydet schimbare de masă. Deoarece ordinea în care se efectuează modificările, nu este garantată, nu este necesar ca de fiecare dată operatorii identice cu date identice, veți obține aceleași rezultate.

Cum puteți depăși această limitare și puteți realiza ceea ce veți face? Am văzut cum a fost încercată rezolvarea acestei probleme de către diverși

- de exemplu, folosind tabele în oglindă sau un proces server dedicat care așteaptă ca un semnal să efectueze o actualizare care duce la o eroare. Aceste soluții sunt foarte complexe și periculoase, așa că vă oferim două metode simple de ieșire din această situație.

Mai întâi, ia în considerare o metodă care este extrem de ineficientă și, prin urmare, nu este recomandată, dar funcționează. Așteptați până când se execută ștergerea și apoi scanați întreaga tabelă pentru prezența rândurilor în care coloana MGR conține o referință la un angajat inexistent. Dacă există astfel de linii, resetați valoarea coloanei MGR în ele. Cum să îl implementați, prezentat în cele de mai jos.







DROP TRIGGER emp bdr;

CREAȚI SAU ÎNLOCAȚI TRIGGER ÎNAINTE DUPĂ CUM SUNTEM DELETE LA BEGIN

Unde nu există (SELECT NULL

DE LA emp emp2 WHERE emp2.empno = emp.mgr);

DELETE emp WHERE empno = 111;

SELECT * FROM emp;

> 123 11 Litle Guy Janitor

În ciuda unor ineficiențe, această soluție are o caracteristică interesantă: elimină referințele eronate anterioare care ar putea apărea din cauza executării programului pentru mai multe ore (sau săptămâni) cu declanșare declanșată aleatoriu. La prima îndepărtarea oricărui angajat începe un declanșator care resetează valoarea coloana MGR corespunzătoare unui sef inexistent, pentru toți angajații, nu doar pentru cei sefi sunt eliminate în situația actuală.

Această auto-corectare a datelor, la prima vedere, poate părea foarte bună, dar implică consecințe nedorite. De fiecare dată când un angajat este eliminat, întregul tabel EMP este căutat pentru angajații care lucrează pentru un șef inexistent. Pentru un exemplu de tabel cu două linii, acest lucru nu este important, dar pentru un tabel cu câteva mii de rânduri, performanța va fi extrem de scăzută. Ar trebui să restricționăm cumva căutarea numai acelor linii care conțin referințe la seful la distanță, fără a crea o problemă cu tabela mutantă.

Ce alte metode pot fi utilizate pentru a rezolva această problemă? A doua metodă (de preferat) oferă un truc inteligent - salvați angajați de la distanță folosind un declanșator la nivel de rând și a pus angajații de căutare, care a fost șef al angajatului de la distanță pentru a declanșa AFTER. Pentru a stoca temporar angajații la distanță, trebuie să utilizați tabela globală PL / SQL.

Care este tabela globală PL / SQL? PL / SQL pachetele pot conține variabile globale. Acestea sunt declarate fie în pachet (dacă acestea trebuie să fie accesibile din exterior), fie în corpul pachetului, dar în afara tuturor procedurilor și funcțiilor. În acest din urmă caz, ele pot fi văzute numai din acest pachet. Variabilele ambelor tipuri sunt create pentru prima dată când pachetul este accesat (din orice motiv) și rămâne în memorie până când sesiunea Oracle întrerupe conexiunea. PL / SQL versiunea 2.3 vă permite să curățați masa, ci la orice nod, care utilizează Oracle versiunea 7.2 și mai puțin creșterea treptată în memorie pentru pachetele de variabile globale poate fi o problemă care trebuie să fie luate în considerare în proiectarea. Pe măsură ce o măsură a tabelului este șters, puteți atribui o tabelă goală de același tip.

Codul pentru implementarea soluției cu variabile globale de pachete este dat în exemplul B.1. Acest cod constă dintr-un pachet cu trei proceduri și trei declanșatoare în tabelul EMP, fiecare dintre acestea fiind declanșat de un eveniment diferit și solicită una dintre procedurile lotului. O variabilă pachet este o tabelă pentru EMPNO la distanță, iar cealaltă este un index pentru aceasta. Declanșatorul BEFORE DELETE al nivelului operatorului solicită pur și simplu o procedură care stabilește acest index la zero, adică Logic curăță masa. Declanșatorul BEFORE DELETE al nivelului rândului trece cheia primară (EMPNO) a înregistrării care urmează să fie ștearsă și este atașată la sfârșitul tabelului. Declanșatorul AFTER DELETE de la nivelul operatorului trece prin tabel și resetează coloana MGR pentru toți angajații al căror angajat la distanță era șeful.

Exemplul B.1 utilizează apeluri de procedură lot în interiorul declanșatorului, astfel încât variabilele globale de pachete să rămână locale la procedură. Aceeași tehnică poate fi pusă în aplicare la un cost mai mic, pe care tocmai ai nevoie pentru a pune variabilele pachet la nivel mondial în pachetul în sine (și nu în corpul pachetului) și manipulate direct de la declanșatoare. Așa cum probabil ați ghici (dacă citim restul cărții), preferăm o abordare exclusiv încapsulată.

Exemplul B. 1. Cum să evităm apariția tabelelor mutante prin amânarea acțiunii la nivelul operatorilor

DROP TRIGGER;

CREAȚI SAU ÎNLOCUIREA PACHETULUI pk emp mgr AS ASCULTARE număr limpede;

PROCEDURĂ adaugă mgr (p empno IN emp.empno% TYPE); PROCEDURA anulează raportul emps; END pk emp mgr, -







Articole similare

Trimiteți-le prietenilor: