Está en la página 1de 8

INSIA SIGL 2 Bases de donnes PL-SQL ORACLE TP 1

Bertrand LIAUDET

Exercice 1 : prise en main du PL-SQL RENDU Chaque exercice impose un rendu. Tous les rendus sont mis dans un fichier texte unique. Ce fichier sappellera obligatoirement : Nom du fichier : NOM-Prenom-PLSQL-01.txt Ce fichier est envoy par mail. Lobjet du mail est obligatoirement : Objet du mail : NOM-Prenom-PLSQL-01.txt 00-Installation de lenvironnement Dans lenvironnement dj cr, ouvrez une session SQL-PLUS en tant que TPSELECT. Vous pouvez utiliser le dossier fournit avec le tlchargement. Rappel : pour crer lutilisateur TPSELECT : CREATE USER tpselect IDENTIFIED BY "tpselect"; GRANT CONNECT, RESOURCE TO tpselect; 1. Afficher le nom de lutilisateur est connect.
Show user

2. Afficher les droits de lutilisateur connect.


select * from user_role_privs;

3. Afficher le catalogue de lutilisateur connect.


select * from cat;

RENDU : le code de rponse aux trois questions. 01-bonjour.sql - Affichage 1. Excuter le script 01-bonjour.sql dans la calculette slq_plus. Corriger les erreurs. 2. Modifier le script pour que laffichage se fasse (serveroutput) 3. Modifier le script pour que le temps dexcution saffiche (timing)

INSIA - BASES DE DONNES SIGL 2 PL-SQL-ORACLE-TP 1 - page 1/8 - Bertrand LIAUDET

4. Mettez jour le fichier login.sql pour que laffichage se fasse chaque fois que vous vous connecterez. RENDU : le fichier login.sql. Explication de la correction apporte.
Fichier login.sql set linesize 120 set pagesize 500 set timing on set serveroutput on Fichier corrig begin dbms_output.put_line ('Bonjour '|| user || '. Nous sommes le ' || to_char(sysdate, 'dd month yyyy') || '. Vous tes bien l''INSIA !'); end; / il y avait deux problmes dapostrophe

02-variable.sql empdept.sql - & 1. 2. 3. 4. 5. Excutez le script empdept.sql dans la calculette slq_plus. Listez les tables de votre catalogue. Excutez le script 02-variable.sql Excutez une deuxime fois le script 02-variable.sql. Que constatez-vous ? Regardez le code et explicitez toute la syntaxe.

RENDU : expliquez la diffrence entre & et &&


Le & dclare une variable locale au select Le && dclare une variable globale la session. Cest lquivalent dun DEF. Pour voir la valeur de la variable : DEF maVar. Pour annuler la valeur de la variable : UNDEF maVar.

03- moySalDept.sql (empdept) - Fonction 1. Excutez le script 04-moySalDept.sql dans la calculette slq_plus. 2. affichez le code pris en compte : Col text format A80 Select line, text From user_source where name = MOYSALDEPT; 3. Explicitez toute la syntaxe. 4. Testez la fonction en utilisant la pseudo-table DUAL 5. Ecrire une requte avec une variable de substitution qui permette dafficher, pour un dpartement dont on saisira la valeur lexcution de la requte, tous les employs qui gagnent plus que la moyenne des salaires du dpartement. RENDU : les questions 4 et 5

INSIA - BASES DE DONNES SIGL 2 PL-SQL-ORACLE-TP 1 - page 2/8 - Bertrand LIAUDET

4 : select moySalDept(10) from dual; 5 : select * from emp where deptno=&v_deptno and sal > moySalDept(deptno);

