Il quarto tipo di blocco PL/SQL con nome è il trigger.
|
|
|
- Gianmaria Dolce
- 10 anni fa
- Просмотров:
Транскрипт
1 Capitolo 10 Trigger di database 10.1 Tipi di trigger 10.2 Creazione di trigger 10.3 Tabelle mutanti 10.4 Sommario Il quarto tipo di blocco PLSQL con nome è il trigger. I trigger condividono molte delle caratteristiche dei sottoprogrammi (esaminati nei due capitoli precedenti), ma presentano significative differenze nel modo in cui sono creati e chiamati. Nel presente capitolo si vedrà come creare diversi tipi di trigger e si descriveranno alcune possibili applicazioni Tipi di trigger I trigger sono simili alle procedure o alle funzioni, per il fatto che sono blocchi PLSQL con nome con sezioni di dichiarazione, eseguibile e di gestione di eccezioni. Come package e tipi oggetto (che verranno descritti nei Capitoli da 14 a 16), i trigger devono essere memorizzati come oggetti standalone nel database e non possono essere locali per un blocco o package. Come si è visto negli ultimi due capitoli, una procedura viene eseguita esplicitamente da un altro blocco attraverso una chiamata di procedura, che può anche passare argomenti. D altra parte, un trigger viene eseguito implicitamente ogni qualvolta si verifica l evento di attivazione e un trigger non accetta argomenti. L atto di eseguire un trigger è noto come attivazione del trigger. L evento di attivazione può essere un operazione DML ( INSERT, UPDATE o DELETE) su una tabella di database o su certi tipi di viste; oppure un evento di sistema, come l avvio o la chiusura di un database e certi tipi di operazioni DDL. Si vedranno gli eventi di attivazione in dettaglio più avanti nel presente capitolo. I trigger possono essere utilizzati in molte situazioni, tra cui: mantenere complesse limitazioni di integrità non possibili attraverso limitazioni dichiarative abilitate alla creazione della tabella; verificare informazioni in una tabella registrando le modifiche effettuate e chi le ha effettuate;
2 398 CAPITOLO 10 segnalare automaticamente ad altri programmi che devono essere effettuate azioni quando vengono apportate modifiche a una tabella; pubblicare informazioni su diversi eventi in un ambiente publishsubscribe. Esistono tre tipi principali di trigger: trigger DML, instead-of e di sistema presentati nei paragrafi successivi. Si vedranno ulteriori dettagli più avanti nel paragrafo Creazione di trigger. NOTA Oracle ammette la scrittura di trigger in PLSQL o in altri linguaggi che possono essere chiamati come routine esterne. Per ulteriori informazioni consultare il paragrafo Corpi di trigger più avanti nel capitolo (oltre al Capitolo 12 per ulteriori informazioni sulle routine esterne in generale). Trigger DML Un trigger DML viene attivato da una dichiarazione DML e il tipo di dichiarazione determina il tipo di trigger DML. I trigger DML possono essere definiti per operazioni INSERT, UPDATE, o DELETE. Possono essere attivati prima o dopo l operazione su una riga. I trigger DML possono agire su tutte le righe o solo su alcune. Agiscono su un sottoinsieme di righe quando sono definiti come trigger a livello di dichiarazione. La differenza sta nel fatto che un trigger a livello di dichiarazione utilizza una clausola WHEN per calcolare dove si sta verificando un tipo specifico di cambiamento. Inserendo la condizione in una clausola WHEN, si elimina l esecuzione del trigger se la condizione non si verifica. Come esempio, si supponga di voler tracciare statistiche su diverse categorie, compreso il numero di libri nel database e il prezzo medio in ogni categoria. I risultati verranno memorizzati nella tabella category _ stats: -- Disponibile online come parte di of tables.sql CREATE TABLE category_stats ( category VARCHAR2(20), total_books NUMBER, average_price NUMBER ); Per tenere aggiornata category _ stats, è possibile creare un trigger su books che aggiornerà category _ stats ogni qualvolta viene modificata books. Il trigger UpdateCategoryStats, mostrato di seguito, effettua questa operazione. Dopo ogni operazione DML su books, viene eseguito il trigger. Il corpo del trigger interroga books e aggiorna category _ stats con le statistiche correnti. -- Disponibile online come UpdateCategoryStats.sql CREATE OR REPLACE TRIGGER UpdateCategoryStats * Tiene aggiornata la tabella category_stats con le modifiche fatte alla tabella books. *
3 TRIGGER DI DATABASE 399 AFTER INSERT OR DELETE OR UPDATE ON books DECLARE CURSOR c_statistics IS SELECT category, COUNT(*) total_books, AVG(price) average_price FROM books GROUP BY category; * Prima cancella da category_stats. Questo azzerera le statistiche ed e necessario per considerare la cancellazione di tutti i libri in una data categoria * DELETE FROM category_stats; * Ora scorre in ogni categoria e inserisce la riga adatta in category_stats. * FOR v_statsrecord in c_statistics LOOP INSERT INTO category_stats (category, total_books, average_price) VALUES (v_statsrecord.category, v_statsrecord.total_books, v_statsrecord.average_price); END LOOP; END UpdateCategoryStats; Un trigger di dichiarazione può essere attivato da più tipi di dichiarazione di attivazione. Per esempio, UpdateCategoryStats viene attivato con dichiarazioni INSERT, UPDATE e DELETE. L evento di attivazione specifica una o più operazioni DML che devono attivare il trigger. Trigger instead-of I trigger instead-of possono essere definiti solo su viste (relazionali od oggetto). A differenza di un trigger DML, che viene eseguito oltre all operazione DML, un trigger instead-of viene eseguito in luogo della dichiarazione DML che lo ha attivato. I trigger instead-of devono essere a livello di riga. Per esempio, si consideri la vista books _ authors: -- Disponibile online come parte di of insteadof1.sql CREATE OR REPLACE VIEW books_authors AS SELECT b.isbn, b.title, a.first_name, a.last_name FROM books b, authors a WHERE b.author1 = a.id OR b.author2 = a.id OR b.author3 = a.id; È illegale inserire direttamente in questa vista, poiché è un unione di due tabelle e l operazione INSERT richiede che entrambe le tabelle sottostanti siano modificate, come mostra la sessione SQL*Plus di seguito:
4 400 CAPITOLO Disponibile online come parte di of insteadof1.sql INSERT INTO books_authors (isbn, title, first_name, last_name) VALUES ( , Oracle Database 10g PLSQL Programming, Joe, Blow ); L output illustra il fallimento dell inserimento nella vista: INSERT INTO books_authors (isbn, title, first_name, last_name) * ERROR at line 1: ORA-01779: cannot modify a column which maps to a non key-preserved table Tuttavia, è possibile creare un trigger instead-of che effettua l operazione corretta per un INSERT, vale a dire aggiornare le tabelle sottostanti: -- Disponibile online come parte di of insteadof2.sql CREATE OR REPLACE TRIGGER InsertBooksAuthors INSTEAD OF INSERT ON books_authors DECLARE v_book books%rowtype; v_authorid authors.id%type; -- Trova l ID del nuovo autore SELECT id INTO v_authorid FROM authors WHERE first_name = :new.first_name AND last_name = :new.last_name; EXCEPTION WHEN NO_DATA_FOUND THEN -- Nessun autore trovato, ne crea uno nuovo INSERT INTO authors (id, first_name, last_name) VALUES (author_sequence.nextval, :new.first_name, :new.last_name) RETURNING ID INTO v_authorid; END; SELECT * INTO v_book FROM books WHERE isbn = :new.isbn; -- Scopre se il libro ha gia 1 o 2 autori e aggiorna -- di conseguenza IF v_book.author2 IS NULL THEN UPDATE books SET author2 = v_authorid WHERE isbn = :new.isbn; ELSE UPDATE books
5 TRIGGER DI DATABASE 401 SET author3 = v_authorid WHERE isbn = :new.isbn; END IF; END InsertBooksAuthors; Con il trigger InsertBooksAuthors, la dichiarazione INSERT va a buon fine ed effettua l operazione corretta. NOTA Per come è scritto, InsertBooksAuthors non ha alcun controllo di errore. Questo problema verrà corretto più avanti nel capitolo nel paragrafo Creazione di trigger instead-of. Trigger di sistema Un trigger di sistema viene attivato quando si verifica un evento di sistema, come l avvio o la chiusura di un database, non quando si verifica un operazione DML su una tabella. Un trigger di sistema può anche essere attivato su operazioni DDL, come la creazione di tabelle. Per esempio, si supponga di voler registrare ogni qualvolta viene creato un dizionario di dati. È possibile farlo creando una tabella, come di seguito: -- Disponibile online come parte di of LogCreations.sql CREATE TABLE ddl_creations ( user_id VARCHAR2(30), object_type VARCHAR2(20), object_name VARCHAR2(30), object_owner VARCHAR2(30), creation_date DATE); Quando la tabella è disponibile, è possibile creare un trigger di sistema per registrare le informazioni relative. Il trigger LogCreations fa esattamente questo: dopo ogni operazione CREATE sullo schema corrente, registra in ddl _ creations informazioni sull oggetto appena creato. -- Disponibile online come parte di of LogCreations.sql CREATE OR REPLACE TRIGGER LogCreations AFTER CREATE ON SCHEMA INSERT INTO ddl_creations (user_id, object_type, object_name, object_owner, creation_date) VALUES (USER, ORA_DICT_OBJ_TYPE, ORA_DICT_OBJ_NAME, ORA_DICT_OBJ_OWNER, SYSDATE); END LogCreations;
6 402 CAPITOLO Creazione di trigger Indipendentemente dal tipo, tutti i trigger vengono creati utilizzando la stessa sintassi. La sintassi generale per la creazione di un trigger è: CREATE [OR REPLACE] TRIGGER nome_trigger {BEFORE AFTER INSTEAD OF} evento_attivante [clausola_referenziale] [WHEN condizione_trigger] [FOR EACH ROW] corpo_trigger; dove nome _ trigger è il nome del trigger, evento _ attivante specifica l evento che attiva il trigger (può anche comprendere una tabella o vista specifica) e corpo _ trigger è il codice principale per il trigger. clausola _ referenziale viene utilizzata per fare riferimento ai dati nella riga che viene modificata da un nome diverso. condizione _ trigger nella clausola WHEN, se presente, è la prima ad essere valutata e il corpo del trigger viene eseguito solo quando tale condizione viene calcolata come TRUE. Si vedranno ulteriori esempi di diversi tipi di trigger nei paragrafi successivi. NOTA Il corpo del trigger non può superare 32 K. Se esiste un trigger che supera tali dimensioni, è possibile ridurlo spostando parte del codice in package o procedure memorizzate compilati separatamente, e chiamandoli dal corpo del trigger. In generale è buona norma mantenere i corpi dei trigger di dimensioni ridotte, a causa della frequenza con cui vengono eseguiti. Il corpo del trigger è un blocco PLSQL, che deve contenere almeno una sezione eseguibile. Come per qualsiasi altro blocco, le sezioni di dichiarazione e di gestione delle eccezioni sono opzionali. Se esiste una sezione di dichiarazione, tuttavia, corpo _ trigger deve cominciare con la parola chiave DECLARE. Questa situazione è diversa da quella di un sottoprogramma, dove la parola chiave DECLARE non è presente. Creazione di trigger DML Un trigger DML viene attivato da un operazione INSERT, UPDATE o DELETE su una tabella di database. Può essere attivato prima o dopo l esecuzione della dichiarazione e può essere attivato una volta per riga interessata o una volta per dichiarazione. La combinazione di tali fattori determina il tipo di trigger. Esiste un totale di 28 possibili tipi: (3 dichiarazioni + 4 combinazioni di dichiarazioni) x 2 tempi x 2 livelli. Per esempio, tutti quelli indicati di seguito sono tipi di trigger DML validi:
7 TRIGGER DI DATABASE 403 prima di UPDATE a livello di dichiarazione; dopo INSERT a livello di riga; prima di DELETE a livello di riga. La Tabella 10.1 riassume le diverse opzioni. Un trigger può anche essere attivato per più tipi di dichiarazioni DML su una data tabella, per esempio INSERT e UPDATE. Qualsiasi codice nel trigger verrà eseguito insieme alla dichiarazione di attivazione stessa, come parte della stessa transazione. Una tabella può avere qualsiasi numero di trigger definiti su di essa, compresi più tipi DML. Per esempio, è possibile definire due trigger dopo DELETE a livello di dichiarazione. Tutti i trigger dello stesso tipo verranno attivati in sequenza (per ulteriori informazioni sull ordine di attivazione di trigger, consultare il paragrafo successivo). L evento di attivazione per un trigger DML specifica il nome della tabella (e della colonna) su cui verrà attivato il trigger. Un trigger può anche essere attivato su una colonna di una tabella annidata. Per ulteriori informazioni sulle tabelle annidate consultare il Capitolo 6. Tabella 10.1 Tipi di trigger DML. CATEGORIA VALORI COMMENTI Dichiarazione INSERT, DELETE o UPDATE Definisce quale tipo di dichiarazione DML causa l attivazione del trigger. Tempo BEFORE o AFTER Definisce se il trigger viene attivato prima o dopo l esecuzione della dichiarazione. Livello Riga o dichiarazione Se il trigger è a livello di riga, viene attivato una volta per ciascuna riga interessata dalla dichiarazione di attivazione. Se il trigger è a livello di dichiarazione, viene attivato una volta, prima o dopo la dichiarazione. Un trigger a livello di riga è identificato dalla clausola FOR EACH ROW nella definizione di trigger. Ordine di attivazione di trigger DML I trigger sono attivati quando viene eseguita la dichiarazione DML. L algoritmo per l esecuzione di una dichiarazione DML è indicato qui di seguito. 1. Esecuzione dei trigger before a livello di dichiarazione, se presenti. 2. Per ogni riga interessata dalla dichiarazione: esecuzione dei trigger before a livello di riga, se presenti; esecuzione della dichiarazione stessa; esecuzione dei trigger after a livello di riga, se presenti. 3. Esecuzione dei trigger after a livello di dichiarazione, se presenti. Per illustrare l algoritmo, si supponga di creare tutti i quattro tipi di trigger UPDATE sulla tabella books, before e after, a livello di dichiarazione e di riga. Verranno anche creati tre trigger prima della riga e due trigger dopo la dichiarazione, come di seguito:
8 404 CAPITOLO Disponibile online come parte di of firingorder.sql CREATE SEQUENCE trig_seq START WITH 1 INCREMENT BY 1; CREATE OR REPLACE PACKAGE TrigPackage AS -- Contatore globale da utilizzare nei trigger v_counter NUMBER; END TrigPackage; CREATE OR REPLACE TRIGGER BooksBStatement BEFORE UPDATE ON books -- Prima azzera il contatore. TrigPackage.v_Counter := 0; INSERT INTO temp_table (num_col, char_col) VALUES (trig_seq.nextval, Before Statement: counter = TrigPackage.v_Counter); -- Ora lo incrementa per il trigger successivo. TrigPackage.v_Counter := TrigPackage.v_Counter + 1; END BooksBStatement; CREATE OR REPLACE TRIGGER BooksAStatement1 AFTER UPDATE ON books INSERT INTO temp_table (num_col, char_col) VALUES (trig_seq.nextval, After Statement 1: counter = TrigPackage.v_Counter); -- Incrementa per il trigger successivo. TrigPackage.v_Counter := TrigPackage.v_Counter + 1; END BooksAStatement1; CREATE OR REPLACE TRIGGER BooksAStatement2 AFTER UPDATE ON books INSERT INTO temp_table (num_col, char_col) VALUES (trig_seq.nextval, After Statement 2: counter = TrigPackage.v_Counter); -- Incrementa per il trigger successivo. TrigPackage.v_Counter := TrigPackage.v_Counter + 1; END BooksAStatement2; CREATE OR REPLACE TRIGGER BooksBRow1 BEFORE UPDATE ON books
9 TRIGGER DI DATABASE 405 FOR EACH ROW INSERT INTO temp_table (num_col, char_col) VALUES (trig_seq.nextval, Before Row 1: counter = TrigPackage.v_Counter); -- Incrementa per il trigger successivo. TrigPackage.v_Counter := TrigPackage.v_Counter + 1; END BooksBRow1; CREATE OR REPLACE TRIGGER BooksBRow2 BEFORE UPDATE ON books FOR EACH ROW INSERT INTO temp_table (num_col, char_col) VALUES (trig_seq.nextval, Before Row 2: counter = TrigPackage.v_Counter); -- Incrementa per il trigger successivo. TrigPackage.v_Counter := TrigPackage.v_Counter + 1; END BooksBRow2; CREATE OR REPLACE TRIGGER BooksBRow3 BEFORE UPDATE ON books FOR EACH ROW INSERT INTO temp_table (num_col, char_col) VALUES (trig_seq.nextval, Before Row 3: counter = TrigPackage.v_Counter); -- Incrementa per il trigger successivo. TrigPackage.v_Counter := TrigPackage.v_Counter + 1; END BooksBRow3; CREATE OR REPLACE TRIGGER BooksARow AFTER UPDATE ON books FOR EACH ROW INSERT INTO temp_table (num_col, char_col) VALUES (trig_seq.nextval, After Row: counter = TrigPackage.v_Counter); -- Incrementa per il trigger successivo. TrigPackage.v_Counter := TrigPackage.v_Counter + 1; END BooksARow; Ora si supponga di emettere la seguente dichiarazione UPDATE:
10 406 CAPITOLO Disponibile online come parte di of firingorder.sql UPDATE books SET category = category WHERE category = Oracle Ebusiness ; Questa dichiarazione interessa tre righe. I trigger a livello di dichiarazione before e after vengono eseguiti ciascuno una volta e i trigger a livello di riga before e after vengono eseguiti ciascuno tre volte. È possibile utilizzare la seguente query per selezionare da temp _ table: -- Disponibile online come parte di of firingorder.sql SELECT * FROM temp_table ORDER BY num_col; Si vedrà il seguente output: NUM_COL CHAR_COL Before Statement: counter = 0 2 Before Row 3: counter = 1 3 Before Row 2: counter = 2 4 Before Row 1: counter = 3 5 After Row: counter = 4 6 Before Row 3: counter = 5 7 Before Row 2: counter = 6 8 Before Row 1: counter = 7 9 After Row: counter = 8 10 Before Row 3: counter = 9 11 Before Row 2: counter = Before Row 1: counter = After Row: counter = After Statement 2: counter = After Statement 1: counter = 14 Ogni trigger, quando viene attivato, vede le modifiche effettuate dai trigger precedenti, oltre alle modifiche effettuate dalla dichiarazione sul database fino a quel momento. Questo si può vedere dal valore di contatore stampato da ciascun trigger (per ulteriori informazioni sull utilizzo di variabili di package consultare il Capitolo 9). L ordine con cui sono attivati i trigger dello stesso tipo non è definito. Nell esempio precedente, ciascun trigger vedrà le modifiche effettuate dai trigger precedenti. Se l ordine è importante, combinare tutte le operazioni in un solo trigger. NOTA Quando si crea uno snapshot log per una tabella, Oracle creerà automaticamente un trigger after riga per la tabella, che aggiornerà il log dopo ogni dichiarazione DML. È necessario saperlo, se su tale tabella deve essere creato un ulteriore trigger after riga. Esistono anche ulteriori
11 TRIGGER DI DATABASE 407 limitazioni su trigger e snapshot (noti in Oracle9i come viste materializzate). Per ulteriori informazioni, consultare la documentazione Oracle Database Advanced Replication. Identificatori di correlazione in trigger a livello di riga Un trigger a livello di riga viene attivato una volta per ogni riga elaborata dalla dichiarazione di attivazione. All interno del trigger, è possibile accedere ai dati nella riga attualmente in fase di elaborazione. Questo viene effettuato attraverso due identificatori di correlazione, :old e :new. Un identificatore di correlazione è uno speciale tipo di variabile bind PLSQL. I due punti davanti a ciascun identificatore indicano che sono variabili bind, nel senso di variabili host utilizzate in PLSQL embedded, e indica che non sono normali variabili PLSQL. Il compilatore PLSQL le tratterà come record di tipo triggering _ table%rowtype, dove triggering _ table è la tabella per cui è definito il trigger. Quindi, un riferimento come: :new.campo sarà valido solo se campo è un campo nella tabella di attivazione. I significati di :old e :new sono descritti nella Tabella Sebbene sintatticamente siano trattati come record, in realtà non lo sono (come discusso più avanti nel paragrafo Pseudorecord ); per questo motivo :old e :new sono anche noti come pseudorecord. NOTA L identificatore :old è indefinito per dichiarazioni INSERT e :new è indefinito per dichiarazioni DELETE. Il compilatore PLSQL non genererà un errore se si utilizza :old in un INSERT o :new in un DELETE, ma i valori di campo di entrambi saranno NULL. Oracle definisce un ulteriore identificatore di correlazione, :parent. Se il trigger è definito su una tabella annidata, :old e :new fanno riferimento alle righe nella tabella annidata, mentre :parent fa riferimento alla riga corrente della tabella genitore. Per ulteriori informazioni, consultare la documentazione Oracle. Tabella 10.2 Gli identificatori di correlazione :old e :new. DICHIARAZIONE DI ATTIVAZIONE :OLD :NEW INSERT Indefinito: tutti i campi Valori che verranno inseriti quando la sono NULL dichiarazione è completa. UPDATE Valori originali per la riga Nuovi valori che verranno aggiornati prima dell aggiornamento quando la dichiarazione è completa. DELETE Valori originali prima della Indefinito: tutti i campi sono NULL. cancellazione della riga
12 408 CAPITOLO 10 Utilizzo di :old e :new. Il trigger GenerateAuthorID, mostrato di seguito, utilizza :new. È un trigger prima di INSERT e lo scopo è compilare il campo ID di authors con un valore generato dalla sequenza author _ sequence. -- Disponibile online come parte di of GenerateAuthorID.sql CREATE OR REPLACE TRIGGER GenerateAuthorID BEFORE INSERT OR UPDATE ON authors FOR EACH ROW * Compila il campo ID di authors con il valore successivo da author_sequence. Poiche ID e una colonna in authors, :new.id e un riferimento valido. * SELECT author_sequence.nextval INTO :new.id FROM dual; END GenerateAuthorID; In realtà GenerateAuthorID modifica il valore di :new.id. Questa è una delle caratteristiche utili di :new: quando la dichiarazione viene eseguita, verranno utilizzati i valori in :new. Con GenerateAuthorID è possibile emettere una dichiarazione INSERT come la seguente: -- Disponibile online come parte di of GenerateAuthorID.sql INSERT INTO authors (first_name, last_name) VALUES ( Lolita, Lazarus ); senza generare un errore. Anche se non è stato specificato un valore per la chiave primaria di colonna ID (necessario), il trigger lo fornirà. Di fatto, se si specifica un valore per ID, sarà ignorato, perché il trigger lo modifica. Se si emette -- Disponibile online come parte di of GenerateAuthorID.sql INSERT INTO authors (ID, first_name, last_name) VALUES (-7, Zelda, Zoom ); la colonna ID verrà popolata da author _ sequence.nextval, invece che contenere 7. Come risultato, non è possibile modificare :new in un trigger a livello di riga after, perché la dichiarazione è già stata elaborata. In generale, :new viene modificato solo in un trigger a livello di riga before, e :old non viene mai modificato, da esso si legge solamente. I record :new e :old sono validi solo in trigger a livello di riga. Se si cerca di fare riferimento a uno di essi in un trigger a livello di dichiarazione, si otterrà un errore di compilazione. Poiché un trigger a livello di riga viene eseguito una volta, anche se vengono elaborate molte righe dalla dichiarazione, :old e :new non hanno significato. A quale riga farebbero riferimento?
13 TRIGGER DI DATABASE 409 Pseudorecord. Sebbene :new e :old siano sintatticamente trattati come record triggering _ table%rowtype, in realtà non lo sono. Come risultato, le operazioni che normalmente sarebbero valide sui record non lo sono per :new e :old. Per esempio, non possono essere assegnati come interi record. Possono essere assegnati solo i singoli campi al loro interno, come illustrato nell esempio di seguito: -- Disponibile online come pseudorecords.sql CREATE OR REPLACE TRIGGER TempDelete BEFORE DELETE ON temp_table FOR EACH ROW DECLARE v_temprec temp_table%rowtype; * Questa non e un assegnazione legale, poiche :old non e davvero un record. * v_temprec := :old; * E possibile fare la stessa cosa, tuttavia, assegnando singolarmente i campi. * v_temprec.char_col := :old.char_col; v_temprec.num_col := :old.num_col; END TempDelete; Inoltre :old e :new non possono essere passati a procedure o funzioni che prendano argomenti di triggering _ table%rowtype. A causa di questo comportamento lo script pseudorecords.sql fallirà con il seguente messaggio di errore: LINECOL ERROR PLS-00049: bad bind variable OLD Clausola REFERENCING. Se si desidera, è possibile utilizzare la clausola REFE- RENCING per specificare un nome diverso per :old e :new. Tale clausola si trova dopo l evento di attivazione, prima della clausola WHEN, con la sintassi REFERENCING [OLD AS vecchio_nome] [NEW AS nuovo_nome] Nel corpo del trigger, è possibile utilizzare :vecchio _ nome e :nuovo _ nome invece di :old e :new. Si noti che gli identificatori di correlazione non hanno due punti nella clausola REFERENCING. Ciò che segue è una versione alternativa del trigger GenerateAuthorID, che utilizza REFERENCING per fare riferimento a :new come :new _ author: -- Disponibile online come parte di of GenerateStudentID.sql CREATE OR REPLACE TRIGGER GenerateAuthorID BEFORE INSERT OR UPDATE ON authors REFERENCING new AS new_author FOR EACH ROW
14 410 CAPITOLO 10 * Compila il campo ID di authors con il valore successivo da author_sequence. Poiche ID e una colonna in authors, :new.id e un riferimento valido. * SELECT author_sequence.nextval INTO :new_author.id FROM dual; END GenerateAuthorID; La clausola WHEN La clausola WHEN è valida solo per trigger a livello di riga. Se presente, il corpo del trigger sarà eseguito solo per le righe che soddisfano la condizione specificata dalla clausola WHEN. La clausola WHEN ha la seguente sintassi: WHEN condizione_trigger dove condizione _ trigger è un espressione booleana, calcolata per ogni riga. Si può fare riferimento ai record :new e :old anche all interno di condizione _ trigger, ma come per REFERENCING, qui non vengono utilizzati i due punti, validi solo nel corpo del trigger. Per esempio, il corpo del trigger CheckPrice viene eseguito solo se il prezzo di un dato libro è superiore a $ 49,99: -- Disponibile online come parte di of CheckPrice1.sql CREATE OR REPLACE TRIGGER CheckPrice BEFORE INSERT OR UPDATE OF price ON books FOR EACH ROW WHEN (new.price > 49.99) * Qui va il corpo del trigger. * NULL; END; CheckPrice potrebbe anche essere scritto come di seguito: CREATE OR REPLACE TRIGGER CheckPrice BEFORE INSERT OR UPDATE OF price ON books FOR EACH ROW IF :new.price > THEN * Qui va il corpo del trigger. * NULL; END IF; END; Predicati di trigger: INSERTING, UPDATING e DELETING Il trigger UpdateCategoryStats esaminato in precedenza nel capitolo è un trigger INSERT, UPDATE e DELETE. All interno di un trigger di questo tipo (che verrà attivato per diversi tipi di dichiarazioni DML) si trovano tre funzioni
15 TRIGGER DI DATABASE 411 booleane che possono essere utilizzate per determinare il tipo di operazione. Tali predicati sono INSERTING, UPDATING e DELETING; il loro comportamento è descritto nella Tabella Tabella 10.3 Comportamento dei predicati PREDICATO INSERTING UPDATING DELETING COMPORTAMENTO TRUE se la dichiarazione di attivazione è un INSERT; FALSE negli altri casi. TRUE se la dichiarazione di attivazione è un UPDATE; FALSE negli altri casi. TRUE se la dichiarazione di attivazione è un DELETE; FALSE negli altri casi. NOTA Esistono ulteriori funzioni che possono essere chiamate nel corpo di un trigger, analoghe ai predicati di trigger. Per ulteriori informazioni consultare il paragrafo Funzioni di attributo di eventi più avanti nel capitolo. Il trigger LogInventoryChanges utilizza i predicati per registrare tutte le modifiche effettuate alla tabella inventory. Oltre alle modifiche, registra l utente che le ha effettuate. I record sono mantenuti nella tabella inventory _ audit, che ha il seguente aspetto: -- Disponibile online come parte di of loginventorychanges1.sql CREATE TABLE inventory_audit ( change_type CHAR(1) NOT NULL, changed_by VARCHAR2(8) NOT NULL, timestamp DATE NOT NULL, old_isbn CHAR(10), new_isbn CHAR(10), old_status VARCHAR2(25), new_status VARCHAR2(25), old_status_date DATE, new_status_date DATE, old_amount NUMBER, new_amount NUMBER ); LogInventoryChanges viene creato con: -- Disponibile online come parte di of loginventorychanges1.sql CREATE OR REPLACE TRIGGER LogInventoryChanges BEFORE INSERT OR DELETE OR UPDATE ON inventory FOR EACH ROW DECLARE v_changetype CHAR(1); * Usa I per un INSERT, D per DELETE e U per UPDATE. * IF INSERTING THEN v_changetype := I ; ELSIF UPDATING THEN v_changetype := U ;
16 412 CAPITOLO 10 ELSE v_changetype := D ; END IF; * Registra tutte le modifiche fatte a inventory in inventory_audit. Usa SYSDATE per generare il timestamp, e USER per restituire lo userid dell utente corrente. * INSERT INTO inventory_audit (change_type, changed_by, timestamp, old_isbn, old_status, old_status_date, old_amount, new_isbn, new_status, new_status_date, new_amount) VALUES (v_changetype, USER, SYSDATE, :old.isbn, :old.status, :old.status_date, :old.amount, :new.isbn, :new.status, :new.status_date, :new.amount); END LogInventoryChanges; La seguente dichiarazione di aggiornamento aggiorna due righe e illustra il comportamento di LogInventoryChanges: -- Disponibile online come parte di of loginventorychanges2.sql UPDATE inventory SET amount = 2000 WHERE isbn IN ( , ); È possibile interrogare la tabella Inventory _ Audit per vedere il trigger in azione. SELECT change_type, old_amount, new_amount FROM inventory_audit; L output della query è mostrato di seguito: C OLD_AMOUNT NEW_AMOUNT U 1,000 2,000 U 1,000 2,000 I trigger vengono molto utilizzati per l auditing, come in LogInventoryChanges. Mentre l auditing a livello di LogInventoryChanges è disponibile come parte del database, i trigger ammettono registrazioni più personalizzate e flessibili. LogInventoryChanges potrebbe essere modificato, per esempio, per registrare le modifiche effettuate solo da certe persone. Potrebbe anche controllare se gli utenti hanno i permessi per effettuare modifiche e sollevare un errore (con RAISE _ APPLICATION _ ERROR) se non li hanno.
17 TRIGGER DI DATABASE 413 Creazione di trigger instead-of A differenza dei trigger DML, che vengono attivati oltre alle operazioni INSERT, UPDATE o DELETE (prima o dopo di esse), i trigger instead-of (come implica il nome, che significa invece di ) vengono attivati in luogo di un operazione DML e la sostituiscono. Inoltre i trigger instead-of possono essere definiti solo su viste, mentre i trigger DML sono definiti su tabelle. I trigger insteadof sono utilizzati in due casi: per consentire di modificare una vista altrimenti non modificabile; per modificare le colonne di una colonna di tabella annidata in una vista. Il primo caso verrà descritto nel presente paragrafo. Per ulteriori informazioni sulle tabelle annidate, consultare il Capitolo 6. Viste modificabili e non modificabili Una vista modificabile è una vista su cui è possibile emettere una dichiarazione DML. In generale, una vista è modificabile se non contiene alcuni dei seguenti elementi: operatori set (UNION, UNION ALL, MINUS); funzioni aggregate (SUM, AVG ecc.); clausole GROUP BY, CONNECT BY o START WITH; l operatore DISTINCT; unioni. Tuttavia esistono alcune viste che contengono unioni e che sono modificabili. In generale, una vista unione è modificabile se l operazione DML su di essa modifica solo una tabella di base per volta e se la dichiarazione DML soddisfa le condizioni indicate nella Tabella 10.4 (per ulteriori informazioni sulle viste unioni modificabili e non modificabili consultare la documentazione Oracle Database Concepts). Se una vista non è modificabile, è possibile scrivere un trigger instead-of su di essa che effettua l operazione corretta, consentendole di essere modificata. Un trigger instead-of può anche essere scritto su una vista modificabile, se è necessaria ulteriore elaborazione. La Tabella 10.4 si riferisce a tabelle con chiave preservata. Una tabella è con chiave preservata se, dopo un unione con un altra tabella, le chiavi nella tabella originale sono anche chiavi nell unione risultante. Tabella 10.4 Viste unione modificabili. OPERAZIONE DML INSERT UPDATE DELETE AMMESSA SE La dichiarazione non fa riferimento, implicitamente o esplicitamente, alle colonne di una tabella con chiave non preservata. Le colonne aggiornate mappano su colonne di una tabella con chiave preservata. Esiste esattamente una tabella con chiave preservata nell unione.
18 414 CAPITOLO 10 Esempio instead-of Si consideri la vista books _ authors vista in precedenza nel presente capitolo: -- Disponibile online come parte di of insteadof1.sql CREATE OR REPLACE VIEW books_authors AS SELECT b.isbn, b.title, a.first_name, a.last_name FROM books b, authors a WHERE b.author1 = a.id OR b.author2 = a.id OR b.author3 = a.id; Come si è visto in precedenza, è illegale effettuare un INSERT in questa vista. È anche illegale effettuare UPDATE o DELETE dalla vista. Questo è vero in parte, perché è possibile definire un comportamento diverso per ciascuna operazione DML sulla vista. Si supponga, tuttavia, che abbiano i significati indicati nella Tabella 10.5: Tabella 10.5 Significati delle operazioni DML sulle viste nel caso in esempio. OPERAZIONE INSERT UPDATE DELETE Tutte SIGNIFICATO Aggiorna la riga contenente il libro, in modo da inserire l autore fornito. Questo darà come risultato un aggiornamento di author2 o author3. Se l autore non esiste, lo aggiunge alla tabella authors utilizzando prima author_sequence per generare l ID dell autore. Uguale al caso INSERT, ad eccezione del fatto che se l autore viene cambiato potrebbe essere modificato author1, author2 o author3. Aggiorna la riga contenente il libro per eliminare l autore fornito. Questo potrebbe dare come risultato un aggiornamento in una qualsiasi delle colonne di autore. Per tutte le operazioni, ammette modifiche solo ai campi first_name e last_name di books_authors. Modifiche a isbn o title devono essere effettuate sulla tabella base. Il trigger InsteadBooksAuthors, mostrato di seguito, rispetta le seguenti regole e consente di effettuare operazioni DML correttamente su books _ authors. Questa è una versione più completa del trigger InsertBooksAuthors visto nei paragrafi introduttivi del presente capitolo e contiene anche la gestione di errori. Si noti che una parte della gestione di errori è effettuata dalle limitazioni sulla tabella books stessa e non nel trigger. -- Disponibile online come parte di of InsteadBooksAuthors.sql CREATE OR REPLACE TRIGGER InsteadBooksAuthors INSTEAD OF INSERT OR UPDATE OR DELETE ON books_authors FOR EACH ROW DECLARE v_book books%rowtype; v_newauthorid authors.id%type; v_oldauthorid authors.id%type; -- Funzione locale che restituisce l ID dei nuovi autori. -- Se i nomi e i cognomi non esistono in authors -- viene generato un nuovo ID da author_sequence.
19 TRIGGER DI DATABASE 415 FUNCTION getid(p_firstname IN authors.first_name%type, p_lastname IN authors.last_name%type) RETURN authors.id%type IS v_authorid authors.id%type; -- Controlla che siano specificati nome e cognome IF p_firstname IS NULL or p_lastname IS NULL THEN RAISE_APPLICATION_ERROR(-20004, Both first and last name must be specified ); END IF; -- Usa un blocco annidato per intercettare l eccezione NO_DATA_FOUND SELECT id INTO v_authorid FROM authors WHERE first_name = p_firstname AND last_name = p_lastname; EXCEPTION WHEN NO_DATA_FOUND THEN -- Nessun autore trovato, ne crea uno nuovo INSERT INTO authors (id, first_name, last_name) VALUES (author_sequence.nextval, p_firstname, p_lastname) RETURNING ID INTO v_authorid; END; -- Ora v_authorid contiene l ID corretto e puo essere restituito. RETURN v_authorid; END getid; -- Funzione locale che restituisce l identificatore di riga da -- ISBN o titolo. FUNCTION getbook(p_isbn IN books.isbn%type, p_title IN books.title%type) RETURN books%rowtype IS v_book books%rowtype; -- Controlla che sia fornito almeno uno tra isbn o titolo IF p_isbn IS NULL AND p_title IS NULL THEN RAISE_APPLICATION_ERROR(-20001, Either ISBN or title must be specified ); ELSIF p_isbn IS NOT NULL AND p_title IS NOT NULL THEN -- Entrambi specificati, quindi usa titolo e ISBN in query SELECT * INTO v_book FROM books WHERE isbn = p_isbn AND title = p_title; ELSE -- Uno solo specificato, quindi usa titolo o ISBN in query SELECT * INTO v_book
20 416 CAPITOLO 10 FROM books WHERE isbn = p_isbn OR title = p_title; END IF; RETURN v_book; EXCEPTION WHEN NO_DATA_FOUND THEN RAISE_APPLICATION_ERROR(-20002, Could not find book with supplied ISBNtitle ); WHEN TOO_MANY_ROWS THEN RAISE_APPLICATION_ERROR(-20003, ISBNtitle must match a single book ); END getbook; * Inizio corpo trigger principale * IF INSERTING THEN -- Prende info su libro e autore v_book := getbook(:new.isbn, :new.title); v_newauthorid := getid(:new.first_name, :new.last_name); -- Controlla che non ci siano doppioni IF v_book.author1 = v_newauthorid OR v_book.author2 = v_newauthorid THEN RAISE_APPLICATION_ERROR(-20006, Cannot have duplicate authors ); END IF; -- Vede se il libro ha gia 1 o 2 autori e -- aggiorna di conseguenza IF v_book.author2 IS NULL THEN UPDATE books SET author2 = v_newauthorid WHERE ISBN = v_book.isbn; ELSIF v_book.author3 IS NULL THEN UPDATE books SET author3 = v_newauthorid WHERE ISBN = v_book.isbn; ELSE -- Troppi autori, non puo inserire RAISE_APPLICATION_ERROR(-20005, v_book.title already has 3 authors ); END IF; ELSIF UPDATING THEN -- Prima controlla che i campi ISBN o title non siano -- modificati. IF (:new.isbn!= :old.isbn OR :new.title!= :old.title) THEN RAISE_APPLICATION_ERROR(-20007, Cannot modify ISBN or title in books_authors ); END IF;
21 TRIGGER DI DATABASE 417 Prende info su libro e autore v_book := getbook(:new.isbn, :new.title); v_newauthorid := getid(:new.first_name, :new.last_name); v_oldauthorid := getid(:old.first_name, :old.last_name); -- Vede quale modificare tra author1, author2 o author3 -- e aggiorna di conseguenza IF v_book.author1 = v_oldauthorid THEN UPDATE books SET author1 = v_newauthorid WHERE ISBN = v_book.isbn; ELSIF v_book.author2 = v_oldauthorid THEN UPDATE books SET author2 = v_newauthorid WHERE ISBN = v_book.isbn; ELSE UPDATE BOOKS SET author3 = v_newauthorid WHERE ISBN = v_book.isbn; END IF; ELSE -- Prende info su libro e autore v_book := getbook(:old.isbn, :old.title); v_oldauthorid := getid(:old.first_name, :old.last_name); -- Vede quale modificare tra author1, author2 o author3 -- e aggiorna di conseguenza. Si noti che se questo risulta -- nell eliminazione di tutti gli autori dalla tabella la limitazione -- NOT NULL su author1 solleva un errore. IF v_book.author1 = v_oldauthorid THEN -- Imposta author1 = author2, author2 = author3 v_book.author1 := v_book.author2; v_book.author2 := v_book.author3; ELSIF v_book.author2 = v_oldauthorid THEN -- Imposta author2 = author 3 v_book.author2 := v_book.author3; ELSE -- Elimina author3 v_book.author3 := NULL; END IF; UPDATE BOOKS SET author1 = v_book.author1, author2 = v_book.author2, author3 = v_book.author3 WHERE ISBN = v_book.isbn; END IF; END InsteadBooksAuthors;
22 418 CAPITOLO 10 NOTA La clausola FOR EACH ROW è opzionale per un trigger instead-of. Tutti i trigger instead-of sono a livello di riga, che sia presente o meno la clausola. InsteadBooksAuthors utilizza predicati di trigger per determinare l operazione DML da effettuare e per intraprendere l azione adatta. La Figura 10.1 contiene i contenuti originali di books, authors e books _ authors per l ISBN , Oracle 9i New Features. Si supponga di emettere quindi la seguente dichiarazione INSERT: -- Disponibile online come parte di of InsteadBooksAuthors.sql INSERT INTO books_authors(isbn, title, first_name, last_name) VALUES ( , Oracle 9i New Features, Esther, Elegant ); Il trigger fa in modo che books sia aggiornata in modo da riflettere il nuovo autore e sia inserita una nuova riga in authors (l ID di autore per Esther Elegant potrebbe essere diverso, secondo il valore di author _ sequence). La Figura 10.2 illustra la situazione che si verifica dopo l INSERT. Ora, si supponga di emettere la seguente dichiarazione UPDATE: -- Disponibile online come parte di of InsteadBooksAuthors.sql UPDATE books_authors SET first_name = Rose, last_name = Riznit WHERE ISBN = AND last_name = Elegant ; Figura 10.1 Contenuti originali di books, authors e books_authors per ISBN La Figura 10.3 illustra la situazione dopo UPDATE. La tabella books è stata nuovamente aggiornata, ed è stata inserita un altra riga in authors. Infine, si supponga di emettere la seguente dichiarazione DELETE: Disponibile online come parte di of InsteadBooksAuthors.sql DELETE FROM books_authors WHERE ISBN = AND last_name = Riznit ;
23 TRIGGER DI DATABASE 419 Figura 10.2 Contenuti dopo INSERT. Ora la tabella books si trova nuovamente nella sua situazione originale, insieme a books _ authors. Ma ci sono ancora le due righe addizionali in authors, come mostrato nella Figura Figura 10.3 Contenuti dopo UPDATE. Figura 10.4 Contenuti dopo DELETE.
24 420 CAPITOLO 10 Creazione di trigger di sistema Come si è visto nei paragrafi precedenti, trigger DML e instead-of vengono attivati su (o invece di) eventi DML, vale a dire dichiarazioni INSERT, UPDATE o DELETE. I trigger di sistema, invece, vengono attivati su due diversi tipi di eventi: DDL o di database. Gli eventi DDL comprendono dichiarazioni CREA- TE, ALTER o DROP, mentre gli eventi di database comprendono avvioshutdown del server, logonlogoff di un utente e un errore di server. La sintassi per la creazione di un trigger di sistema è la seguente: CREATE [OR REPLACE] TRIGGER [schema.]nome_trigger {BEFORE AFTER} {elenco_eventi_ddl elenco_eventi_database} ON {DATABASE [schema.]schema} [clausola_when] corpo_trigger; dove elenco _ eventi _ ddl è uno o più eventi DDL (separati dalla parola chiave OR) ed elenco _ eventi _ database è uno o più eventi di database (separati dalla parola chiave OR). La Tabella 10.6 descrive gli eventi DDL e di database, insieme alle tempistiche ammesse (BEFORE o AFTER). Non è possibile creare un trigger di sistema instead-of. NOTA Per poter creare un trigger di sistema è necessario avere il privilegio di sistema ADMINISTER DATABASE TRIGGER. Per ulteriori informazioni consultare il paragrafo Privilegi di trigger più avanti nel capitolo. Tabella 10.6 Eventi DDL e di database di sistema. EVENTO TEMPISTICHE AMMESSE DESCRIZIONE STARTUP AFTER Attivato quando viene avviata un istanza. SHUTDOWN BEFORE Attivato quando viene chiusa un istanza. Questo evento potrebbe non essere attivato se il database viene chiuso in modo non normale (come in un annullamento di shutdown). SERVERERROR AFTER Attivato quando si verifica un errore. LOGON AFTER Attivato dopo che un utente si è collegato con successo al database. LOGOFF BEFORE Attivato all inizio del logoff di un utente. CREATE BEFORE, AFTER Attivato prima o dopo la creazione di un oggetto schema. DROP BEFORE, AFTER Attivato prima o dopo l eliminazione di un oggetto schema. ALTER BEFORE, AFTER Attivato prima o dopo la modifica di un oggetto schema. TRUNCATE BEFORE, AFTER Attivato prima o dopo l emissione di una dichiarazione TRUNCATE. (segue)
25 TRIGGER DI DATABASE 421 Tabella 10.6 Eventi DDL e di database di sistema. (continua) EVENTO TEMPISTICHE AMMESSE DESCRIZIONE DDL BEFORE, AFTER Attivato prima o dopo la maggior parte delle dichiarazioni DDL. Questo evento non verrà attivato per dichiarazioni ALTER DATABASE, CREATE CONTROLFILE o CREATE DATABASE, né verrà attivato per DDL emesse attraverso un interfaccia procedurale, quale AQ. ANALYZE BEFORE, AFTER Attivato prima o dopo l emissione di ANALYZE STATE- MENT. ASSOCIATE BEFORE, AFTER Attivato prima o dopo l emissione di una dichiarazione STATISTICS ASSOCIATE STATISTICS. DISASSOCIATE BEFORE, AFTER Attivato prima o dopo l emissione di una dichiarazione STATISTICS DISASSOCIATE STATISTICS. AUDIT BEFORE, AFTER Attivato prima o dopo l emissione di una dichiarazione AUDIT. NOAUDIT BEFORE, AFTER Attivato prima o dopo l emissione di una dichiarazione NOAUDIT. COMMENT BEFORE, AFTER Attivato prima o dopo l emissione di una dichiarazione COMMENT. GRANT BEFORE, AFTER Attivato prima o dopo l emissione di una dichiarazione GRANT. REVOKE BEFORE, AFTER Attivato prima o dopo l emissione di una dichiarazione REVOKE. RENAME BEFORE, AFTER Attivato prima o dopo l emissione di una dichiarazione RENAME. SUSPEND* AFTER Attivato dopo la sospensione di una dichiarazione SQL a causa di una condizione di mancanza di spazio. In questo caso il trigger può correggere la situazione, quindi la dichiarazione può essere nuovamente emessa. *Questo evento è disponibile in Oracle9i e successivi. Trigger di database e di schema Un trigger di sistema può essere definito a livello del database o a livello di schema. Un trigger a livello di database verrà attivato ogniqualvolta si verifica l evento di attivazione, mentre un trigger a livello di schema verrà attivato solo quando l evento di attivazione si verifica per lo schema specificato. Le parole chiave DATABASE e SCHEMA determinano il livello per un dato trigger di sistema. Se lo schema non è specificato con la parola chiave SCHEMA, per impostazione predefinita corrisponde allo schema che possiede il trigger. Per esempio, si supponga di creare il seguente trigger mentre si è connessi come UserA: NOTA Questi esempi richiedono l esistenza di UserA, UserB ed Example nel database. Se non sono presenti, eseguire createuser.sql prima di eseguire DatabaseSchema1.sql. Per ulteriori dettagli consultare DatabaseSchema1.sql. Inoltre è necessario eseguire lo script DatabaseSchema1.sql come utente system o come utente con privilegi di ruolo DBA. Lo script crea l utente example e concede i necessari privilegi di sistema.
26 422 CAPITOLO Disponibile online come parte di of DatabaseSchema1.sql CREATE OR REPLACE TRIGGER LogUserAConnects AFTER LOGON ON SCHEMA INSERT INTO example.temp_table VALUES (1, LogUserAConnects fired! ); END LogUserAConnects; LogUserAConnects registrerà in temp _ table ogni connessione di UserA al database. È possibile fare la stessa cosa per UserB creando quanto segue, mentre si è connessi come UserB: -- Disponibile online come parte di of DatabaseSchema.sql CREATE OR REPLACE TRIGGER LogUserBConnects AFTER LOGON ON SCHEMA INSERT INTO example.temp_table VALUES (2, LogUserBConnects fired! ); END LogUserBConnects; Infine è possibile creare il seguente trigger mentre si è connessi come example. LogAllConnects registrerà tutte le connessioni al database, perché è un trigger a livello di database. -- Disponibile online come parte di of DatabaseSchema1.sql CREATE OR REPLACE TRIGGER LogAllConnects AFTER LOGON ON DATABASE INSERT INTO example.temp_table VALUES (3, LogAllConnects fired! ); END LogAllConnects; Ora è possibile connettersi al database come UserA, UserB ed Example e vedere gli effetti dei diversi trigger. Il trigger after-logon sullo schema si attiva per primo, seguito dal trigger after-logon sul database. -- Disponibile online come parte di of DatabaseSchema1.sql connect UserAUserA connect UserBUserB connect exampleexample Una query SQL*Plus formattata sulla tabella temporanea consente di vedere la sequenza dei trigger attivati. COL num_col FORMAT 9 COL char_col FORMAT A50 SELECT * FROM temp_table;
27 TRIGGER DI DATABASE 423 Il trigger di schema UserA è il primo record nella tabella, seguito dal trigger sul database after-logon. La terza e la quarta voce riflettono il comportamento per UserB. L utente Example non ha un trigger a livello di schema. La connessione a tale schema attiva solo il trigger after-logon sul database. NUM_COL CHAR_COL LogUserAConnects fired! 3 LogAllConnects fired! 2 LogUserBConnects fired! 3 LogAllConnects fired! 3 LogAllConnects fired! LogAllConnects è stato attivato tre volte (una volta per le tre connessioni), mentre LogUserAConnects e LogUserBConnects sono stati attivati una sola volta, come previsto. NOTA I trigger STARTUP e SHUTDOWN sono rilevanti solo a livello di database. Non è illegale crearli a livello di schema, ma non verranno attivati. Funzioni di attributo di eventi In un trigger di sistema, sono disponibili numerose funzioni di attributo di eventi. Simili ai predicati di trigger (INSERTING, UPDATING e DELETING), consentono al corpo di un trigger di prendere informazioni sull evento di attivazione. Sebbene sia legale chiamare tali funzioni da altri blocchi PLSQL (non necessariamente nel corpo di un trigger di sistema), non restituiranno sempre un risultato valido. Le funzioni di attributo di eventi sono descritte nella Tabella Il trigger LogCreations, visto all inizio del presente capitolo, utilizza alcune funzioni di attributo. A differenza dei predicati di trigger, le funzioni di attributo di eventi sono funzioni PLSQL standalone, con sinonimi pubblici definiti, e cominciano con ORA _. Prima di eseguire il presente paragrafo, ci si deve connettere allo schema di esempio. -- Disponibile online come parte di of LogCreations.sql CREATE OR REPLACE TRIGGER LogCreations AFTER CREATE ON SCHEMA INSERT INTO ddl_creations (user_id, object_type, object_name, object_owner, creation_date) VALUES (USER, ORA_DICT_OBJ_TYPE, ORA_DICT_OBJ_NAME, ORA_DICT_OBJ_OWNER, SYSDATE); END LogCreations;
28 424 CAPITOLO 10 SUGGERIMENTO Prima di Oracle8i, le funzioni di attributo di eventi, oltre ad avere nomi diversi, erano possedute da SYS e non avevano sinonimi definiti. Di conseguenza, dovevano avere il prefisso SYS per poter essere risolte. Sebbene questa sintassi sia ancora legale, si dovrebbe utilizzare la sintassi corrente. Utilizzare il comando di descrizione SQL*Plus per vedere elenco di argomenti, tipo e modalità di ORA _ DICT _ OBJ _ NAME _ LIST. FUNCTION ora_dict_obj_name_list RETURNS BINARY_INTEGER Argument Name Type InOut Default? OBJECT_LIST DBMS_STANDARD OUT Alcune funzioni di attributo (quali ORA _ DICT _ OBJ _ NAME _ LIST) hanno parametri OUT di tipo ORA _ NAME _ LIST _ T. Tale tipo è definito come parte del package STANDARD come di seguito: TYPE ORA_NAME_LIST_T IS TABLE OF VARCHAR2(64); I parametri OUT sono descritti nella Tabella Tabella 10.7 Funzioni di attributo di eventi. FUNZIONE ATTRIBUTO TIPO EVENTI DI SISTEMA DESCRIZIONE RESTITUITO PER CUI E APPLICABILE ORA_CLIENT_IP_ADDRESS VARCHAR2 LOGON Restituisce l indirizzo IP del client per un logon di database. Se il protocollo non è TCPIP, questa funzione non è valida. ORA_DATABASE_NAME VARCHAR2(50) Tutti gli eventi Restituisce il nome del database. ORA_DES_ENCRYPTED_ VARCHAR2 ALTER Per eventi ALTER USER, resti- PASSWORD tuisce la password decifrata dell utente. ORA_DICT_OBJ_NAME VARCHAR2(30) ALTER, ANALYZE, ASSOCIATE Restituisce il nome dell oggetto STATISTICS, COMMENT, CREA- dizionario su cui si è verificata TE, DDL, DISASSOCIATE STA- un operazione DDL. TISTICS, DROP, GRANT, RENA- ME, REVOKE, TRUNCATE ORA_DICT_OBJ_NAME_LIST BINARY_ ASSOCIATE STATISTICS, DI- elenco_nomi conterrà un elenco di (elenco_nomi OUT ORA_NA- INTEGER SASSOCIATE STATISTICS nomi di oggetti modificati dal- ME_LIST_T) l evento. Il valore restituito è la dimensione dell array. ORA_DICT_OBJ_OWNER VARCHAR2(30) ALTER, ANALYZE, ASSOCIATE Restituisce il possessore STATISTICS, COMMENT, CRE- dell oggetto dizionario su cui si ATE, DDL, DISASSOCIATE è verificata un operazione STATISTICS, DROP, GRANT, DDL. RENAME, REVOKE, TRUNCATE (segue)
29 TRIGGER DI DATABASE 425 Tabella 10.7 Funzioni di attributo di eventi. (continua) FUNZIONE ATTRIBUTO TIPO EVENTI DI SISTEMA DESCRIZIONE RESTITUITO PER CUI E APPLICABILE ORA_DICT_OBJ_OWNER_ BINARY_ ASSOCIATE STATISTICS, DI- elenco_nomi conterrà un elenco LIST(elenco_nomi OUT INTEGER SASSOCIATE STATISTICS dei possessori di oggetti modificati ORA_NAME_LIST_T) dall evento. Il valore restituito è la dimensione dell array. ORA_DICT_OBJ_TYPE VARCHAR2(20) ALTER, ANALYZE, ASSOCIATE Restituisce il tipo di oggetto di- STATISTICS, COMMENT, CRE- zionario su cui si è verificata ATE, DDL, DISASSOCIATE un operazione DDL. STATISTICS, DROP, GRANT, RENAME, REVOKE, TRUNCATE ORA_GRANTEE(elenco_utenti BINARY_ GRANT elenco_utenti conterrà i conces- OUT ORA_NAME_ LIST_T) INTEGER sionari per una dichiarazione GRANT. Il valore restituito è la dimensione dell array. ORA_INSTANCE_NUM NUMBER Tutti gli eventi Restituisce il numero di istanza. ORA_IS_ALTER_COLUMN BOOLEAN ALTER Per eventi ALTER TABLE, resti- (nome_colonna IN VARCHAR2) tuisce true se viene alterato nome_colonna. ORA_IS_CREATING_ BOOLEAN CREATE Restituisce true se l evento NESTED_TABLE corrente sta creando una tabella annidata. ORA_IS_DROP_COLUMN BOOLEAN DROP Restituisce true se viene eliminata (nome_colonna IN VARCHAR2) nome_colonna. ORA_IS_SERVERERROR BOOLEAN SERVERERROR, Restituisce true se num_errore (num_errore IN BINARY_INTEGER) SUSPEND è nello stack di errori. ORA_LOGIN_USER VARCHAR2(30) Tutti gli eventi Restituisce il nome di utente di login. ORA_PARTITION_POS* BINARY_ CREATE Per una dichiarazione CREATE INTEGER TABLE, restituisce la posizione nel testo dove può essere inse rita una clausola PARTITION. ORA_PRIVILEGE_LIST(elenco_ BINARY_ GRANT, REVOKE elenco_privilegi conterrà i privilegi privilegi OUT ORA_NAME_ INTEGER concessi o revocati. Il valore LIST_T) restituito è la dimensione dell array. ORA_REVOKEE(elenco_utenti BINARY_ REVOKE elenco_utenti conterrà i revocanti OUT ORA_NAME_LIST_T) INTEGER per una dichiarazione REVOKE. Il valore restituito è la dimensione dell array. ORA_SERVER_ERROR(posi- NUMBER SERVERERROR Restituisce il numero di errore zione IN BINARY_INTEGER) nella posizione data nello stack di errori. La posizione in cima allo stack è la posizione 1. ORA_SERVER_ERROR_DEPTH* BINARY_ SERVERERROR Restituisce il numero totale di INTEGER errori nello stack di errori. ORA_SERVER_ERROR_MSG VARCHAR2 SERVERERROR Restituisce il messaggio di errore (posizione IN BINARY_INTEGER)* nella posizione data nello stack di errori. La posizione in cima allo stack è la posizione 1. (segue)
30 426 CAPITOLO 10 Tabella 10.7 Funzioni di attributo di eventi. (continua) FUNZIONE ATTRIBUTO TIPO EVENTI DI SISTEMA DESCRIZIONE RESTITUITO PER CUI E APPLICABILE ORA_SERVER_ERROR_ BINARY_ SERVERERROR Restituisce il numero di parametri NUM_PARAMS(posizione INTEGER per il messaggio di errore nella IN BINARY_INTEGER)* posizione data. Un parametro viene inserito in un messaggio di errore utilizzando nel testo del messaggio di errore un formato stringa come %s o %d. La posizione in cima allo stack è la posizione 1. ORA_SERVER_ERROR_ VARCHAR2 SERVERERROR Restituisce il valore sostituito per PARAM(posizione IN BI- il parametro dato (1 è il primo NARY_INTEGER), param parametro) nella posizione data IN BINARY_INTEGER)* nello stack di errori. La posizione in cima allo stack è la posizione 1. ORA_SQL_TEXT(testo_ BINARY_ Tutti gli eventi Restituisce il testo della dichiarasql OUT ORA_NAME_ INTEGER zione attivante. Se la dichiarazione LIST_T* è lunga, viene suddivisa in più elementi, con il valore restituito che specifica la dimensione dell array. ORA_SYSEVENT VARCHAR2 Tutti gli eventi Nome dell evento di sistema che attiva il trigger. ORA_WITH_GRANT_OPTION BOOLEAN GRANT Restituisce true se i privilegi sono concessi con l opzione grant. SPACE_ERROR_INFO(numero_ BOOLEAN SERVERERROR, Restituisce true se l errore è errore OUT NUMBER, tipo_errore SUSPEND relativo a una condizione di OUT VARCHAR2, possessore_ mancanza di spazio e i parametri oggetto OUT VARCHAR2, nome_ out sono compilati con informaspazio_tabella OUT VARCHAR2, zioni sull oggetto che ha causato nome_oggetto OUT VARCHAR2, l errore. nome_sottooggetto OUT VAR- CHAR2)* *Questa funzione è disponibile in Oracle9iR1 e successivi. Trigger di sistema e transazioni Secondo l evento di attivazione, cambia il comportamento transazionale di un trigger di sistema. Un trigger di sistema viene attivato come una transazione separata confermata al completamento con successo del trigger, oppure viene attivato come parte della transazione dell utente corrente. I trigger STARTUP, SHU- TDOWN, SERVERERROR e LOGON si attivano tutti come transazioni separate, mentre i trigger LOGOFF e DDL vengono attivati come parte della transazione corrente. È importante notare, tuttavia, che il lavoro svolto dal trigger in genere verrà confermato in ogni caso. Nel caso di un trigger DDL, la transazione corrente (vale a dire la dichiarazione CREATE, ALTER o DROP) viene confermata automaticamente, confermando il lavoro nel trigger. Anche il lavoro in un trigger LOGOFF verrà confermato come parte della transazione finale nella sessione.
31 TRIGGER DI DATABASE 427 NOTA Poiché in genere i trigger di sistema vengono confermati in ogni caso, la loro dichiarazione come autonomi non avrà alcun effetto. Trigger di sistema e clausola WHEN Come i trigger DML, i trigger di sistema possono utilizzare la clausola WHEN per specificare una condizione sull attivazione del trigger. Tuttavia esistono limitazioni sui tipi di condizioni che possono essere specificati per ogni tipo di trigger di sistema, vale a dire: i trigger STARTUP e SHUTDOWN non possono avere alcuna condizione; i trigger SERVERERROR possono utilizzare il test ERRNO per controllare solo un errore specifico; i trigger LOGON e LOGOFF possono controllare ID o nome utente con i test USERID o USERNAME; i trigger DDL possono controllare il tipo e il nome dell oggetto da modificare e possono controllare ID o nome utente. Altre questioni sui trigger Nel presente paragrafo si vedranno altre questioni sui trigger. Tra queste il namespace per i nomi di trigger, diverse limitazioni sull utilizzo dei trigger e diversi tipi di corpi di trigger. Il paragrafo si conclude con una discussione sui privilegi relativi ai trigger. Nomi di trigger Il namespace per i nomi di trigger è diverso da quello di altri sottoprogrammi. Un namespace è l insieme di identificatori legali disponibili per l uso come nomi di un oggetto. Procedure, package e tabelle condividono il medesimo namespace. Questo significa che, in uno schema di database, tutti gli oggetti nello stesso namespace devono avere nomi unici. Per esempio, è illegale dare lo stesso nome a una procedura e a un package. I trigger, tuttavia, si trovano in un namespace separato. Questo significa che un trigger può avere lo stesso nome di una tabella o di una procedura. In uno schema, tuttavia, un dato nome può essere utilizzato per un solo trigger. Per esempio, è possibile creare un trigger chiamato inventory sulla tabella inventory, ma è illegale creare anche una procedura chiamata inventory. Quanto di seguito deve essere testato nell account UserA a causa della dipendenza dalla tabella inventory creata in esso. In alternativa, per provarlo, è possibile eseguire lo script tables.sql in un altro schema. -- Disponibile online come samename.sql CREATE OR REPLACE TRIGGER inventory BEFORE INSERT ON inventory INSERT INTO temp_table (char_col)
32 428 CAPITOLO 10 VALUES ( Trigger fired! ); END inventory; Se si cerca di creare una procedura chiamata inventory dopo la creazione del trigger con lo stesso nome, l operazione fallirà perché cerca di occupare lo stesso namespace. -- Disponibile online come samename.sql CREATE OR REPLACE PROCEDURE inventory AS INSERT INTO temp_table (char_col) VALUES ( Procedure called! ); END inventory; Il tentativo di creare la procedura solleverà il seguente errore: CREATE OR REPLACE PROCEDURE inventory AS * ERROR at line 1: ORA-00955: name is already used by an existing object SUGGERIMENTO Sebbene sia possibile utilizzare lo stesso nome per un trigger e una tabella, è sconsigliato: è meglio dare a ciascun trigger un nome unico che identifichi la sua funzione, oltre alla tabella su cui viene definito, o di anteporre ai trigger una sequenza di caratteri comune (quale TRG _ ). Limitazioni sui trigger Il corpo di un trigger è un blocco PLSQL o una dichiarazione CALL (per particolari sull utilizzo di CALL consultare il paragrafo successivo). Qualsiasi dichiarazione legale in un blocco PLSQL è legale in un corpo di trigger, conformemente alle seguenti limitazioni: un trigger può non emettere alcuna dichiarazione di controllo di transazione, COMMIT, ROLLBACK, SAVEPOINT o SET TRANSACTION. Il compilatore PLSQL ammetterà la creazione di un trigger che contenga una di queste dichiarazioni, ma si riceverà un errore quando il trigger viene attivato. Questo perché è attivato come parte dell esecuzione della dichiarazione di attivazione e si trova nella stessa transazione della dichiarazione di attivazione. Quando la dichiarazione di attivazione viene confermata o annullata, anche il lavoro nel trigger viene confermato o annullato (è possibile creare un trigger che venga eseguito come transazione autonoma; in tal caso il lavoro nel trigger può essere confermato o annullato indipendentemente dalla dichiarazione di attivazione. Per ulteriori informazioni sulle transazioni anonime consultare il Capitolo 4);
33 TRIGGER DI DATABASE 429 analogamente, qualsiasi procedura o funzione chiamata dal corpo del trigger non può emettere alcuna dichiarazione di controllo di transazione (a meno che anch esse siano dichiarate come autonome); il corpo del trigger non può dichiarare alcuna variabile LONG o LONG RAW. Inoltre :new e :old non possono fare riferimento a una colonna LONG o LONG RAW nella tabella per cui è definito il trigger; il codice nel corpo di un trigger può fare riferimento a colonne LOB (Large OBject) e utilizzarle, ma potrebbe non modificare i valori delle colonne. Questo vale anche per colonne oggetto. Esistono anche limitazioni sulle tabelle a cui può accedere il corpo di un trigger. Secondo il tipo di trigger e le limitazioni sulle tabelle, le tabelle possono essere mutanti. Questa situazione è descritta in dettaglio nel paragrafo Tabelle mutanti più avanti nel capitolo. Corpi di trigger Prima di Oracle8i, i corpi di trigger dovevano essere blocchi PLSQL. In Oracle8i e successivi, tuttavia, un corpo di trigger può essere costituito invece da una dichiarazione CALL. La procedura chiamata può essere un sottoprogramma memorizzato PLSQL o un wrapper per una routine C o Java. Questo consente di creare trigger in cui il codice funzionale è scritto in Java. Per esempio, si supponga di voler registrare le connessioni e le sconnessioni al database, nella seguente tabella che si trova nello schema UserA: -- Disponibile online come parte di of tables.sql CREATE TABLE connect_audit ( user_name VARCHAR2(30), operation VARCHAR2(30), timestamp DATE); Per registrare connessioni e sconnessioni è possibile utilizzare il seguente package: -- Disponibile online come LogPkg1.sql CREATE OR REPLACE PACKAGE LogPkg AS PROCEDURE LogConnect(p_UserID IN VARCHAR2); PROCEDURE LogDisconnect(p_UserID IN VARCHAR2); END LogPkg; CREATE OR REPLACE PACKAGE BODY LogPkg AS PROCEDURE LogConnect(p_UserID IN VARCHAR2) IS INSERT INTO connect_audit (user_name, operation, timestamp) VALUES (p_userid, CONNECT, SYSDATE); END LogConnect;
34 430 CAPITOLO 10 PROCEDURE LogDisconnect(p_UserID IN VARCHAR2) IS INSERT INTO connect_audit (user_name, operation, timestamp) VALUES (p_userid, DISCONNECT, SYSDATE); END LogDisconnect; END LogPkg; LogPkg.LogConnect e LogPkg.LogDisconnect prendono come argomento un nome utente e inseriscono una riga in connect_audit. Infine è possibile chiamarle da trigger LOGON e LOGOFF, come di seguito: -- Disponibile online come LogConnects.sql CREATE OR REPLACE TRIGGER LogConnects AFTER LOGON ON DATABASE CALL LogPkg.LogConnect(SYS.LOGIN_USER) CREATE OR REPLACE TRIGGER LogDisconnects BEFORE LOGOFF ON DATABASE CALL LogPkg.LogDisconnect(SYS.LOGIN_USER) NOTA Poiché LogConnects e LogDisconnects sono trigger di sistema sul database (e non su uno schema), per crearle è necessario avere il privilegio di sistema ADMINISTER DATABASE TRIGGER. Il corpo di trigger per LogConnects e LogDisconnects è semplicemente una dichiarazione CALL, che indica la procedura da eseguire. Come unico argomento viene passato l utente corrente. Nell esempio precedente, la destinazione di CALL è una procedura di package PLSQL standard, ma potrebbe essere un wrapper per una routine esterna C o Java. Per esempio, si supponga di caricare la seguente classe Java nel database e provarla. Prima di cercare di caricare il programma Java nel database, è necessario controllare di avere l ambiente impostato correttamente. È necessario controllare che sia impostata la variabile di ambiente CLASSPATH. Questa operazione viene effettuata in modo leggermente diverso in Windows e Unix; sono indicate le sintassi per entrambi i sistemi. Se l archivio Java classes12.zip si trova nel CLASSPATH, potrebbe non essere necessario impostarlo. UNIX # echo $CLASSPATH Windows C:> echo %CLASSPATH% Se la variabile di ambiente CLASSPATH non contiene classes12.zip e un riferimento alla directory di lavoro presente, è necessario aggiungerli al classpath.
35 TRIGGER DI DATABASE 431 Gli archivi Java possono avere diversi tipi di estensioni, ma i più diffusi sono *.jar e *.zip. Quando li si inserisce nella variabile di ambiente CLASSPATH, è necessario trattarli come directory. Sarà necessario avere la directory di lavoro presente quando si esegue un comando loadjava sul database. Se esiste una variabile CLASSPATH, deve essere inserita prima del file classes12.zip. UNIX # export set CLASSPATH=$ORACLE_HOMEjdbclibclasses12.zip:. Windows C:> set CLASSPATH=%ORACLE_HOME%jdbclibclasses12.zip;. Copiare il file Logger.java che segue dal sito Web o dal tipo nella propria directory di lavoro e compilare il file. La sintassi è la stessa in Unix e Windows. Questo creerà un programma client Thick Java che deve essere eseguito dal server in sui si trova il database Oracle. Questa limitazione è dovuta alle dipendenze di libreria esterne all implementazione Oracle JDBC. javac Logger.java Questo genererà un byte file Java, chiamato Logger.class. Verrà caricato nel database con l utility loadjava e la sintassi di seguito. Questo caricherà il bytecode Java nel database per lo schema Example. loadjava -r -f -o -user exampleexample Logger.class Disponibile online come Logger.java import java.sql.*; import oracle.jdbc.driver.*; public class Logger { public static void LogConnect(String userid) throws SQLException { Prende connessione JDBC predefinita Connection conn = new OracleDriver().defaultConnection(); String insertstring = INSERT INTO connect_audit + (user_name, operation, timestamp) + VALUES (?, CONNECT, SYSDATE) ; Prepara ed esegue una dichiarazione che fa l inserimento PreparedStatement insertstatement = conn.preparestatement(insertstring); insertstatement.setstring(1, userid); insertstatement.execute(); } public static void LogDisconnect(String userid) throws SQLException {
36 432 CAPITOLO 10 Prende connessione JDBC predefinita Connection conn = new OracleDriver().defaultConnection(); String insertstring = INSERT INTO connect_audit (user_name, operation, timestamp) + VALUES (?, DISCONNECT, SYSDATE) ; Prepara ed esegue una dichiarazione che fa l inserimento PreparedStatement insertstatement = conn.preparestatement(insertstring); insertstatement.setstring(1, userid); insertstatement.execute(); } } Si crea il package PLSQL LogPkg come wrapper per la classe Java creata. -- Disponibile online come LogPkg2.sql CREATE OR REPLACE PACKAGE LogPkg AS PROCEDURE LogConnect(p_UserID IN VARCHAR2); PROCEDURE LogDisconnect(p_UserID IN VARCHAR2); END LogPkg; CREATE OR REPLACE PACKAGE BODY LogPkg AS PROCEDURE LogConnect(p_UserID IN VARCHAR2) IS LANGUAGE JAVA NAME Logger.LogConnect(java.lang.String) ; PROCEDURE LogDisconnect(p_UserID IN VARCHAR2) IS LANGUAGE JAVA NAME Logger.LogDisconnect(java.lang.String) ; END LogPkg; Prima di provare i wrapper, è necessario creare una copia della tabella connect_audit nello schema Example. Se questa operazione non viene effettuata, quando si cerca di provare i wrapper PLSQL si ottengono un errore Java non intercettato e un errore ORA Disponibile online come parte di of createconnectaudit.sql CREATE TABLE connect_audit ( user_name VARCHAR2(30), operation VARCHAR2(30), timestamp DATE); È possibile creare un programma PLSQL con blocco anonimo per provare la connessione e la sconnessione. Sono definite come segue:
37 TRIGGER DI DATABASE 433 Disponibile online come testlogpkg.sql DECLARE v_string VARCHAR2(80) := USERA ; logpkg.logconnect(v_string); END; DECLARE v_string VARCHAR2(80) := USERA ; logpkg.logdisconnect(v_string); END; Si possono vedere i risultati del test interrogando la tabella connect_audit. Analogamente, è possibile utilizzare gli stessi trigger per ottenere l effetto desiderato. Per ulteriori informazioni sulle routine esterne consultare il Capitolo 12. NOTA I predicati di trigger quali INSERTING, UPDATING e DELETING, e gli identificatori di correlazione :old e :new (e :parent), possono essere utilizzati solo se il corpo del trigger è un blocco PLSQL completo e non una dichiarazione CALL. Privilegi di trigger Esistono cinque privilegi di sistema che si applicano ai trigger, descritti nella Tabella Oltre a questi, il possessore di un trigger deve avere i privilegi di oggetto necessari sugli oggetti a cui fa riferimento il trigger. Poiché un trigger è un oggetto compilato, tali privilegi devono essere concessi direttamente e non attraverso un ruolo (i trigger sono definiti solo con diritti di definitore). Trigger e dizionario di dati Simili ai sottoprogrammi memorizzati, alcune viste di dizionario di dati contengono informazioni sui trigger e sul loro stato. Tali viste vengono aggiornate ogniqualvolta un trigger viene creato o eliminato. Tabella 10.8 Privilegi di sistema relativi ai trigger. PRIVILEGIO DI SISTEMA CREATE TRIGGER CREATE ANY TRIGGER ALTER ANY TRIGGER DESCRIZIONE Consente al concessionari di creare un trigger nel proprio schema. Consente al concessionario di creare trigger in qualsiasi schema ad eccezione di SYS. È sconsigliato creare trigger su tabelle di dizionari di dati. Consente al concessionario di abilitare, disabilitare o compilare trigger di database in qualsiasi schema ad eccezione di SYS. Si noti che se il con cessionario non ha CREATE ANY TRIGGER, non può modificare il codice del trigger. (segue)
38 434 CAPITOLO 10 Tabella 10.8 Privilegi di sistema relativi ai trigger. (continua) PRIVILEGIO DI SISTEMA DESCRIZIONE DROP ANY TRIGGER ADMINISTER DATABASE TRIGGER Consente al concessionario di eliminare trigger di database in qualsiasi schema ad eccezione di SYS. Consente al concessionario di creare o modificare un trigger di sistema sul database (al contrario dello schema corrente). Il concessionario deve anche avere CREATE TRIGGER o CREATE ANY TRIGGER. Viste di dizionari di dati Quando un trigger viene creato, il suo codice sorgente è memorizzato nella vista di dizionario di dati user _ triggers. Questa vista comprende il corpo del trigger, la clausola WHEN, la tabella attivante e il tipo di trigger. Per esempio, la seguente query formattata restituisce informazioni su UpdateMajorStats dopo l esecuzione dello script GenerateAuthorID.sql nello schema UserA: COL table_name FORMAT A10 COL triggering_event FORMAT A20 SELECT trigger_type, table_name, triggering_event FROM user_triggers WHERE trigger_name = GENERATEAUTHORID ; Nell output della query si vedranno il tipo di trigger, il nome di tabella e l evento attivante. TRIGGER_TYPE TABLE_NAME TRIGGERING_EVENT BEFORE EACH ROW AUTHORS INSERT OR UPDATE La vista user _ triggers contiene informazioni sui trigger posseduti dall utente corrente. Esistono anche altre due viste: all _ triggers contiene informazioni sui trigger accessibili all utente corrente (ma che potrebbero essere posseduti da un utente diverso) e dba _ triggers contiene informazioni su tutti i trigger nel database. Eliminazione e disabilitazione di trigger Come procedure e package, i trigger possono essere eliminati, con la sintassi indicata di seguito: DROP TRIGGER nometrigger; dove nometrigger è il nome del trigger da eliminare. Questo elimina definitivamente il trigger dal dizionario di dati. Come nei sottoprogrammi, può essere specificata la clausola OR REPLACE nella dichiarazione CREATE per il trigger. In tal caso il trigger viene prima eliminato, se esiste. A differenza di procedure e package, tuttavia, un trigger può essere disabilitato senza essere eliminato. Quando un trigger viene disabilitato, esiste
39 TRIGGER DI DATABASE 435 ancora nel dizionario di dati, ma non viene mai attivato. Per disabilitare un trigger, utilizzare la dichiarazione ALTER TRIGGER: ALTER TRIGGER nometrigger {DISABLE ENABLE}; dove nometrigger è il nome del trigger. Per impostazione predefinita tutti i trigger sono abilitati al momento della loro creazione. ALTER TRIGGER può disabilitare e quindi abilitare nuovamente qualsiasi trigger. Per esempio, il seguente codice disabilita e quindi abilita nuovamente UpdateMajorStats: ALTER TRIGGER GenerateAuthorID DISABLE; ALTER TRIGGER GenerateAuthorID ENABLE; Tutti i trigger per una particolare tabella possono essere abilitati o disabilitati utilizzando il comando ALTER TABLE, aggiungendo la clausola ENABLE ALL TRIGGERS o DISABILE ALL TRIGGERS. Per esempio: ALTER TABLE authors ENABLE ALL TRIGGERS; ALTER TABLE authors DISABLE ALL TRIGGERS; La colonna status di user _ triggers contiene ENABLED o DISABLED, a indicare lo stato corrente di un trigger. La disabilitazione di un trigger non lo elimina dal dizionario di dati. Per controllare lo stato è possibile utilizzare la seguente query: SELECT nome_trigger, status FROM user_triggers WHERE trigger_name = trigger_name ; P-code di trigger Quando un package o un sottoprogramma viene memorizzato nel dizionario di dati, oltre al codice sorgente per l oggetto viene memorizzato il p-code compilato. Questo vale anche per i trigger, quindi i trigger possono essere chiamati senza ricompilazione, e vengono memorizzate le informazioni di dipendenza. Di conseguenza possono essere automaticamente invalidati allo stesso modo di package e sottoprogrammi. Quando un trigger viene invalidato, sarà ricompilato alla nuova attivazione Tabelle mutanti Esistono limitazioni su tabelle e colonne a cui può accedere il corpo di un trigger. Per definire tali limitazioni, è necessario comprendere le tabelle mutanti e limitanti. Una tabella mutante è una tabella che viene modificata da una
40 436 CAPITOLO 10 dichiarazione DML. Per un trigger, questa è la tabella su cui viene definito il trigger. Anche le tabelle che possono avere necessità di essere aggiornate come risultato di una limitazione di integrità referenziale DELETE CASCADE sono mutanti. Una tabella limitante è una tabella che può avere necessità di essere letta da una limitazione di integrità referenziale. Per illustrare queste definizioni, si considerino le tabelle students, classes e registered _ students. Le tabelle students e classes non hanno dipendenze, ma la tabella registered _ students ha due dipendenze di chiave esterna. Una dipendenza è sulla chiave primaria della tabella students, l altra sulla chiave primaria della tabella classes. Questo garantisce integrità referenziale a livello di database, ma porta un sovraccarico di elaborazione. È possibile eseguire tutti gli script di esempio utilizzando lo script createobjects.sql. -- Disponibile online come parte di of createstudents.sql CREATE TABLE students ( id NUMBER(5) NOT NULL, current_credits NUMBER(2), major VARCHAR2(20), last_name VARCHAR2(20) NOT NULL, first_name VARCHAR2(20) NOT NULL, middle_initial VARCHAR2(1) NOT NULL, CONSTRAINT students_pk PRIMARY KEY (id)); -- Disponibile online come parte di of createclasses.sql CREATE TABLE classes ( department CHAR(3) NOT NULL, course NUMBER(3) NOT NULL, current_students NUMBER(3) NOT NULL, num_credits NUMBER(1) NOT NULL, name VARCHAR2(30) NOT NULL, CONSTRAINT classes_pk PRIMARY KEY (department,course)); -- Disponibile online come parte di of createregisteredstudents.sql CREATE TABLE registered_students ( student_id NUMBER(5) NOT NULL, department CHAR(3) NOT NULL, course NUMBER(3) NOT NULL, grade CHAR(1), CONSTRAINT rs_grade CHECK (grade IN ( A, B, C, D, F )), CONSTRAINT rs_student_id FOREIGN KEY (student_id) REFERENCES students (id), CONSTRAINT rs_department_course FOREIGN KEY (department, course) REFERENCES classes (department, course)); registered _ students ha due limitazioni di integrità referenziale dichiarative. Come tale, sia students sia classes sono tabelle limitanti per registered _ students. A causa delle limitazioni, classes e students possono avere necessità di essere modificate eo interrogate dalla dichiarazione DML.
41 TRIGGER DI DATABASE 437 Inoltre registered _ students stessa è mutante durante l esecuzione di una dichiarazione DML su di essa. Le dichiarazioni SQL in un corpo di trigger non possono: leggere o modificare alcuna tabella mutante della dichiarazione di attivazione. Questo comprende la tabella attivante stessa; leggere da o modificare le colonne di chiave primaria, unica o esterna di una tabella limitante della tabella attivante. Tuttavia possono modificare le altre colonne. Tali limitazioni valgono per tutti i trigger a livello di riga; valgono per trigger di dichiarazione solo quando il trigger di dichiarazione sarebbe attivato come risultato di un operazione DELETE CASCADE. NOTA Se una dichiarazione INSERT interessa solo una riga, i trigger before e after riga per tale riga non trattano la tabella attivante come mutante. Questo è l unico caso in cui un trigger a livello di riga può leggere o modificare la tabella attivante. Dichiarazioni quali INSERT INTO table SELECT... trattano sempre la tabella attivante come mutante, anche se la sottoquery restituisce una sola riga. Come esempio, si consideri il trigger CascadeRSInserts, mostrato di seguito. Anche se modifica students e classes, è legale perché le colonne in students e classes modificate non sono colonne chiave. Nel prossimo paragrafo si esaminerà un trigger illegale. -- Disponibile online come cascadersinsert.sql CREATE OR REPLACE TRIGGER CascadeRSInserts * Mantiene le tabelle registered_students, students e classes sincronizzate quando viene fatto un INSERT in registered_students. * BEFORE INSERT ON registered_students FOR EACH ROW DECLARE v_credits classes.num_credits%type; -- Determina il numero di crediti per questa classe. SELECT num_credits INTO v_credits FROM classes WHERE department = :new.department AND course = :new.course; -- Modifica i crediti correnti per questo studente. UPDATE students SET current_credits = current_credits + v_credits WHERE ID = :new.student_id; -- Aggiunge uno al numero di studenti nella classe. UPDATE classes
42 438 CAPITOLO 10 SET current_students = current_students + 1 WHERE department = :new.department AND course = :new.course; END CascadeRSInserts; Esempio di tabella mutante Si supponga di voler limitare a cinque il numero di studenti in ciascuna specializzazione. Si potrebbe fare con un trigger a livello di riga before INSERT o UPDATE su students, indicato di seguito: -- Disponibile online come parte di of limitmajors.sql CREATE OR REPLACE TRIGGER LimitMajors * Limita a 5 il numero di studenti in ciascuna specializzazione. Se tale limite viene superato, viene sollevato un errore con raise_application_error. * BEFORE INSERT OR UPDATE OF major ON students FOR EACH ROW DECLARE v_maxstudents CONSTANT NUMBER := 5; v_currentstudents NUMBER; -- Determina il numero corrente di studenti in questa -- specializzazione. SELECT COUNT(*) INTO v_currentstudents FROM students WHERE major = :new.major; -- Se non c e spazio, solleva un errore. IF v_currentstudents + 1 > v_maxstudents THEN RAISE_APPLICATION_ERROR(-20000, Too many students in major :new.major); END IF; END LimitMajors; A un primo sguardo, questo trigger sembra ottenere il risultato desiderato. Tuttavia, se si cerca di aggiornare students, attiverà il trigger LimitMajor. Sarà necessario popolare le tabelle con dati prima di provare la dichiarazione di aggiornamento. Questo può essere fatto eseguendo insertacademicrecords. sql, oppure eseguendo nuovamente createobjects.sql. -- Disponibile online come parte di of limitmajors.sql UPDATE students SET major = History WHERE id = 1;
43 TRIGGER DI DATABASE 439 Il trigger LimitMajor solleverà la seguente eccezione: UPDATE students * ERROR at line 1: ORA-04091: table USERA.STUDENTS is mutating, triggerfunction may not see it ORA-06512: at USERA.LIMITMAJORS, line 7 ORA-04088: error during execution of trigger USERA.LIMITMAJORS L errore ORA-4091 si verifica perché LimitMajors interroga la propria tabella attivante, che è mutante. ORA-4091 viene sollevato quando il trigger viene attivato, non quando viene creato. Soluzione per l errore di tabella mutante Students è mutante solo per un trigger a livello di riga. Questo significa che non è possibile interrogarla in un trigger a livello di riga, ma è possibile farlo in un trigger a livello di dichiarazione. Tuttavia non è possibile semplicemente rendere LimitMajors un trigger a livello di dichiarazione, poiché nel corpo del trigger è necessario utilizzare il valore di :new.major. La soluzione è la creazione di due trigger: uno a livello di riga e uno a livello di dichiarazione. Nel trigger a livello di riga si registra il valore di :new.major, ma non si interroga students; la query viene effettuata nel trigger a livello di dichiarazione che utilizza il valore registrato nel trigger di riga. Come si registra tale valore? Un modo è l utilizzo di una tabella PLSQL in un package. In questo modo è possibile salvare più valori per ciascun aggiornamento. Inoltre ogni sessione prende la propria istanziazione di variabili in package, quindi non ci si deve preoccupare di aggiornamenti contemporanei da parte di sessioni diverse. Questa soluzione è implementata con il package student _ data e i trigger RLimitMajors e SLimitMajors: -- Disponibile online come parte di of createnonmutating.sql CREATE OR REPLACE PACKAGE StudentData AS TYPE t_majors IS TABLE OF students.major%type INDEX BY BINARY_INTEGER; TYPE t_ids IS TABLE OF students.id%type INDEX BY BINARY_INTEGER; v_studentmajors t_majors; v_studentids t_ids; v_numentries BINARY_INTEGER := 0; END StudentData; CREATE OR REPLACE TRIGGER RLimitMajors BEFORE INSERT OR UPDATE OF major ON students FOR EACH ROW
44 440 CAPITOLO 10 * Registra i nuovi dati in StudentData. Non si fanno modifiche a students, per evitare l errore ORA * StudentData.v_NumEntries := StudentData.v_NumEntries + 1; StudentData.v_StudentMajors(StudentData.v_NumEntries) := :new.major; StudentData.v_StudentIDs(StudentData.v_NumEntries) := :new.id; END RLimitMajors; CREATE OR REPLACE TRIGGER SLimitMajors AFTER INSERT OR UPDATE OF major ON students DECLARE v_maxstudents CONSTANT NUMBER := 2; v_currentstudents NUMBER; v_studentid students.id%type; v_major students.major%type; * Scorre in ogni studente inserito o aggiornato e verifica di essere ancora nel limite. * FOR v_loopindex IN 1..StudentData.v_NumEntries LOOP v_studentid := StudentData.v_StudentIDs(v_LoopIndex); v_major := StudentData.v_StudentMajors(v_LoopIndex); -- Determina il numero corrente di studenti in questa specializzazione. SELECT COUNT(*) INTO v_currentstudents FROM students WHERE major = v_major; -- Se non c e spazio, solleva un errore. IF v_currentstudents > v_maxstudents THEN RAISE_APPLICATION_ERROR(-20000, Too many students for major v_major because of student v_studentid); END IF; END LOOP; -- Reimposta il contatore, quindi la prossima esecuzione usera nuovi dati. StudentData.v_NumEntries := 0; END SlimitMajors; NOTA Prima di eseguire lo script indicato in precedenza, eliminare il trigger LimitMajors errato. Ora è possibile provare questa serie di trigger aggiornando students fino ad avere troppi specializzandi in storia. Questo si può fare utilizzando lo script testnonmutating.sql o scrivendo la seguente dichiarazione di aggiornamento:
45 TRIGGER DI DATABASE Disponibile online come parte di of testnonmutating.sql UPDATE students SET major = History WHERE id IN (1,2,3); Nel trigger SlimitMajors il limite di specializzazioni è impostato a due. La dichiarazione di aggiornamento cerca di inserire nel sistema tre specializzandi in storia. Fallisce con il seguente messaggio di errore: UPDATE students * ERROR at line 1: ORA : Too many students for major History because of student 2 ORA-06512: at USERA.SLIMITMAJORS, line 21 ORA-04088: error during execution of trigger USERA.SLIMITMAJORS Questo è il comportamento desiderato. Questa tecnica può essere applicata alle occorrenze di ORA-4091 quando un trigger a livello di riga legge da o modifica una tabella mutante. Invece di effettuare l elaborazione illegale nel trigger a livello di riga, si deferisce l elaborazione a un trigger a livello di dichiarazione after, dove è legale. Le tabelle PLSQL in package sono utilizzate per memorizzare le righe che sono state modificate. Esistono diverse cose da notare rispetto a questa tecnica: le tabelle PLSQL sono contenute in un package, in modo che saranno visibili ai trigger a livello di riga e a livello di dichiarazione. L unico modo per garantire che le variabili siano globali è inserirle in un package; viene utilizzata una variabile di contatore, StudentData.v _ NumEntries. Questa è inizializzata su zero quando viene creato il package. Viene incrementata dal trigger a livello di riga. Il trigger a livello di dichiarazione fa riferimento ad essa e quindi la reimposta a zero dopo l elaborazione. Questo è necessario affinché la prossima dichiarazione UPDATE emessa da questa sessione abbia il valore corretto; il controllo in SLimitMajors del numero massimo di studenti doveva essere leggermente modificato. Poiché ora è un trigger di dichiarazione after, v_currentstudents conterrà il numero di studenti nella specializzazione dopo l inserimento o l aggiornamento, non prima. Quindi il controllo per v _ CurrentStudents + 1, effettuato in LimitMajors, è sostituito da v_currentstudents; invece di tabelle PLSQL si sarebbe potuta utilizzare una tabella di database. Non si consiglia questa tecnica, perché sessioni contemporanee che emettano un UPDATE interferirebbero tra di loro (in Oracle8i e successivi, tuttavia, si può utilizzare una tabella temporanea). Le tabelle PLSQL in package sono uniche tra sessioni, il che evita il problema.
46 442 CAPITOLO Sommario Come si è visto, i trigger sono un aggiunta importante a PLSQL e Oracle. Possono essere utilizzati per rispettare limitazioni sui dati molto più complesse delle normali limitazioni di integrità referenziali, oltre a implementare il comportamento corretto per viste complesse. Le funzioni di attributo di eventi possono essere utilizzate per i trigger di sistema, per determinare tutti i tipi di informazioni sull evento attivante e sulla situazione che lo ha causato. Nel prossimo capitolo si comincerà la discussione sui package incorporati con la comunicazione tra sessioni.
Basi di dati. Il Linguaggio SQL. K. Donno - Il Linguaggio SQL
Basi di dati Il Linguaggio SQL Data Definition Language (DDL) Data Definition Language: insieme di istruzioni utilizzate per modificare la struttura della base di dati Ne fanno parte le istruzioni di inserimento,
PL/SQL PL/SQL. Ordine degli elementi dei triggers di Oracle. Differenze nei triggers. Versione dei trigger e PSM di Oracle
Versione dei trigger e PSM di Oracle Lucidi derivati da quelli di Jeffrey D Ullman Oracle usa una variante di SQL/PSM che si chiama non consente solo di creare e memorizzare procedure e funzioni, ma puo
Il linguaggio SQL. è di fatto lo standard tra i linguaggi per la gestione di data base relazionali.
(Structured Query Language) : Il linguaggio è di fatto lo standard tra i linguaggi per la gestione di data base relazionali. prima versione IBM alla fine degli anni '70 per un prototipo di ricerca (System
DDL, VINCOLI D INTEGRITÁ, AGGIORNAMENTI E VISTE. SQL è più di un semplice linguaggio di interrogazione
SQL DDL, VINCOLI D INTEGRITÁ, AGGIORNAMENTI E VISTE SQL è più di un semplice linguaggio di interrogazione! Linguaggio di definizione dati (Data-definition language, DDL):! Crea/distrugge/modifica relazioni
Esercitazione query in SQL L esercitazione viene effettuata sul database viaggi e vacanze che prevede il seguente modello E/R:
Esercitazione query in SQL L esercitazione viene effettuata sul database viaggi e vacanze che prevede il seguente modello E/R: Si consiglia di creare il data base, inserire i dati nelle tabelle, provare
Lezione 8. Metadati, Viste e Trigger
Lezione 8 Metadati, Viste e Trigger Pag.1 Metadati e catalogo di sistema I metadati sono dati a proposito dei dati (quali tabelle esistono?, quali campi contengono?, quante tuple contengono?, ci sono vincoli
Nozione ed uso. Operazioni eseguite automaticamente ogni volta che avviene un certo evento Uso:
Nozione ed uso Operazioni eseguite automaticamente ogni volta che avviene un certo evento Uso: Gestione di vincoli di integrità: Per fallimento Per modifica Auditing: Sicurezza Statistiche Valori derivati
Insegnamento di Informatica CdS Scienze Giuridiche A.A. 2006/7. Il trattamento dei dati
Insegnamento di Informatica CdS Scienze Giuridiche A.A. 2006/7 Il trattamento dei dati database: il linguaggio SQL seconda parte Prof. Valle D.ssa Folgieri Lez9 15.11.06 Trattamento dati. Database: il
Definizione di domini
Definizione di domini Come nei linguaggi ad alto livello (es. C) è possibile definire nuovi domini (tipi di dati) a partire da quelli predefiniti, anche se il costruttore è più limitato. create domain
Dispensa di database Access
Dispensa di database Access Indice: Database come tabelle; fogli di lavoro e tabelle...2 Database con più tabelle; relazioni tra tabelle...2 Motore di database, complessità di un database; concetto di
Capitolo 13. Interrogare una base di dati
Capitolo 13 Interrogare una base di dati Il database fisico La ridondanza è una cosa molto, molto, molto brutta Non si devono mai replicare informazioni scrivendole in più posti diversi nel database Per
MySQL Database Management System
MySQL Database Management System http://www.mysql.com/ DATABASE RELAZIONALI Un database è una collezione strutturata di informazioni. I database sono delle strutture nelle quali è possibile memorizzare
Il linguaggio SQL: trigger. Versione elettronica: 04.7.SQL.trigger.pdf
Il linguaggio SQL: trigger Sistemi Informativi T Versione elettronica: 04.7.SQL.trigger.pdf DBMS attivi Un DBMS si dice attivoquando dispone di un sottosistema integrato per definire e gestire regole I
Basi di Dati: Corso di laboratorio
Basi di Dati: Corso di laboratorio Lezione 2 Raffaella Gentilini 1 / 45 Sommario 1 Il DDL di SQL: Cancellazione ed Aggiornamento di una BD Cancellazione di Schemi, Tabelle, e Domini Aggiornamento di Tabelle
Al giorno d oggi, i sistemi per la gestione di database
Introduzione Al giorno d oggi, i sistemi per la gestione di database implementano un linguaggio standard chiamato SQL (Structured Query Language). Fra le altre cose, il linguaggio SQL consente di prelevare,
DBMS (Data Base Management System)
Cos'è un Database I database o banche dati o base dati sono collezioni di dati, tra loro correlati, utilizzati per rappresentare una porzione del mondo reale. Sono strutturati in modo tale da consentire
Corso Sistemi Informativi Avanzati. Programma 30 set 2015. Installazione Macchina Virtuale. Introduzione alla BI nelle Aziende.
Programma 30 set 205 Installazione Macchina Virtuale Introduzione alla BI nelle Aziende Introduzione SQL Macchina Virtuale È un emulazione di un computer su un altro computer Stesso punto di partenza per
Manuale Amministratore Legalmail Enterprise. Manuale ad uso degli Amministratori del Servizio Legalmail Enterprise
Manuale Amministratore Legalmail Enterprise Manuale ad uso degli Amministratori del Servizio Legalmail Enterprise Pagina 2 di 16 Manuale Amministratore Legalmail Enterprise Introduzione a Legalmail Enterprise...3
Volumi di riferimento
Simulazione seconda prova Esame di Stato Gestione di un centro agroalimentare all ingrosso Parte prima) Un nuovo centro agroalimentare all'ingrosso intende realizzare una base di dati per l'attività di
GESGOLF SMS ONLINE. Manuale per l utente
GESGOLF SMS ONLINE Manuale per l utente Procedura di registrazione 1 Accesso al servizio 3 Personalizzazione della propria base dati 4 Gestione dei contatti 6 Ricerca dei contatti 6 Modifica di un nominativo
Basi di Dati. S Q L Lezione 5
Basi di Dati S Q L Lezione 5 Antonio Virdis [email protected] Sommario Gestione eventi Gestione dei privilegi Query Complesse 2 Esercizio 9 (lezione 4) Indicare nome e cognome, spesa e reddito annuali
Operazioni sui database
Operazioni sui database Le operazioni nel modello relazionale sono essenzialmente di due tipi: Operazioni di modifica della base di dati (update) Interrogazioni della base di dati per il recupero delle
2104 volume III Programmazione
2103 SQLite Capitolo 77 77.1 Utilizzo generale................................. 2104 77.1.1 Utilizzo di sqlite3».......................... 2104 77.1.2 Copie di sicurezza............................ 2106
Soluzione dell esercizio del 2 Febbraio 2004
Soluzione dell esercizio del 2 Febbraio 2004 1. Casi d uso I casi d uso sono riportati in Figura 1. Figura 1: Diagramma dei casi d uso. E evidenziato un sotto caso di uso. 2. Modello concettuale Osserviamo
OSSIF WEB. Manuale query builder
OSSIF WEB Manuale query builder - Maggio 2010 1) Sommario 1) SOMMARIO... 2 INTRODUZIONE... 3 Scopo del documento... 3 Struttura del documento... 3 Descrizione dell interfaccia grafica... 3 SELEZIONE DI
INFORMATICA. Applicazioni WEB a tre livelli con approfondimento della loro manutenzione e memorizzazione dati e del DATABASE.
INFORMATICA Applicazioni WEB a tre livelli con approfondimento della loro manutenzione e memorizzazione dati e del DATABASE. APPLICAZIONI WEB L architettura di riferimento è quella ampiamente diffusa ed
Join in SQL (primo modo) Informatica. Tabella Dipartimento. Interrogazione 4a. Interrogazione 4b. Interrogazione 4a
Join in SQL (primo modo) Informatica Lezione 7 Laurea magistrale in Psicologia Laurea magistrale in Psicologia dello sviluppo e dell'educazione Anno accademico: 09- Per formulare interrogazioni che coinvolgono
5.3 TABELLE 5.3.1 RECORD 5.3.1.1 Inserire, eliminare record in una tabella Aggiungere record Eliminare record
5.3 TABELLE In un sistema di database relazionali le tabelle rappresentano la struttura di partenza, che resta poi fondamentale per tutte le fasi del lavoro di creazione e di gestione del database. 5.3.1
Data Base. Master "Bio Info" Reti e Basi di Dati Lezione 6
Data Base 1 Sommario I concetti fondamentali. Database Relazionale.. Query e SQL MySql, Creazione di un db in MySQL con PHPmyAdmin Creazione database e delle Tabelle Query Inserimento Ricerca Modifica
Abilità Informatiche A.A. 2010/2011 Lezione 9: Query Maschere Report. Facoltà di Lingue e Letterature Straniere
Abilità Informatiche A.A. 2010/2011 Lezione 9: Query Maschere Report Facoltà di Lingue e Letterature Straniere Le QUERY 2 Che cos è una Query? Una Query rappresenta uno strumento per interrogare un database.
SQL non è solo un linguaggio di interrogazione (Query Language), ma. Un linguaggio per la definizione di basi di dati (Data-definition language (DDL))
SQL PER LA DEFINIZIONE DI BASI DI DATI 1 SQL non è solo un linguaggio di interrogazione (Query Language), ma Un linguaggio per la definizione di basi di dati (Data-definition language (DDL)) CREATE SCHEMA
Progetto NoiPA per la gestione giuridicoeconomica del personale delle Aziende e degli Enti del Servizio Sanitario della Regione Lazio
Progetto NoiPA per la gestione giuridicoeconomica del personale delle Aziende e degli Enti del Servizio Sanitario della Regione Lazio Pillola operativa Integrazione Generazione Dettagli Contabili INFORMAZIONI
Giovanna Rosone 04/03/2010. 04/03/2010 SQL, Istruzioni per la modifica dello schema
Giovanna Rosone 04/03/2010 04/03/2010 SQL, Istruzioni per la modifica dello schema 1 Riepilogo Impiegato Pagamenti Nome colonna PAG_COD PAG_MATR Tipo dati CHAR(6) CHAR(6) Nome colonna Tipo dati PAG_STIPENDIO
GERARCHIE RICORSIVE - SQL SERVER 2008
GERARCHIE RICORSIVE - SQL SERVER 2008 DISPENSE http://dbgroup.unimo.it/sia/gerarchiericorsive/ L obiettivo è quello di realizzare la tabella di navigazione tramite una query ricorsiva utilizzando SQL SERVER
ESEMPI DI QUERY SQL. Esempi di Query SQL Michele Batocchi AS 2012/2013 Pagina 1 di 7
ESEMPI DI QUERY SQL Dati di esempio... 2 Query su una sola tabella... 2 Esempio 1 (Ordinamento)... 2 Esempio 2 (Scelta di alcune colonne)... 3 Esempio 3 (Condizioni sui dati)... 3 Esempio 4 (Condizioni
Riccardo Dutto, Paolo Garza Politecnico di Torino. Riccardo Dutto, Paolo Garza Politecnico di Torino
Integration Services Project SQL Server 2005 Integration Services Permette di gestire tutti i processi di ETL Basato sui progetti di Business Intelligence di tipo Integration services Project SQL Server
ROUTINE E PROGRAMMAZIONE
LEZIONE-TSQL-02 TRIGGER E PROCEDURE (VER03 PAG. 1 / 6 LEZIONE-TSQL-02 TRIGGER E PROCEDURE (VER03 T-SQL PROGRAMMAZIONE PARTE SECONDA ROUTINE E PROGRAMMAZIONE In TSQL è possibile definire alcune routine
Suggerimenti per lo Sviluppo delle Applicazioni con PL/SQL. Simona Rotolo
Suggerimenti per lo Sviluppo delle Applicazioni con PL/SQL Simona Rotolo 2 Questo documento, rivolto a chi sviluppa codice in PL/Sql, è stato redatto al fine di fornire degli standard di sviluppo che aiuteranno
GUIDA RAPIDA PER LA COMPILAZIONE DELLA SCHEDA CCNL GUIDA RAPIDA PER LA COMPILAZIONE DELLA SCHEDA CCNL
GUIDA RAPIDA BOZZA 23/07/2008 INDICE 1. PERCHÉ UNA NUOVA VERSIONE DEI MODULI DI RACCOLTA DATI... 3 2. INDICAZIONI GENERALI... 4 2.1. Non modificare la struttura dei fogli di lavoro... 4 2.2. Cosa significano
Esercizio data base "Biblioteca"
Rocco Sergi Esercizio data base "Biblioteca" Database 2: Biblioteca Testo dell esercizio Si vuole realizzare una base dati per la gestione di una biblioteca. La base dati conterrà tutte le informazioni
Lezione V. Aula Multimediale - sabato 29/03/2008
Lezione V Aula Multimediale - sabato 29/03/2008 LAB utilizzo di MS Access Definire gli archivi utilizzando le regole di derivazione e descrivere le caratteristiche di ciascun archivio ASSOCIAZIONE (1:1)
Database 1 biblioteca universitaria. Testo del quesito
Database 1 biblioteca universitaria Testo del quesito Una biblioteca universitaria acquista testi didattici su indicazione dei professori e cura il prestito dei testi agli studenti. La biblioteca vuole
COLLI. Gestione dei Colli di Spedizione. Release 5.20 Manuale Operativo
Release 5.20 Manuale Operativo COLLI Gestione dei Colli di Spedizione La funzione Gestione Colli consente di generare i colli di spedizione in cui imballare gli articoli presenti negli Ordini Clienti;
FIRESHOP.NET. Gestione completa delle fidelity card & raccolta punti. Rev. 2014.3.1 www.firesoft.it
FIRESHOP.NET Gestione completa delle fidelity card & raccolta punti Rev. 2014.3.1 www.firesoft.it Sommario SOMMARIO Introduzione... 3 La gestione delle fidelity card nel POS... 4 Codificare una nuova fidelity
SQL: concetti base SQL. Definizione dei dati in SQL. SQL: "storia"
SQL SQL: concetti base originariamente "Structured Query Language", ora "nome proprio" linguaggio con varie funzionalità: contiene sia il DDL sia il DML ne esistono varie versioni vediamo gli aspetti essenziali,
Uso delle basi di dati DBMS. Cos è un database. DataBase. Esempi di database
Uso delle basi di dati Uso delle Basi di Dati Il modulo richiede che il candidato comprenda il concetto di base dati (database) e dimostri di possedere competenza nel suo utilizzo. Cosa è un database,
Oracle PL/SQL. Motivazioni
Oracle PLSQL Motivazioni Supponiamo che nella gestione del database Azienda ci venga chiesto di apportare le modifiche necessarie a far sì che ad ogni impiegato possa essere assegnato, alla fine di ogni
I file di dati. Unità didattica D1 1
I file di dati Unità didattica D1 1 1) I file sequenziali Utili per la memorizzazione di informazioni testuali Si tratta di strutture organizzate per righe e non per record Non sono adatte per grandi quantità
SQL PER LA DEFINIZIONE DI BASI DI DATI
SQL PER LA DEFINIZIONE DI BASI DI DATI SQL non è solo un linguaggio di interrogazione (Query Language), ma Un linguaggio per la definizione di basi di dati (Data-definition language (DDL)) CREATE SCHEMA
Access. P a r t e p r i m a
Access P a r t e p r i m a 1 Esempio di gestione di database con MS Access 2 Cosa è Access? Access e un DBMS che permette di progettare e utilizzare DB relazionali Un DB Access e basato sui concetti di
Nella relazione CINEMA, Nome è chiave secondaria. Nella relazione FILM, CodRegista, e CodProtagonista sono chiavi esterne sulla tabella PERSONE.
Si consideri il seguente schema relazionale, relaivo ad una base di dati per gestire la programmazione cinematografica giornaliera in un certo insieme di cinema: CINEMA(CodC, Nome, Indirizzo, Tel, NSale)
LA GESTIONE DELLE VISITE CLIENTI VIA WEB
LA GESTIONE DELLE VISITE CLIENTI VIA WEB L applicazione realizzata ha lo scopo di consentire agli agenti l inserimento via web dei dati relativi alle visite effettuate alla clientela. I requisiti informatici
Triggers. Basi dati attive. Trigger. Indipendenza della conoscenza
Basi dati attive Triggers Antonella Poggi Domenico Lembo Dipartimento di informatica e Sistemistica SAPIENZA Università di Roma Progetto di Applicazioni Software Anno accademico 2009-2010 Una base di dati
Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:
Tipi primitivi Il linguaggio Java offre alcuni tipi di dato primitivi Una variabile di tipo primitivo può essere utilizzata direttamente. Non è un riferimento e non ha senso tentare di istanziarla mediante
Sistema Informativo Gestione Fidelizzazione Clienti MANUALE D USO
Sistema Informativo Gestione Fidelizzazione Clienti MANUALE D USO Login All apertura il programma controlla che sia stata effettuata la registrazione e in caso negativo viene visualizzato un messaggio.
Le Basi di Dati. Le Basi di Dati
Le Basi di Dati 20/05/02 Prof. Carlo Blundo 1 Le Basi di Dati Le Base di Dati (database) sono un insieme di tabelle di dati strutturate in maniera da favorire la ricerca di informazioni specializzate per
Gestione delle tabelle
Linguaggio SQL: fondamenti Creazione di una tabella Modifica della struttura di una tabella Cancellazione di una tabella Dizionario dei dati Integrità dei dati 2 Creazione di una tabella (1/3) Si utilizza
Database. Si ringrazia Marco Bertini per le slides
Database Si ringrazia Marco Bertini per le slides Obiettivo Concetti base dati e informazioni cos è un database terminologia Modelli organizzativi flat file database relazionali Principi e linee guida
Regione Toscana. ARPA Fonte Dati. Manuale Amministratore. L. Folchi (TAI) Redatto da
ARPA Fonte Dati Regione Toscana Redatto da L. Folchi (TAI) Rivisto da Approvato da Versione 1.0 Data emissione 06/08/13 Stato DRAFT 1 Versione Data Descrizione 1,0 06/08/13 Versione Iniziale 2 Sommario
SOSEBI PAPERMAP2 MODULO WEB MANUALE DELL UTENTE
SOSEBI PAPERMAP2 MODULO WEB MANUALE DELL UTENTE S O. S E. B I. P R O D O T T I E S E R V I Z I P E R I B E N I C U L T U R A L I So.Se.Bi. s.r.l. - via dell Artigianato, 9-09122 Cagliari Tel. 070 / 2110311
MySQL Database Management System
MySQL Database Management System II parte Progetto gestione booking prenotazioni on-line 1. Progettazione e creazione struttura database che chiameremo booking. 2. Progettazione e creazione di un form
DBMS. Esempi di database. DataBase. Alcuni esempi di DBMS DBMS. (DataBase Management System)
(DataBase Management System) Sistemi di ges3one di basi di da3 Un Database Management System è un sistema software progettato per consentire la creazione e manipolazione efficiente di database (collezioni
Utilizzando Microsoft Access. Si crea la tabella Anagrafica degli alunni,le Materie e i voti si mettono alcuni campi
Vogliamo creare una struttura per permettere di memorizzari i voti della classe in tutte le materie Per fare questo untilizziamo tre tabelle Alunni,materie,voti Alunni Materie Voti Creo un record per ogni
Organizzazione degli archivi
COSA E UN DATA-BASE (DB)? è l insieme di dati relativo ad un sistema informativo COSA CARATTERIZZA UN DB? la struttura dei dati le relazioni fra i dati I REQUISITI DI UN DB SONO: la ridondanza minima i
Appunti di MySql. Evoluzione di un tutorial di base di mysql, scritto da Etel Sverdlov.
Appunti di MySql Evoluzione di un tutorial di base di mysql, scritto da Etel Sverdlov. Indice generale avviare la shell mysql...2 comandi SQL per la gestione del database (DDL)...2 visualizzare l'elenco
Corso sul linguaggio SQL
Corso sul linguaggio SQL Modulo L2B (SQL) 2.2 Comandi sulle tabelle 1 Prerequisiti Introduzione ai DB Tabelle, relazioni e attributi Chiave primaria Chiave esterna Vincoli di integrità 2 1 Introduzione
Sistemi per la gestione di database: MySQL ( )
Sistemi per la gestione di database: MySQL ( ) Relational Database e Relational Database Management System Un database è una raccolta di dati organizzata in modo da consentire l accesso, il reperimento
CONCETTO DI ANNIDAMENTO
LEZIONE14 SQL ANNIDAMENTI PAG. 1 / 5 PROF. ANDREA ZOCCHEDDU LEZIONE14 SQL ANNIDAMENTI CONCETTO DI ANNIDAMENTO LINGUAGGIO SQL QUERY ANNIDATE Per annidamento si intende la possibilità che, all interno di
Funzioni in C. Violetta Lonati
Università degli studi di Milano Dipartimento di Scienze dell Informazione Laboratorio di algoritmi e strutture dati Corso di laurea in Informatica Funzioni - in breve: Funzioni Definizione di funzioni
Esercitazione 1. Sistemi Informativi T. Versione elettronica: L01.2.DDLDMLbase.pdf
Esercitazione 1 SQL: DDL e DML di base Sistemi Informativi T Versione elettronica: L01.2.DDLDMLbase.pdf Prime cose da fare Fare login sul PC usando lo username di Facoltà Procedura descritta qui: http://ccib.ing.unibo.it/content/account
Informatica per le discipline umanistiche 2 lezione 10
Informatica per le discipline umanistiche 2 lezione 10 Parte III: il computer come strumento per l interazione e la comunicazione Si è parlato di identità Parte III: il computer come strumento per l interazione
ARCHIVI E DATABASE (prof. Ivaldi Giuliano)
ARCHIVI E DATABASE (prof. Ivaldi Giuliano) Archivio: è un insieme di registrazioni (o records) ciascuna delle quali è costituita da un insieme prefissato di informazioni elementari dette attributi (o campi).
SQL Server. SQL server e un RDBMS di tipo client/server che utilizza Transact-SQL per gestire la comunicazione fra un client e SQL Server
SQL Server 7.0 1 SQL Server SQL server e un RDBMS di tipo client/server che utilizza Transact-SQL per gestire la comunicazione fra un client e SQL Server 2 Strumenti per la gestione Enterprise Manager
User Tools: DataBase Manager
Spazio di lavoro Per usare T-SQL Assistant selezionare il link Simple Query e spostare a piacere la piccola finestra dove un menu a tendina mostra i diversi comandi SQL selezionabili, il pulsante Preview
EXCEL FUNZIONI PRINCIPALI
EXCEL FUNZIONI PRINCIPALI Funzione SE() Sintassi: SE(VERIFICA, VALORE SE VERO, VALORE SE FALSO): verifica un valore e ritorna una risposta in base al risultato vero/falso Esempio: =SE(A2=15; "OK"; "NO")
Manuale d uso Software di parcellazione per commercialisti Ver. 1.0.3 [05/01/2015]
Manuale d uso Software di parcellazione per commercialisti Ver. 1.0.3 [05/01/2015] Realizzato e distribuito da LeggeraSoft Sommario Premessa... 2 Fase di Login... 2 Menù principale... 2 Anagrafica clienti...
Guida alla registrazione on-line di un DataLogger
NovaProject s.r.l. Guida alla registrazione on-line di un DataLogger Revisione 3.0 3/08/2010 Partita IVA / Codice Fiscale: 03034090542 pag. 1 di 17 Contenuti Il presente documento è una guida all accesso
PROGRAMMA GESTIONE TURNI MANUALE UTENTE. Programma Gestione Turni Manuale Utente versione 1.1
PROGRAMMA GESTIONE TURNI MANUALE UTENTE INDICE 1 PREMESSA 3 2 COMANDI COMUNI 3 3 SEDI 3 4 FESTIVITÀ 4 5 PERIODI TURNI 4 6 COD. TURNI 6 7 TURNI SPORTIVI 9 8 COD. EQUIPAGGI 9 9 DISPONIBILITÀ 10 10 INDISPONIBILITÀ
SQL prima parte D O C E N T E P R O F. A L B E R T O B E L U S S I. Anno accademico 2011/12
SQL prima parte D O C E N T E P R O F. A L B E R T O B E L U S S I Anno accademico 2011/12 DEFINIZIONE Il concetto di vista 2 È una relazione derivata. Si specifica l espressione che genera il suo contenuto.
Introduzione. Alberto Fortunato [email protected]. www.albertofortunato.com Pag. 1 di 137
Introduzione Il software Gestione magazzino è stato realizzato con l intenzione di fornire uno strumento di apprendimento per chi intendesse cominciare ad utilizzare Access 2010 applicando le tecniche
Basi di Dati Prof. L. Tanca e F. A. Schreiber APPELLO DEL 12 FEBBRAIO 2015 PARTE 1
Basi di Dati Prof. L. Tanca e F. A. Schreiber APPELLO DEL 12 FEBBRAIO 2015 PARTE 1 Si consideri il seguente schema di base di dati che vuole tenere traccia delle attività di un autofficina. MECCANICO (CodiceFiscale,
Istruzioni DML di SQL
Istruzioni DML di SQL Pag. 99 par.4 1 Sintassi: Costrutto: INSERT INTO (Inserimento di dati in tabelle) INSERT INTO [(, ,, )] VALUES (, ,
Hub-PA Versione 1.0.6 Manuale utente
Hub-PA Versione 1.0.6 Manuale utente (Giugno 2014) Hub-PA è la porta d ingresso al servizio di fatturazione elettronica verso la Pubblica Amministrazione (PA) a disposizione di ogni fornitore. Questo manuale
Il DBMS Oracle. Express Edition. Donatella Gubiani e Angelo Montanari
Gubiani & Montanari Il DBMS Oracle 1 Il DBMS Oracle Express Edition Donatella Gubiani e Angelo Montanari Il DBMS Oracle Il DBMS Oracle Oracle 10g Express Edition Il DBMS Oracle (nelle sue versioni più
Il database management system Access
Il database management system Access Corso di autoistruzione http://www.manualipc.it/manuali/ corso/manuali.php? idcap=00&idman=17&size=12&sid= INTRODUZIONE Il concetto di base di dati, database o archivio
Mon Ami 3000 Varianti articolo Gestione di varianti articoli
Prerequisiti Mon Ami 3000 Varianti articolo Gestione di varianti articoli L opzione Varianti articolo è disponibile per le versioni Azienda Light e Azienda Pro e include tre funzionalità distinte: 1. Gestione
LUdeS Informatica 2 EXCEL. Seconda parte AA 2013/2014
LUdeS Informatica 2 EXCEL Seconda parte AA 2013/2014 STAMPA Quando si esegue il comando FILE STAMPA, Excel manda alla stampante tutte le celle del foglio di lavoro corrente che hanno un contenuto. Il numero
Progetto: ARPA Fonte Dati. ARPA Fonte Dati. Regione Toscana. Manuale Amministratore
ARPA Fonte Dati Regione Toscana 1 Redatto da L. Folchi (TAI) Rivisto da Approvato da Versione 1.1 Data emissione 09/10/13 Stato FINAL 2 Versione Data Descrizione 1,0 06/08/13 Versione Iniziale 1.1 09/10/2013
SQL Sintassi Dei Comandi
SQL Sintassi Dei Comandi Di Roberto Aloi http://prof3ta.homeunix.org [email protected] Questo fascicolo è stato realizzato esclusivamente a fini divulgativi e per la libera consultazione. E' concessa la
Informatica Generale Andrea Corradini. 19 - Sistemi di Gestione delle Basi di Dati
Informatica Generale Andrea Corradini 19 - Sistemi di Gestione delle Basi di Dati Sommario Concetti base di Basi di Dati Il modello relazionale Relazioni e operazioni su relazioni Il linguaggio SQL Integrità
Laboratorio di Basi di Dati e Web
Laboratorio di Basi di Dati e Web Docente: Alberto Belussi Lezione 1 SQL Structured Query Language SQL è stato definito nel 1973 ed è oggi il linguaggio più diffuso per i DBMS relazionali Il linguaggio
Introduzione a MySQL
Introduzione a MySQL Cinzia Cappiello Alessandro Raffio Politecnico di Milano Prima di iniziare qualche dettaglio su MySQL MySQL è un sistema di gestione di basi di dati relazionali (RDBMS) composto da
Funzioni non documentate Openoffice.org. 3 Base mini-howto
Funzioni non documentate Openoffice.org. 3 Base mini-howto Augusto Scatolini ([email protected]) Ver. 1.0 gennaio 2009 Come risolvere il problema del contatore che inizia da 0 (zero) Come importare
Manuale Utente Albo Pretorio GA
Manuale Utente Albo Pretorio GA IDENTIFICATIVO DOCUMENTO MU_ALBOPRETORIO-GA_1.4 Versione 1.4 Data edizione 04.04.2013 1 TABELLA DELLE VERSIONI Versione Data Paragrafo Descrizione delle modifiche apportate
