care este diferența dintre triggere, aserțiuni și verificări (în baza de date) (Programare, Sql, Bază De Date, Declanșează, Aserțiuni)

Am1rr3zA a intrebat.
a intrebat.

Poate cineva să explice (sau să sugereze un site sau o lucrare) care este diferența exactă între triggers, assertions și checks, de asemenea să descrie unde ar trebui să le folosesc?

EDIT: Mă refer în baza de date, nu în alte sisteme sau limbaje de programare.

Comentarii

5 răspunsuri
jellomonkey

Declanșează – un declanșator este o bucată de SQL care se execută înainte sau după o actualizare, inserție sau ștergere într-o bază de date. Un exemplu de declanșator în limba engleză simplă ar putea fi ceva de genul: înainte de a actualiza o înregistrare a unui client, salvați o copie a înregistrării curente. Ceea ce ar arăta ceva de genul:

CREATE TRIGGER triggerName
AFTER UPDATE
    INSERT INTO CustomerLog (blah, blah, blah)
    SELECT blah, blah, blah FROM deleted

Diferența dintre aserțiuni și verificări este puțin mai neclară, multe baze de date nici măcar nu acceptă aserțiunile.

Restricție de verificare – O verificare este un fragment de SQL care se asigură că o condiție este îndeplinită înainte de a se putea acționa asupra unei înregistrări. În termeni simpli, aceasta ar fi ceva de genul: Toți clienții trebuie să aibă un sold de cel puțin 100 de dolari în cont. Ceea ce ar arăta ceva de genul:

ALTER TABLE accounts 
ADD CONSTRAINT CK_minimumBalance
CHECK (balance >= 100)

Orice încercare de a insera o valoare în coloana de sold mai mică de 100 ar genera o eroare.

Afirmații – O aserțiune este o bucată de SQL care se asigură că o condiție este îndeplinită sau că nu se mai efectuează o acțiune asupra unei anumite rubrici. obiect al bazei de date. Aceasta poate însemna blocarea întregului tabel sau chiar a întregii baze de date.

Pentru ca lucrurile să fie și mai confuze, un declanșator poate fi utilizat pentru a impune o constrângere de verificare și, în unele baze de date, poate înlocui o afirmație (permițându-vă să executați cod care nu are legătură cu tabelul modificat). O greșeală frecventă pentru începători este aceea de a utiliza o constrângere de verificare atunci când este necesar un trigger sau un trigger atunci când este necesară o constrângere de verificare.

Un exemplu: Toți clienții noi care deschid un cont trebuie să aibă un sold de 100 de dolari; cu toate acestea, odată ce contul este deschis, soldul lor poate scădea sub această sumă. În acest caz, trebuie să utilizați un declanșator, deoarece doriți ca această condiție să fie evaluată numai atunci când se introduce o nouă înregistrare.

Erwin Smout

În standardul SQL, atât ASSERȚIUNILE, cât și CONSTANȚELE DE VERIFICARE sunt ceea ce teoria relațională numește „constrângeri” : reguli pe care datele conținute efectiv în baza de date trebuie să le respecte.

Diferența dintre cele două constă în faptul că CHECK CONSTRAINTS sunt, într-un anumit sens, mult mai „simple”: sunt reguli care se referă la un singur rând, în timp ce ASSERTION-urile pot implica orice număr de alte tabele sau orice număr de alte rânduri din aceeași tabelă. Acest lucru face, în mod evident, ca pentru constructorii SGBD-urilor să fie (mult!) mai complex să le susțină, iar acesta este, la rândul său, motivul pentru care nu o fac: pur și simplu nu știu cum să o facă.

TRIGGER-urile sunt bucăți de cod executabil care pot fi declarate SGBD-ului că ar trebui să fie executate de fiecare dată când un anumit tip de operațiune de actualizare (inserare/eliminare/ actualizare) se efectuează pe un anumit tabel. Deoarece declanșatoarele pot ridica excepții, ele sunt un MEDIU de implementare a aceluiași lucru ca și o ASSERȚIE. Cu toate acestea, cu declanșatoarele, tot programatorul este cel care trebuie să facă toată codificarea și să nu facă nicio greșeală.