04- AffEmpDept.sql (empdept) - Procdure 1. Excutez le script 03-AffEmpDept.sql dans la calculette slq_plus. 2. Affichez les erreurs repres par le systme Show errors; 3. affichez le code pris en compte. Col text format A80 Select line, text From user_source where name = AFFEMPDEPT; 4. Corrigez la ou les erreurs. Explicitez toute la syntaxe. 5. Appelez la procdures pour toutes les valeurs de dpartement. 6. Mettez jour la procdure pour quelle prenne correctement en compte le cas o le numro de dpartement nexiste pas. RENDU : le code de la procdure corrige avec un appel de cette procdure
create or replace procedure affEmpDept(v_deptno EMP.DEPTNO%TYPE) is v_nbemp number; vide number; Begin select count(*) into vide from dept where deptno=v_deptno; if vide=0 then dbms_output.put_line('Le dept '|| v_deptno || ' n''existe pas'); return; end if; select count(*) into v_nbemp from emp where deptno=v_deptno; dbms_output.put_line('Le dpartement '||v_deptno|| ' contient '||v_nbemp||' employe(s) : ') ; dbms_output.put_line('.'); for i_emp in ( select empno, ename, sal, deptno from emp where deptno = v_deptno ) loop dbms_output.put_line('. Employ n'|| i_emp.EMPNO||' : '||i_emp.ENAME||
INSIA - BASES DE DONNES SIGL 2 PL-SQL-ORACLE-TP 1 - page 3/8 - Bertrand LIAUDET

', salaire = '||i_emp.SAL); -- il manquait une ' avant ||i_emp.ENAME|| end loop; dbms_output.put_line('.'); end; / call affEmpDept(10); call affEmpDept(1); REMARQUE : pour le 5 Soit on fait call affEmpDept(10); call affEmpDept(20); call affEmpDept(30); call affEmpDept(40); soit on fait : create or replace procedure tousLesAffEmpDept is Begin for i_dept in ( select deptno from dept ) loop -- dbms_output.put_line('. affEmpDept(i_dept.DEPTNO) ; end loop; end; / call tousLesAffEmpDept() ; A noter que les appels de procdure dans la procdure se font sans call

DEPT n '|| i_dept.DEPTNO);

05- Curseurs 1. Excutez les scripts 05-lesEmployes_01.sql et 05-lesEmployes_02.sql dans la calculette slq_plus. 2. Comparez les rsultats. 3. Comparez les codes des deux scripts. 4. Transformer les deux scripts en procdure, la procdure prenant le numro du dpartement en paramtre et laffichage se limitant aux employs du dpartement trait. Affichez un message spcial si le dpartement est vide. RENDU : Explication de la diffrence entre les deux scripts. Code de la procdure de lexo 4.
Le premier code utilise un curseur explicite : cursor ... is select Le deuxime code utilise un curseur implicite : for .. in

INSIA - BASES DE DONNES SIGL 2 PL-SQL-ORACLE-TP 1 - page 4/8 - Bertrand LIAUDET

create or replace procedure affEmpDept(v_deptno EMP.DEPTNO%TYPE) is v_nbemp number; i number; BEGIN i:=0; for v_emp in ( select empno, ename, job, sal+nvl(comm, 0) as saltot from emp where deptno=v_deptno order by saltot desc ) loop dbms_output.put_line(v_emp.empno||'-'||v_emp.ename ||'-'||v_emp.job||'-'||v_emp.saltot); i:=i+1; end loop; if i=0 then dbms_output.put_line('le dpartement est vide'); end if; dbms_output.put_line('Nb lignes traites : '|| i); END; / call affEmpDept(10); call affEmpDept(1);

06- SQL dynamique - exercice 1. Ecrire une procdure (ou un bloc) qui permet dafficher, pour chaque table de la BD, le nom de la table, le nombre de tuples, et les 5 premiers tuples de chaque table. RENDU : Code de la procdure.
create or replace procedure consulteTable is TYPE NameList IS TABLE OF user_tab_columns.COLUMN_NAME%TYPE; i number; nbColonnes number; nbTuples number; v_columname NameList; v_sqlDynamique varchar2(200); v_sqlDynamique2 varchar2(1000); v_sqlDynamique3 varchar2(1000); v_attribut varchar2(30); v_valeur varchar2(200); Begin i:=0;

INSIA - BASES DE DONNES SIGL 2 PL-SQL-ORACLE-TP 1 - page 5/8 - Bertrand LIAUDET

