5AE7BD0Bd01
-
Upload
hamza-sellami -
Category
Documents
-
view
8 -
download
1
Transcript of 5AE7BD0Bd01
INSIA - BASES DE DONNÉES – SIGL 2 – PL-SQL-ORACLE-TP 1 - page 1/8 - Bertrand LIAUDET
INSIA – SIGL 2 Bases de données
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 s’appellera obligatoirement :
Nom du fichier : NOM-Prenom-PLSQL-01.txt
Ce fichier est envoyé par mail.
L’objet du mail est obligatoirement :
Objet du mail : NOM-Prenom-PLSQL-01.txt
00-Installation de l’environnement
Dans l’environnement déjà créé, ouvrez une session SQL-PLUS en tant que TPSELECT.
Vous pouvez utiliser le dossier fournit avec le téléchargement.
Rappel : pour créer l’utilisateur TPSELECT : CREATE USER tpselect IDENTIFIED BY "tpselect"; GRANT CONNECT, RESOURCE TO tpselect;
1. Afficher le nom de l’utilisateur est connecté. Show user
2. Afficher les droits de l’utilisateur connecté. select * from user_role_privs;
3. Afficher le catalogue de l’utilisateur connecté. select * from cat;
RENDU : le code de réponse aux trois questions.
01-bonjour.sql - Affichage
1. Exécuter le script 01-bonjour.sql dans la calculette slq_plus. Corriger les erreurs.
2. Modifier le script pour que l’affichage se fasse (serveroutput)
3. Modifier le script pour que le temps d’exécution s’affiche (timing)
INSIA - BASES DE DONNÉES – SIGL 2 – PL-SQL-ORACLE-TP 1 - page 2/8 - Bertrand LIAUDET
4. Mettez à jour le fichier login.sql pour que l’affichage se fasse à chaque fois que vous vous connecterez.
RENDU : le fichier login.sql. Explication de la correction apportée. 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 problèmes d’apostrophe
02-variable.sql – empdept.sql - &
1. Exécutez le script empdept.sql dans la calculette slq_plus.
2. Listez les tables de votre catalogue.
3. Exécutez le script 02-variable.sql
4. Exécutez une deuxième fois le script 02-variable.sql. Que constatez-vous ?
5. Regardez le code et explicitez toute la syntaxe.
RENDU : expliquez la différence entre & et && Le & déclare une variable locale au select
Le && déclare une variable globale à la session. C’ est l’équivalent d’un 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. Exécutez 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 requête avec une variable de substitution qui permette d’afficher, pour un département dont on saisira la valeur à l’exécution de la requête, tous les employés qui gagnent plus que la moyenne des salaires du département.
RENDU : les questions 4 et 5
INSIA - BASES DE DONNÉES – SIGL 2 – PL-SQL-ORACLE-TP 1 - page 3/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) - Procédure
1. Exécutez le script 03-AffEmpDept.sql dans la calculette slq_plus.
2. Affichez les erreurs repérées par le système 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 procédures pour toutes les valeurs de département.
6. Mettez à jour la procédure pour qu’elle prenne correctement en compte le cas où le numéro de département n’existe pas.
RENDU : le code de la procédure corrigée avec un appel de cette procédure 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 département '||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 DONNÉES – SIGL 2 – PL-SQL-ORACLE-TP 1 - page 4/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('. DEPT n° '|| i_dept .DEPTNO);
affEmpDept(i_dept.DEPTNO) ;
end loop;
end;
/
call tousLesAffEmpDept() ;
A noter que les appels de procédure dans la procédu re se font sans call
05- Curseurs
1. Exécutez les scripts 05-lesEmployes_01.sql et 05-lesEmployes_02.sql dans la calculette slq_plus.
2. Comparez les résultats.
3. Comparez les codes des deux scripts.
4. Transformer les deux scripts en procédure, la procédure prenant le numéro du département en paramètre et l’affichage se limitant aux employés du département traité. Affichez un message spécial si le département est vide.
RENDU : Explication de la différence entre les deux scripts. Code de la procédure de l’exo 4. Le premier code utilise un curseur explicite : curs or ... is select
Le deuxième code utilise un curseur implicite : for .. in
INSIA - BASES DE DONNÉES – SIGL 2 – PL-SQL-ORACLE-TP 1 - page 5/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 sal tot
from emp
where deptno=v_deptno
order by saltot desc
)
loop
dbms_output.put_line(v_emp.empno||'-'||v_emp.enam e
||'-'||v_emp.job||'-'||v_emp.saltot);
i:=i+1;
end loop;
if i=0 then
dbms_output.put_line('le département est vide');
end if;
dbms_output.put_line('Nb lignes traitées : '|| i);
END;
/
call affEmpDept(10);
call affEmpDept(1);
06- SQL dynamique - exercice
1. Ecrire une procédure (ou un bloc) qui permet d’afficher, 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 procédure. 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 DONNÉES – SIGL 2 – PL-SQL-ORACLE-TP 1 - page 6/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_n ame);
-- récupération du nombre de tuples de la table
v_sqlDynamique3:='select count(*) from '|| v_tabl e.table_name;
-- dbms_output.put_line(v_sqlDynamique3);
EXECUTE IMMEDIATE v_sqlDynamique3 into nbTuples;
-- récupération des attributs de la table
v_sqlDynamique:='SELECT COLUMN_NAME FROM user_tab _columns WHERE table_name='''|| v_table.table_name||'''';
-- dbms_output.put_line(v_sqlDynamique);
EXECUTE IMMEDIATE v_sqlDynamique BULK COLLECT INT O v_columname;
-- 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;
-- Création de la requête dans v_sqlDynamique2
v_sqlDynamique2:='BEGIN for v_attributs in (selec t ';
nbColonnes:=0;
FOR j IN 1..v_columname.count LOOP
-- dbms_output.put_line('Attribut : '||v_columna me(j));
v_attribut:=v_columname(j);
v_sqlDynamique2:=v_sqlDynamique2||v_attribut||', ';
nbColonnes:=nbColonnes+1;
END LOOP;
v_sqlDynamique2:=v_sqlDynamique2||' '''' as nb FR OM '||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 création de la requête dans v_sqlDyn amique2
dbms_output.put_line('La Table '||v_table.table_n ame||' possède '|| nbColonnes ||' colonnes et '|| nbTuples ||' tuples : ');
dbms_output.put_line('-');
EXECUTE IMMEDIATE v_sqlDynamique2;
INSIA - BASES DE DONNÉES – SIGL 2 – PL-SQL-ORACLE-TP 1 - page 7/8 - Bertrand LIAUDET
i:=i+1;
dbms_output.put_line('-');
end loop;
-- dbms_output.put_line('Nb lignes traitées : '|| i);
end;
/
call consulteTable();
07- Trigger
1. Exécutez le script 07-trigBefore.txt dans la calculette slq_plus.
2. Affichez le code pris en compte (même principe que pour les procédures 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 l’affichage 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 inférieur ou égale à l''ancien : ' ||
:old.sal);
end if;
END;
/
// il y a des problèmes de quotes
INSIA - BASES DE DONNÉES – SIGL 2 – PL-SQL-ORACLE-TP 1 - page 8/8 - Bertrand LIAUDET
5. Vérifiez que le trigger fonctionne correctement : augmenter un salaire de 10%. Affichez les salaires.
update emp
set sal = 5500
where empno = 7839;
6. Ouvrez une deuxième session SQL-PLUS pour l’utilisateur TPSELECT. Regardez l’état des salaires. Que constatez-vous ? Regardez l’état des variables d’environnement (SHOW ALL). Comment expliquez-vous la situation ? Dans la première session : validez la transaction. Vérifiez sa prise en compte dans la deuxième session.
Dans la deuxième session, on constate que la modifi cation n’apparaît pas :
Select * from emp where where empno = 7839;
Le SHOW ALL montre le AUTOCOMMIT à OFF
Pour valider la transaction dans la première sessio n :
Commit ;
Dans la 2 ème session : on constate que la modification a été pr ise en compte :
Select * from emp where where empno = 7839;
7. Vérifiez 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 inférieur o u égale à l'ancien : 5500
ORA-06512: à "TPSELECT.TBU_SAL_EMP", ligne 3
ORA-04088: erreur lors d'exécution du déclencheur ' TPSELECT.TBU_SAL_EMP'
RENDU : requête du 2, 3. code corrigé du trigger. Solution du 6.