EDITARE

Comentariile lui Onedaywhen referitoare la ASSERTION/CHECK cnstr. sunt corecte. Diferența este mult mai subtilă (ȘI confuză). Standardul permite, într-adevăr, subinterogări în constrângerile CHECK. (Totuși, majoritatea produselor nu o acceptă, așa că afirmația mea „se referă la un singur rând” este adevărată pentru majoritatea produselor SQL, dar nu și pentru standard). Așadar, mai există o diferență ? Da, încă mai există. Chiar mai multe decât una.

Primul caz : TABLE MEN (ID:INTEGER) și TABLE WOMEN(ID:INTEGER). Acum imaginați-vă o regulă conform căreia „nicio valoare ID nu poate apărea atât în tabelul MEN, cât și în tabelul WOMEN”. Aceasta este o singură regulă. Intenția ASSERTION este tocmai aceea ca proiectantul bazei de date să enunțe această regulă unică [și să termine cu ea], iar SGBD să știe cum să se ocupe de aceasta [în mod eficient, desigur] și cum să aplice această regulă, indiferent de actualizarea particulară care se face în baza de date. În exemplu, SGBD ar ști că trebuie să verifice această regulă la INSERT INTO MEN și la INSERT INTO WOMEN, dar nu și la DELETE FROM MEN/WOMEN sau la INSERT INTO <anyothertable>.

Dar SGBD-urile nu sunt suficient de inteligente pentru a face toate acestea. Deci, ce trebuie făcut? Proiectantul bazei de date trebuie să adauge DOUĂ constrângeri CHECK la baza de date, una la tabelul MEN (verificând ID-urile MEN nou introduse în tabelul WOMEN) și una la tabelul WOMAN (verificând invers). Aceasta este prima diferență: o regulă, o ASERȚIUNE, DOUĂ Constrângeri CHECK. Constrângerile CHECK reprezintă un nivel de abstractizare mai scăzut decât ASSERTION-urile, deoarece acestea necesită ca proiectantul să se gândească mai mult la (a) toate tipurile de actualizare care ar putea duce la încălcarea ASSERTION-ului său și (b) ce verificare specială ar trebui efectuată pentru oricare dintre „tipurile de actualizare” specifice pe care le-a găsit la (a). (Deși nu-mi place foarte mult să fac declarații „absolute” cu privire la ceea ce este încă „CE” și ceea ce este „CUM”, aș rezuma că constrângerile CHECK necesită mai multă gândire „CUM” (procedurală) din partea proiectantului bazei de date, în timp ce ASSERTION-urile îi permit proiectantului bazei de date să se concentreze exclusiv pe „CE” (declarativ)).

Al doilea caz (deși nu sunt pe deplin sigur de acest lucru – așa că luați-o cu un grăunte de sare) : doar regula RI obișnuită. Bineînțeles că sunteți obișnuiți să specificați acest lucru folosind o anumită clauză REFERENCES. Dar imaginați-vă că o clauză REFERENCES nu ar fi disponibilă. O regulă de genul „Fiecare comandă trebuie să fie plasată de un CLIENT cunoscut” este de fapt doar atât, o regulă, deci : o singură ASSERȚIE. Cu toate acestea, știm cu toții că o astfel de regulă poate fi întotdeauna încălcată în două moduri: inserarea unei COMENZI (în acest exemplu) și ștergerea unui CLIENT. Acum, în concordanță cu exemplul de mai sus MAN/WOMEN, dacă am dori să implementăm această singură regulă/ASERȚIUNE folosind constrângeri CHECK, atunci ar trebui să scriem o constrângere CHECK care să verifice existența CLIENTULUI la inserțiile în ORDER, dar ce constrângere CHECK am putea scrie care să facă tot ceea ce este necesar la ștergerea din CUSTOMER? Din câte îmi dau seama, acestea pur și simplu nu sunt concepute în acest scop. Aceasta este cea de-a doua diferență: constrângerile CHECK sunt legate exclusiv de INSERTĂRI, în timp ce ASSERTIONS pot defini reguli care vor fi verificate și la ȘTERGERI.