-- on boucle sur toutes les tables for v_table in (select table_name FROM user_tables) loop dbms_output.put_line('----------------------------------------------------------------------'); -- dbms_output.put_line('Table '||v_table.table_name); -- rcupration du nombre de tuples de la table v_sqlDynamique3:='select count(*) from '|| v_table.table_name; -- dbms_output.put_line(v_sqlDynamique3); EXECUTE IMMEDIATE v_sqlDynamique3 into nbTuples; -- rcupration des attributs de la table v_sqlDynamique:='SELECT COLUMN_NAME FROM user_tab_columns table_name='''|| v_table.table_name||''''; -- dbms_output.put_line(v_sqlDynamique); EXECUTE IMMEDIATE v_sqlDynamique BULK COLLECT INTO v_columname;

WHERE

-- on peut aussi crire : notez le 1 et le USING -- v_sqlDynamique:='SELECT COLUMN_NAME FROM user_tab_columns WHERE table_name=:1'; -- EXECUTE IMMEDIATE v_sqlDynamique BULK COLLECT INTO v_columname USING v_table.table_name; -- Cration de la requte dans v_sqlDynamique2 v_sqlDynamique2:='BEGIN for v_attributs in (select '; nbColonnes:=0; FOR j IN 1..v_columname.count LOOP -- dbms_output.put_line('Attribut : '||v_columname(j)); v_attribut:=v_columname(j); v_sqlDynamique2:=v_sqlDynamique2||v_attribut||','; nbColonnes:=nbColonnes+1; END LOOP; v_sqlDynamique2:=v_sqlDynamique2||' '''' as nb FROM '||v_table.table_name||' WHERE rownum<6) LOOP dbms_output.put_line('; FOR j IN 1..v_columname.count LOOP v_attribut:=v_columname(j); v_sqlDynamique2:=v_sqlDynamique2||'v_attributs.'||v_attribut||'||'' ''|| '; END LOOP; v_sqlDynamique2:=v_sqlDynamique2||'v_attributs.nb); END loop; END;'; -- fin de la cration de la requte dans v_sqlDynamique2 dbms_output.put_line('La Table '||v_table.table_name||' nbColonnes ||' colonnes et '|| nbTuples ||' tuples : '); dbms_output.put_line('-'); EXECUTE IMMEDIATE v_sqlDynamique2; possde '||

INSIA - BASES DE DONNES SIGL 2 PL-SQL-ORACLE-TP 1 - page 6/8 - Bertrand LIAUDET

i:=i+1; dbms_output.put_line('-'); end loop; -- dbms_output.put_line('Nb lignes traites : '|| i); end; /

call consulteTable();

07- Trigger 1. Excutez le script 07-trigBefore.txt dans la calculette slq_plus. 2. Affichez le code pris en compte (mme principe que pour les procdures et les fonctions)
Col text format A80 Select line, text From user_source where name = TBU_SAL_EMP;

3. Affichez les erreurs : trouvez dans les vues publiques la table correspondante et listez son contenu. On pourra se contenter des attributs : name, line, position, text. On fera en sorte que laffichage soit lisible.
Col text format A80 col name format a15 Select name, line, position, text from user_errors;

4. Corrigez les erreurs.


CREATE OR REPLACE TRIGGER TBU_SAL_EMP BEFORE UPDATE OF SAL ON EMP FOR EACH ROW BEGIN if (:new.sal <= :old.sal ) then RAISE_APPLICATION_ERROR ( -20000, 'Le nouveau salaire : '|| :new.sal || 'est infrieur ou gale l''ancien : ' || :old.sal); end if; END; / // il y a des problmes de quotes

INSIA - BASES DE DONNES SIGL 2 PL-SQL-ORACLE-TP 1 - page 7/8 - Bertrand LIAUDET

5. Vrifiez que le trigger fonctionne correctement : augmenter un salaire de 10%. Affichez les salaires.
update emp set sal = 5500 where empno = 7839;

6. Ouvrez une deuxime session SQL-PLUS pour lutilisateur TPSELECT. Regardez ltat des salaires. Que constatez-vous ? Regardez ltat des variables denvironnement (SHOW ALL). Comment expliquez-vous la situation ? Dans la premire session : validez la transaction. Vrifiez sa prise en compte dans la deuxime session.
Dans la deuxime session, on constate que la modification napparat pas : Select * from emp where where empno = 7839; Le SHOW ALL montre le AUTOCOMMIT OFF Pour valider la transaction dans la premire session : Commit ; Dans la 2me session : on constate que la modification a t prise en compte : Select * from emp where where empno = 7839;

7. Vrifiez que le trigger fonctionne correctement : essayez de baisser un salaire.


update emp set sal = 4000 where empno = 7839; update emp * ERREUR la ligne 1 : ORA-20000: Le nouveau salaire : 4000est infrieur ou gale l'ancien : 5500 ORA-06512: "TPSELECT.TBU_SAL_EMP", ligne 3 ORA-04088: erreur lors d'excution du dclencheur 'TPSELECT.TBU_SAL_EMP'

RENDU : requte du 2, 3. code corrig du trigger. Solution du 6.

INSIA - BASES DE DONNES SIGL 2 PL-SQL-ORACLE-TP 1 - page 8/8 - Bertrand LIAUDET

También podría gustarte