Stored Procedure Prof. Alfredo Pulvirenti
Stored Procedure Programmi memorizzati nel DBMS che vengono eseguiti su esplicita richiesta degli utenti. PL/pgSQL di PostgreSQL PL/SQL di Oracle SQL PL di DB2 Transact-SQL di SQL Server MySql Stored Procedure di MySQL,
Stored Procedure Generalmente i DBMS che supportano le stored procedure effettuano una loro compilazione in modo da ottimizzarne le esecuzioni. Le stored procedure possono accettare parametri ma non restituiscono valori; l eventuale valore viene restituito attraverso una variabile di output passata in input per indirizzo.
Stored Procedure Possono anche essere scritte in linguaggi standard: C/C++, Java Compilate come oggetti esterni e integrati dal DBMS In alcuni casi possono eseguire azioni esterne: Cancellare un file Spedire un email
Stored Procedure Si tratta di un linguaggio procedurale che grazie ai suoi costrutti riesce a completare la natura dichiarativa di SQL: BEGIN, END, DECLARE, FOR, WHILE, LOOP, IF, etc
Modularizzazione programmi DECLARE Vantaggi delle S.P. BEGIN END;
Vantaggi delle S.P. Integrazione Applicazione Libreria condivisa DB Server
Prestazioni Elevate Vantaggi delle S.P. SQL Applicazione SQL SQL DBMS SQL Applicazione SQL IF...THEN SQL ELSE SQL END IF; SQL DBMS con S.P.
Vantaggi delle S.P. Portabilità. Elaborazioni complesse non altrimenti realizzabili usando solo query SQL. Riusabilità del codice e creazione di librerie. Accesso controllato alle tabelle (sicurezza). Consente la gestione degli errori.
Vantaggi delle S.P. La compilazione di una stored procedure avviene una volta sola, al suo inserimento. Consentono di condividere fra gli utenti delle attività comuni, in modo da centralizzare la manutenzione, la modifica etc Unificano la semantica di certe operazioni sul DB per ogni applicazione. Possono controllare in modo centralizzato certi vincoli d integrità non esprimibili nelle tabelle.
Svantaggi delle S.P. Le stored procedure aumentano il carico di lavoro per il server. A volte non si può utilizzare il linguaggio che si vorrebbe utilizzare, perché il DBMS non lo supporta. La logica di creare uno strato applicativo a livello di DB, non è compatibile con il modello logico di applicativi a tre livelli.
Tipi di sottoprogrammi Procedure Funzioni PROCEDURE name IS BEGIN --statements [EXCEPTION] FUNCTION name RETURN datatype IS BEGIN --statements RETURN value; [EXCEPTION] END; END;
Procedure in PL/SQL Una procedura e un blocco PL/SQL non anonimo che esegue delle azioni. Una procedura puo essere conservata nel database, come un qualsiasi altro oggetto del db.
CREATE [OR REPLACE] PROCEDURE nome_procedure (argomento1 [modo1] tipo_dati, argomento2 [modo2] tipo_dati,...) IS AS PL/SQL Block; Sintassi
PL/SQL di Oracle DECLARE Opzionale Variabili, cursori, eccezioni definite dall utente BEGIN Obbligatorio Comandi SQL Comandi PL/SQL EXCEPTION Opzionale Azioni da effettuare in caso di errori END; Obbligatorio DECLARE BEGIN EXCEPTION END;
PL/SQL: Struttura Blocco DECLARE v_variable VARCHAR2(5); BEGIN SELECT column_name INTO v_variable FROM table_name; EXCEPTION WHEN exception_name THEN... END; DECLARE BEGIN EXCEPTION END;
Costrutti Blocchi Anonimi DECLARE Procedure/ funzioni Memorizzate Applicazioni Trigger BEGIN EXCEPTION Applicazioni procedure/ funzioni Database trigger END; Pacchetti procedure/ funzioni
Variabili Variabili per: Immagazzinare dati temporaneamente Manipolare valori memorizzati Riutilizzo Facilita di gestione
Manipolazione variabili in PL/SQL Dichiarazione ed inizializzazione variabili nella sezione Declare Assegnamento di valori alle variabili nella sezione eseguibile. Passaggio variabili in blocchi PL/SQL attraverso parametri. Visualizzazione risultati attraverso variabili di output.
Tipi di variabili Variabili PL/SQL: Scalari Composte Referenze LOB (Large OBjects) Variabili Non-PL/SQL: Variabili ospite e Bind
Modi per i Parametri Formali IN Default Richiede che venga passato un valore. Agisce come una costante Puo essere una espressione, un letterale o una variabile OUT Da Specificare. Restituisce un valore al chiamante. Non viene inizializzato. Il parametro attuale deve essere una variabile. IN OUT Da Specificare. Passato al sottoprogramma e restituito al chiamante. Deve essere inizializzato. Il parametro attuale deve essere una variabile.
Esempio Parametri IN : 7369 v_id SQL> CREATE OR REPLACE PROCEDURE raise_salary 2 (v_id in emp.empno%type) 3 IS 4 BEGIN 5 UPDATE emp 6 SET sal = sal * 1.10 7 WHERE empno = v_id; 8 END raise_salary; 9 / Procedure created. SQL> EXECUTE raise_salary (7369) PL/SQL procedure successfully completed.
Esempio Parametri OUT: Calling environment QUERY_EMP procedure 7654 v_id MARTIN 1250 1400 v_name v_salary v_comm
Valorizzazione dei parametri OUT : SQL> CREATE OR REPLACE PROCEDURE query_emp 1 (v_id IN emp.empno%type, 2 v_name OUT emp.ename%type, 3 v_salary OUT emp.sal%type, 4 v_comm OUT emp.comm%type) 5 IS 6 BEGIN 7 SELECT ename, sal, comm 8 INTO v_name, v_salary, v_comm 9 FROM emp 10 WHERE empno = v_id; 11 END query_emp; 12 /
Uso dei Parametri IN OUT: Calling environment FORMAT_PHONE procedure '8006330575' '(800)633-0575' v_phone_no SQL> CREATE OR REPLACE PROCEDURE format_phone 2 (v_phone_no IN OUT VARCHAR2) 3 IS 4 BEGIN 5 v_phone_no := '(' SUBSTR(v_phone_no,1,3) 6 ')' SUBSTR(v_phone_no,4,3) 7 '-' SUBSTR(v_phone_no,7); 8 END format_phone; 9 /
Posizionale Metodi di associazione dei Parametri nell invocazione Per associazione col nome del parametro
Esempio SQL> CREATE OR REPLACE PROCEDURE add_dept 1 (v_name IN dept.dname%type DEFAULT 'unknown', 2 v_loc IN dept.loc%type DEFAULT 'unknown') 3 IS 4 BEGIN 5 INSERT INTO dept 6 VALUES (dept_deptno.nextval, v_name, v_loc); 7 END add_dept; 8 /
Esempi di passaggio di parametri a add_dept() SQL> BEGIN 2 add_dept; 3 add_dept ( 'TRAINING', 'NEW YORK'); 4 add_dept ( v_loc => 'DALLAS', v_name =>'EDUCATION'); 5 add_dept ( v_loc => 'BOSTON') ; 6 END; 7 / PL/SQL procedure successfully completed. SQL> SELECT * FROM dept; DEPTNO DNAME LOC ------ -------------- -------------......... 41 unknown unknown 42 TRAINING NEW YORK 43 EDUCATION DALLAS 44 unknown BOSTON
Invocazione di procedure da blocchi anonimi PL/SQL DECLARE v_id NUMBER := 7900; BEGIN raise_salary(v_id); COMMIT;... --invoke procedure END;
Invocazione di procedure da Stored Procedure SQL> CREATE OR REPLACE PROCEDURE process_emps 2 IS 3 CURSOR emp_cursor IS 4 SELECT empno 5 FROM emp; 6 BEGIN 7 FOR emp_rec IN emp_cursor 8 LOOP 9 raise_salary(emp_rec.empno); --invoke procedure 10 END LOOP; 11 COMMIT; 12 END process_emps; 13 /
Cancellare una procedura Sintassi: DROP PROCEDURE procedure_name Esempio: SQL> DROP PROCEDURE raise_salary; Procedure dropped.
Introduzione alle Stored Functions Una funzione e un blocco PL/SQL non anonimo che restituisce un valore. Le funzioni possono essere immagazzinate nel DB come le procedure. Una funzione puo essere invocata all interno di espressioni.
Sintassi CREATE [OR REPLACE] FUNCTION nome_funzione (argomento1 [modo1] tipo_dati, argomento2 [modo2] tipo_dati,...) RETURN tipo_dati IS AS PL/SQL Block; Il blocco PL/SQL deve restituire un valore il cui tipo e specificato nella clausola RETURN.
Esempio di Stored Function SQL> CREATE OR REPLACE FUNCTION get_sal 2 (v_id IN emp.empno%type) 3 RETURN NUMBER 4 IS 5 v_salary emp.sal%type :=0; 6 BEGIN 7 SELECT sal 8 INTO v_salary 9 FROM emp 10 WHERE empno = v_id; 11 RETURN (v_salary); 12 END get_sal; 13 /
Eseguire le Funzioni Invocare una funzione in una espressione PL/SQL. Eseguire le funzioni in SQL*PLUS usando variabili di appoggio.
Esempio con SQL*Plus: Calling environment 7934 GET_SAL function v_id SQL> START get_salary.sql Function created. SQL> VARIABLE g_salary number SQL> EXECUTE :g_salary := get_sal(7934) PL/SQL procedure successfully completed. SQL> PRINT g_salary G_SALARY ------------------ 1300 RETURN v_salary
Dove Invocare Funzioni User- Nella target list della SELECT Defined Nelle clausole WHERE ed HAVING CONNECT BY, START WITH, ORDER BY, e GROUP BY. Nella clausola VALUES del comando INSERT. Nella clausola SET del comando UPDATE.
Restrizioni nell uso di funzioni in SQL I soli parametri consentiti in una funzione user-defined sono di tipo IN. Non si possono utilizzare tipi PL/SQL ma solo tipi consentiti in SQL. Il passaggio di parametri puo avvenire soltanto con la notazione posizionale. Per eseguire un stored function bisogna esserne il proprietario od avere il grant di EXECUTE.
Restrizioni nell uso di SQL nelle Funzioni Le seguenti Restrizioni sono applicate alle stored function eseguite in comandi SQL: I comandi INSERT, UPDATE o DELETE ed i rimanenti comandi che modifcano il DB non sono consentiti. Non sono consentite nelle funzioni chiamate a procedure che eseguono le suddette operazioni.
Funzioni Sintassi completa [CREATE [OR REPLACE]] FUNCTION function_name[(parameter[, parameter]...)] RETURN datatype} [AUTHID {DEFINER CURRENT_USER}] [PARALLEL_ENABLE] [DETERMINISTIC] {IS AS} [PRAGMA AUTONOMOUS_TRANSACTION;] [local declarations] BEGIN executable statements [EXCEPTION exception handlers] END [name];
Procedure o Funzioni? Procedure Eseguono statement PL/SQL Non hanno la clausola RETURN Possono restituire 0 o piu valori Funzioni Sono invocate all interno di espressioni Devono contenere la clausola RETURN Devono restituire un solo valore.
Overview sui Package Raggruppano oggetti PL/SQL correlati: tipi, cursori, variabili, funzioni e procedure. Un package e formato da due parti: La Specifica Il Corpo (detto Body) Puo essere condiviso da molte applicazioni. Quando viene invocato un elemento del package l intero package e caricato in memoria.
Vantaggi dei Package Modularita, rendono piu facile costruire complesse applicazioni. Information hiding: consentono di sfruttare tecniche di incapsulamento ed overloading tipiche della programmazione OOP, fornendo cosi interfacce semplici verso l utente.
Specifica del Package Sintassi CREATE [OR REPLACE] PACKAGE nome_package IS AS dichiarazione dei tipi publici specifiche dei metodi END nome_package;
Esempio di specifica SQL>CREATE OR REPLACE PACKAGE comm_package IS 2 g_comm NUMBER := 10; --initialized to 10 3 PROCEDURE reset_comm 4 (v_comm IN NUMBER); 5 END comm_package; 6 /
Package Body Sintassi CREATE [OR REPLACE] PACKAGE BODY nome_package IS AS dichiarazione tipi privati body del sottoprogramma END nome_package;
Esempio di Package SQL> CREATE OR REPLACE PACKAGE BODY comm_package 2 IS 3 FUNCTION validate_comm 4 (v_comm IN NUMBER) 5 RETURN BOOLEAN 6 IS 7 v_max_comm NUMBER; 8 BEGIN 9 SELECT max(comm) 10 INTO v_max_comm 11 FROM emp; 12 IF v_comm > v_max_comm 13 THEN RETURN(FALSE); 14 ELSE RETURN(TRUE); 15 END IF; 16 END validate_comm;
Invocare Elementi del Package SQL> EXECUTE comm_package.reset_comm(1500) SQL> EXECUTE scott.comm_package.reset_comm(1500)
Rimozione di Packages Per rimuovere l intero package: DROP PACKAGE package_name Per rimuovere solo il corpo del package: DROP PACKAGE BODY package_name
Cursori SQL Un cursore e una area di lavoro SQL privata. Due tipi di cursori: Impliciti Espliciti Oracle usa cursori impliciti per fare il parsing ed eseguire comandi SQL. I cursori espliciti sono dichiarati dagli sviluppatori.
Cursori SQL: Attributi Usare gli attributi dei cursori, per controllare l output dei comandi SQL. SQL%ROWCOUNT Numero di righe restituite dal comando piu recente (valore intero) SQL%FOUND Attributo Booleano che restituisce TRUE se il piu recente comando SQL ha restituito una o piu righe SQL%NOTFOUND Attributo Booleano che restituisce TRUE se il piu recente comando SQL non ha ha restituito righe SQL%ISOPEN Restituisce sempre FALSE perche PL/SQL chiude i cursori impliciti subito dopo la fine dell esecuzione
Cursori SQL: Attributi Cancellare una riga che ha un numero particolare di ordine nella tabella ITEM. Visualizzare il numero della riga cancellata. Esempio VARIABLE rows_deleted VARCHAR2(30) DECLARE v_ordid NUMBER := 605; BEGIN DELETE FROM item WHERE ordid = v_ordid; :rows_deleted := (SQL%ROWCOUNT ' rows deleted.'); END; / PRINT rows_deleted
Cursori Ogni comando SQL eseguito da Oracle ha un cursore individuale associato ad esso: Cursori impliciti: Dichiarati per comandi DML e PL/SQL SELECT Cursori espliciti: Dichiarati ed usati dal programmatore
Funzioni sui cursori espliciti Insieme attivo Cursor 7369 SMITH CLERK 7566 JONES MANAGER 7788 SCOTT ANALYST 7876 ADAMS CLERK 7902 FORD ANALYST Riga corrente
Controllare cursori Espliciti No DECLARE OPEN FETCH EMPTY? Yes CLOSE Creare un area SQL con nome Identificare l insieme attivo Inserire la riga corrente dentro una variabile Controllare se esistono righe Ritornare a FETCH se viene trovata una riga Rilasciare l insieme attivo
Controllo dei cursori espliciti Aprire il cursore Pointer Cursor Fetch di una riga dal cursore. Pointer Cursor Continuare fino alla fine Pointer Cursor Chiudere il cursore.
Dichiarare un cursore Sintassi CURSOR cursor_name IS select_statement; Non includere la clausola INTO nella dichiarazione del cursore. Se e richiesto il processing di una sequenza di righe usare la clausola ORDER BY.
Dichiarare un cursore Esempio DECLARE CURSOR emp_cursor IS SELECT empno, ename FROM emp; CURSOR dept_cursor IS SELECT * FROM dept WHERE deptno = 10; BEGIN...
Aprire un cursore Sintassi OPEN cursor_name; Aprire un cursore per eseguire la query ed identificare l insieme attivo. Se la query non restituisce riga non c e eccezione. Usare gli attributi del cursore per testare l output dopo la fetch.
Sintassi Fetch dei Dati da un cursore FETCH cursor_name INTO [variable1, variable2,...] record_name]; Inserire I valori della riga corrente nelle variabili. Includere lo stesso numero di variabili. Match ogni variabile alla corrispondente posizione della colonna. Test per vedere se il cursore contiene righe.
Fetch dei dati da Cursore Esempio FETCH emp_cursor INTO v_empno, v_ename;... OPEN defined_cursor; LOOP FETCH defined_cursor INTO defined_variables EXIT WHEN...;... -- Process the retrieved data... END;
Chiudere un cursore Sintassi CLOSE cursor_name; Chiudere un cursore dopo il completamento del fetching delle righe. Riaprire un cursore se richiesto. Non aspettare dati da un cursore dopo che e stato chiuso.
Attributi dei cursori espliciti Ottenere informazioni di stato da un cursore. Attributo Tipo Descrizione %ISOPEN Booleano TRUE se il cursore e aperto %NOTFOUND Boolean TRUE se la fetch piu recente non ha restituito righe %FOUND Boolean TRUE se la piu recente fetch ha restituito dei valori complementare di %NOTFOUND %ROWCOUNT Number Valuta il numero totale di righe restitutie dalla fetch
Controllare fetch multiple Processare diverse righe da un cursore esplicito usando un loop. Fetch di una riga alla volta. Usare l attributo %NOTFOUND per testare se la fetch va a mal fine. Usare un attributo di cursore esplicito per testare il risultato di ogni fetch.
Attributo %ISOPEN Fetch di righe solo quando il cursore e aperto. Usare l attributo %ISOPEN prima di effettuare una fetch per testare se il cursore e aperto. Esempio IF NOT emp_cursor%isopen THEN OPEN emp_cursor; END IF; LOOP FETCH emp_cursor...
Uso di %NOTFOUND e %ROWCOUNT Usare l attributo %ROWCOUNT per ottenere il numero esatto di righe. Usare %NOTFOUND per determinare l uscita da un loop.
Cursori e record Processare le righe di un insieme attivo attraverso il fetching dei valori in RECORD PL/SQL. Esempio DECLARE CURSOR emp_cursor IS SELECT empno, ename FROM emp; emp_record emp_cursor%rowtype; BEGIN OPEN emp_cursor; LOOP FETCH emp_cursor INTO emp_record;...
Cursori per FOR Loop Sintassi FOR record_name IN cursor_name LOOP statement1; statement2;... END LOOP; Il cursore FOR loop e un collegamento a un cursore esplicito. Si hanno open, fetch e close implicite. Il record e dichiarato in maniera implicita.
Cursore FOR Loop Recuperare gli impiegati uno ad uno fino alla fine. Esempio DECLARE CURSOR emp_cursor IS SELECT ename, deptno FROM emp; BEGIN FOR emp_record IN emp_cursor LOOP -- implicit open and implicit fetch occur IF emp_record.deptno = 30 THEN... END LOOP; -- implicit close occurs END;
Cursori FOR Loop attraverso l uso di sottoquery Non si necessita di dichiarare cursori. Esempio BEGIN FOR emp_record IN (SELECT ename, deptno FROM emp) LOOP -- implicit open and implicit fetch occur IF emp_record.deptno = 30 THEN... END LOOP; -- implicit close occurs END;
Cursori con parametri Sintassi CURSOR cursor_name [(parameter_name datatype,...)] IS select_statement; Passare i valori dei parametri al cursore quando esso è aperto. Un cursore esplicito può essere aperto diverse volte con parametri differenti.
Cursori con parametri Passare il numero di dipartimento ed il nome dell impiegato nella clausola WHERE. Esempio DECLARE CURSOR emp_cursor (p_deptno NUMBER, p_job VARCHAR2) IS SELECT empno, ename FROM emp WHERE deptno = p_deptno AND job = p_job; BEGIN OPEN emp_cursor(10, 'CLERK');...
Clausola FOR UPDATE Sintassi SELECT... FROM... FOR UPDATE [OF column_reference][nowait]; Lock esplicito da accesso negato durante la transazione. Lock delle righe prima di UPDATE O DELETE.
Clausola FOR UPDATE Prendere gli impiegati che lavorano nel dipartimento 30. Esempio DECLARE CURSOR emp_cursor IS SELECT empno, ename, sal FROM emp WHERE deptno = 30 FOR UPDATE OF sal NOWAIT;
Clausola WHERE CURRENT OF Sintassi WHERE CURRENT OF cursor ; Usare il cursore per cancellare o aggiornare la riga corrente. Includere la clausola FOR UPDATE nella query cursore per guardare prima le righe. Usare la clausola WHERE CURRENT OF per riferirsi alla riga corrente di un cursore esplicito.
Esempio Clausola WHERE CURRENT OF DECLARE CURSOR sal_cursor IS SELECT sal FROM emp WHERE deptno = 30 FOR UPDATE OF sal NOWAIT; BEGIN FOR emp_record IN sal_cursor LOOP UPDATE emp SET sal = emp_record.sal * 1.10 WHERE CURRENT OF sal_cursor; END LOOP; COMMIT; END;
Cursori con sottoquery Esempio DECLARE CURSOR my_cursor IS SELECT t1.deptno, t1.dname, t2.staff FROM dept t1, (SELECT deptno, count(*) STAFF FROM emp GROUP BY deptno) t2 WHERE t1.deptno = t2.deptno AND t2.staff >= 5;