Al treilea caz: Imaginați-vă un tabel COMPOS (componentID:… percentage:INTEGER) și o regulă conform căreia „suma tuturor procentelor trebuie să fie în orice moment egală cu 100”. Aceasta este o singură regulă, iar o ASSERTION este capabilă să specifice acest lucru. Dar încercați să vă imaginați cum ați putea aplica o astfel de regulă cu constrângeri CHECK … Dacă aveți un tabel valid cu, să zicem, trei rânduri care nu sunt egale cu zero și care însumează o sută, cum ați putea aplica o modificare la acest tabel care ar putea supraviețui constrângerii CHECK? Nu puteți șterge sau actualiza (micșora) niciun rând fără a fi nevoit să adăugați alte rânduri de înlocuire sau să actualizați rândurile rămase, care însumează același procent. La fel și pentru inserare sau actualizare (creștere). Ar fi nevoie cel puțin de o verificare amânată a constrângerilor, și atunci ce veți face cu CHECK ? Aceasta este cea de-a treia diferență: constrângerile CHECK vizează rânduri individuale, în timp ce ASSERTION-urile pot, de asemenea, să definească/exprime reguli care „acoperă” mai multe rânduri (de exemplu, reguli privind agregările de rânduri).

Comentarii

  • CHECK constrângerile nu „se referă la un singur rând”: ele pot conține subinterogări pentru a se referi la mai multe rânduri, inclusiv la rânduri din alte tabele decât cel pentru care se aplică constrângerea CHECK a fost declarată. Diferența reală constă în faptul că o CHECK este testată doar atunci când tabelul pentru care a fost declarată este actualizat, în timp ce o constrângere ASSERTION este testat indiferent de tabelele implicate în actualizare. –  > Por onedaywhen.
  • „motivul pentru care nu [implementează constrângeri care implică mai mult de un rând este că] pur și simplu nu știu cum să o facă” – Cred mai degrabă că adevărul este că nu știu cum să o facă în mod eficient folosind tehnologia lor veche. De exemplu, ei ar putea să mapeze o constrângere de verificare la nivel de tabel la un declanșator, însă ei îi pun pe utilizatori să scrie declanșatorul și, prin urmare, nu își asumă responsabilitatea pentru performanța slabă rezultată. Sau ar putea să își rescrie produsele de la zero folosind algoritmi noi 😉 –  > Por onedaywhen.
  • „Eficient” a fost, desigur, presupusă ca o condiție prealabilă. Chiar și pisica mea știe „cum să o facă” dacă „eficient” nu face parte din cerințe 🙂 –  > Por Erwin Smout.
  • „Interesant, tu, eu, tu, autorul …, toți am furnizat răspunsuri la această întrebare SO!” Poți să pariezi că vor mai fi câteva din acestea. (Și dacă Stackoverflow ar suporta Diviziunea relațională, am putea să le căutăm cu ușurință !!!!!!!) Relationland nu este o piscină mare, cu nu prea mulți înotători … (Iar David se numără cu siguranță printre cei mai respectabili) -.  > Por Erwin Smout.
  • Am fost intrigat de comentariile dvs. ulterioare referitoare la constrângerile CHECK. Într-adevăr, se pare că nu există nimic în standard care să spună că un CHECK este direcționat la nivelul rândurilor individuale. Curios, de asemenea, nu pare să existe nimic care să spună în mod explicit că un CHECK este direcționat la nivelul TABELULUI !!!!!!! Ceea ce este foarte sigur este că construcțiile care sunt uneori disponibile în contextul expresiilor de constrângere CHECK (de exemplu, :new.<columnname> de la Oracle) vizează cu siguranță nivelul rândului și, cu siguranță, sunt complet incompatibile cu direcționarea la nivelul tabelului.) … –  > Por Erwin Smout.
