2012-03-12 8 views
5

Sto studiando i trigger e i vincoli.SQL utilizzando il trigger per il vincolo

E ho una domanda da utilizzare trigger (Per essere onesti, io non sono davvero sicuro di come utilizzare grilletto ..)

Diciamo che abbiamo un tavolo insegnanti.

E questa tabella insegnante contiene teacher_id, ssn, first_name, cognome, class_time

per esempio,

|teacher_id|ssn | first_name | last_name | student_number| max_student 
|1   |1234 | bob  | Smith  | 25   |25 
|2   |1235 | kim  | Johnson | 24   |21 
|3   |1236 | kally  | Jones  | 23   |22 

e

diciamo che il numero massimo di numero di matricola sarà 25. (il numero massimo di studenti sarà definito dall'insegnante, quindi può essere qualsiasi numero come 10, 22, 25 ...)

e uno studente desidera aggiungere il clone del bob S. Comunque, voglio fare il trigger che rifiuta di aggiungere lo studente (perché la classe di bob è già piena ..)

Tuttavia, non sono proprio sicuro del modo in cui creare il trigger .. :(.. (questo è la prima volta a studiare circa grilletto ....)

qualcuno può contribuire a creare il codice di esempio per capire parte grilletto?

+2

Dovrai aggiungere il database a cui sei interessato, poiché i trigger tendono ad essere specifici del database. –

+0

Benvenuti in StackOverflow: se inserisci codice, XML o campioni di dati, ** per favore ** evidenzia queste righe nell'editor di testo e fai clic sul pulsante "esempi di codice" ('{}') sulla barra degli strumenti dell'editor per formattarlo e la sintassi lo evidenzia! Non c'è bisogno di 'orge'   'tag e'
', in realtà .... –

+1

Questa è una regola aziendale, che avrei dovuto essere implementata nel software applicativo piuttosto che come trigger o vincolo nel database. I vincoli ei trigger del database generalmente applicano l'integrità referenziale (ovvero mantengono i dati coerenti internamente) e sebbene possa essere un backstop per garantire che le classi non superino i 25, la tua app dovrebbe davvero interrompere il tentativo in primo luogo. –

risposta

10

In primo luogo, credo che questa è una regola di dati e quindi dovrebbe essere applicata a livello centrale. Cioè, dovrebbe esserci un vincolo di database (o equivalente) applicato dal DBMS che impedisce a tutte le applicazioni di scrivere dati non validi (piuttosto che affidarsi ai singoli codificatori di ciascuna applicazione per astenersi dal scrivere dati errati).

In secondo luogo, penso che un trigger AFTER sia appropriato (piuttosto che un trigger INSTEAD OF).

In terzo luogo, questo può essere applicato utilizzando la chiave esterna e i vincoli CHECK a livello di riga.

Per un trigger del tipo di vincolo, l'idea generalmente è di scrivere una query per restituire dati non validi, quindi nel test di attivazione questo risultato è vuoto.

Non hai pubblicato molti dettagli dei tuoi tavoli, quindi suppongo. Presumo che lo student_number sia destinato a essere un numero di studenti; come è che suona come un identificatore così cambierò il nome e assumere l'identificatore per gli studenti è student_id:

WITH EnrolmentTallies 
    AS 
    (
     SELECT teacher_id, COUNT(*) AS students_tally 
     FROM Enrolment 
     GROUP 
      BY teacher_id  
    ) 
SELECT * 
    FROM Teachers AS T 
     INNER JOIN EnrolmentTallies AS E 
     ON T.teacher_id = E.teacher_id 
      AND E.students_tally > T.students_tally; 

In SQL Server, la definizione grilletto sarebbe simile a questa:

CREATE TRIGGER student_tally_too_high ON Enrolment 
AFTER INSERT, UPDATE 
AS 
IF EXISTS (
      SELECT * 
      FROM Teachers AS T 
        INNER JOIN (
           SELECT teacher_id, COUNT(*) AS students_tally 
           FROM Enrolment 
           GROUP 
            BY teacher_id  
          ) AS E 
            ON T.teacher_id = E.teacher_id 
            AND E.students_tally > T.students_tally 
     ) 
BEGIN 
RAISERROR ('A teachers''s student tally is too high to accept new students.', 16, 1); 
ROLLBACK TRANSACTION; 
RETURN 
END; 

Ci sono alcune ulteriori considerazioni, tuttavia. L'esecuzione di una query di questo tipo dopo ogni UPDATE nella tabella potrebbe essere molto inefficiente. È necessario utilizzare UPDATE() (o COLUMNS_UPDATED se si ritiene che l'ordine delle colonne possa essere invocato) e/o le tabelle concettuali deleted e inserted per limitare l'ambito della query e quando è attiva. Sarà inoltre necessario assicurarsi che le transazioni siano serializzate correttamente per evitare problemi di concorrenza. Sebbene coinvolto, non è terribilmente complesso.

Consiglio vivamente il libro Applied Mathematics for Database Professionals  By Lex de Haan, Toon Koppelaars, capitolo 11 (gli esempi di codice sono Oracle ma possono essere facilmente portati su SQL Server).


Potrebbe essere possibile ottenere lo stesso senza trigger. L'idea è di creare un superkey su (teacher_id, students_tally) a cui fare riferimento nell'iscrizione, per il quale verrà mantenuta una sequenza di occorrenze di studenti unici con un test che la sequenza non supererà mai il conteggio massimo.

Ecco alcuni nudo DDL ossa SQL:

CREATE TABLE Students 
(
student_id INTEGER NOT NULL, 
UNIQUE (student_id) 
); 

CREATE TABLE Teachers 
(
teacher_id INTEGER NOT NULL, 
students_tally INTEGER NOT NULL CHECK (students_tally > 0), 
UNIQUE (teacher_id), 
UNIQUE (teacher_id, students_tally) 
); 

CREATE TABLE Enrolment 
(
teacher_id INTEGER NOT NULL UNIQUE, 
students_tally INTEGER NOT NULL CHECK (students_tally > 0), 
FOREIGN KEY (teacher_id, students_tally) 
    REFERENCES Teachers (teacher_id, students_tally) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE, 
student_id INTEGER NOT NULL UNIQUE 
    REFERENCES Students (student_id), 
student_teacher_sequence INTEGER NOT NULL 
    CHECK (student_teacher_sequence BETWEEN 1 AND students_tally) 
UNIQUE (teacher_id, student_id), 
UNIQUE (teacher_id, student_id, student_teacher_sequence) 
); 

poi aggiungere un po 'di aiuto' memorizzati procs/funzioni per mantenere la sequenza aggiornata.

+0

scusate, ho dimenticato di mettere max_student dal tavolo. Sto studiando per creare il TRIGGER che è in grado di controllare il limite di iscrizione quando lo studente vuole iscriversi alle lezioni. Ad esempio, se max_student == numero_salute, lo studente non può aggiungere la classe. Ad ogni modo, mi aiuta davvero a capire TRIGGER. Grazie :) –