Mohamed Adel

Aserțiunile nu modifică datele, ci doar verifică anumite condiții

Declanșatoarele sunt mai puternice, deoarece pot verifica condițiile și, de asemenea, pot modifica datele.


Afirmațiile nu sunt legate de tabele specifice din baza de date și nu sunt legate de evenimente specifice.

Declanșatoarele sunt legate de tabele specifice și de evenimente specifice

Comentarii

  • Vă mulțumim. Ce înseamnă „aserțiunile nu sunt legate de tabele specifice” și „declanșatoarele sunt legate de tabele specifice”? – utilizator3284469
onedaywhen

O constrângere a bazei de date implică o condiție care trebuie să fie îndeplinită atunci când baza de date este actualizată. În SQL, dacă o condiție de constrângere se evaluează la fals, atunci actualizarea eșuează, datele rămân neschimbate și SGBD generează o eroare.

Atât CHECK și ASSERTION sunt constrângeri ale bazei de date definite de standardele SQL. O distincție importantă este aceea că o CHECK se aplică unei anumite tabele de bază, în timp ce o constrângere ASSERTION se aplică la întreaga bază de date. Luați în considerare o constrângere care limitează rândurile combinate din tabelele T1 și T2 la un total de 10 rânduri, de exemplu

CHECK (10 >= (
              SELECT COUNT(*)
                FROM (
                      SELECT *
                        FROM T1
                      UNION
                      SELECT * 
                        FROM T2
                     ) AS Tn
             ))

Să presupunem că tabelele sunt goale. Dacă aceasta ar fi fost aplicată ca o constrângere ASSERTION numai și un utilizator ar încerca să introducă 11 rânduri în T1 atunci actualizarea ar eșua. Același lucru s-ar aplica și în cazul în care constrângerea ar fi aplicată ca o restricție de tip CHECK constrângere pentru T1 numai. Cu toate acestea, dacă constrângerea a fost aplicată ca o restricție de tip CHECK constrângere la T2 only, constrângerea ar avea succes, deoarece o instrucțiune care vizează T1 nu determină constrângerile aplicate la T1 să fie testate.

Atât o ASSERTION și a CHECK pot fi amânate (dacă sunt declarate ca DEFERRABLE), permițând ca datele să încalce temporar condiția de constrângere, dar numai în cadrul unei tranzacții.

ASSERTION și CHECK constrângerile care implică subinterogări sunt caracteristici care nu fac parte din SQL standard de bază și niciunul dintre principalele produse SQL nu le acceptă. MS Access (care nu este chiar un produs industrial puternic) suportă CHECK constrângeri care implică subinterogări, dar nu și constrângeri care pot fi amânate; în plus, testarea constrângerilor se efectuează întotdeauna rând cu rând, consecințele practice fiind că funcționalitatea este foarte limitată.

În comun cu CHECK constrângerile, un declanșator se aplică unui anumit tabel. Prin urmare, un declanșator poate fi utilizat pentru a implementa aceeași logică ca și un CHECK constrângere, dar nu și o ASSERTION. Un declanșator este un cod procedural și, spre deosebire de constrângeri, utilizatorul trebuie să își asume o responsabilitate mult mai mare în ceea ce privește aspecte precum performanța și gestionarea erorilor. Cele mai multe produse comerciale SQL acceptă declanșatori (MS Access, menționat anterior, nu).

Comentarii

  • un CHECK se aplică unui tabel de bază specific, în timp ce o constrângere CHECK se aplică întregii baze de date, cred că unul dintre CHECK trebuie înlocuit cu Assertion. –  > Por Am1rr3zA.
Feri

Expresia trebuie să fie adevărată pentru ca declanșatorul să se declanșeze, dar check va fi evaluat oriunde expresia este falsă.