M1 Informatique – Bases de données avancées – TD 5 1/2 M1 Informatique – Année 2017-2018
Bases de données avancées TD n° 5 (PL/SQL) : SQL dynamique
J. Darmont (http://eric.univ-lyon2.fr/~jdarmont/), 28/11/17
Exercice 1 : Requête dynamique imbriquée dans un curseur statique
1. Écrire une procédure stockée permettant de compter le nombre de n-uplets dans toutes les tables de votre catalogue système (vue système TAB (TNAME, TABTYPE…)). Exclure les vues (type VIEW) de ce calcul. Afficher le résultat trié par ordre alphabétique sous la forme NOM_TABLE : NB_NUPLETS n-uplet(s).
Tester.
2. Gérer le pluriel du mot « n-uplet », qui prend un « s » uniquement quand la taille de la table est strictement supérieure à 1 n-uplet. Tester.
Exercice 2 : Curseur paramétré
1. Dans un bloc PL/SQL anonyme, définir une variable chaîne de caractères nommée « nomtable » et lui affecter le nom d’une table de votre compte. Écrire le code PL/SQL permettant d’afficher le schéma de cette table (la liste de ses attributs) au format NOM_TABLE (ATT1, ATT2…). Les attributs de vos tables sont répertoriés dans la vue système USER_TAB_COLUMNS (TABLE_NAME, COLUMN_NAME…).
2. Transformer le bloc PL/SQL anonyme en procédure stockée nommée « schema » prenant en paramètre le nom de la table dont on affiche le schéma.
Exercice 3 : Curseur dynamique
En reprenant une partie du code de la procédure stockée « schema » de l’exercice 2, créer une nouvelle procédure stockée « deuxAtt » qui affiche les valeurs des deux premiers attributs (généralement la clé primaire et un attribut que l’on espère significatif) de la table passée en paramètre.
Indications :
• Récupérer les noms des deux premiers attributs de la table à l’aide du curseur paramétré de l’exercice 2.
• Exprimer la requête qui permet de récupérer les valeurs des deux premiers attributs sous la forme d’une chaîne de caractères stockée dans une variable. Afficher la requête pour vérification.
• Utiliser un curseur dynamique pour exécuter la requête, parcourir son résultat et afficher les valeurs des deux premiers attributs.
Résultat attendu pour la table EMP : SELECT EMPNO, ENAME FROM EMP 7369, SMITH
7499, ALLEN 7521, WARD 7566, JONES 7654, MARTIN 7698, BLAKE 7782, CLARK 7839, KING 7844, TURNER 7900, JAMES 7902, FORD 7934, MILLER
M1 Informatique – Bases de données avancées – TD 5 2/2 Exercice 4 : Altération de schéma (fausse requête dynamique)
Écrire une procédure stockée prenant en paramètre le nom d’une table et permettant de créer une vue contenant les noms de tous les attributs de cette table, ainsi que leur type. Le nom de la vue devra être de la forme ATT_nom_de_la_table. Utiliser la vue système USER_TAB_COLUMNS (TABLE_NAME, COLUMN_NAME, DATA_TYPE…) pour accéder au nom et au type des attributs. Vérifier le résultat.
Indications :
• Dans les vues systèmes, toutes les chaînes de caractères (comme les noms de tables ou d’attributs) sont stockées en majuscules.
• Dans la définition de la procédure stockée, avant le mot clé IS, ajouter la clause AUTHID CURRENT_USER afin d’autoriser l’altération de schéma sur votre compte.
M1 Informatique – Bases de données avancées – TD 5 3/2 Correction
-- Exercice 1
CREATE OR REPLACE PROCEDURE compte IS
CURSOR tables IS SELECT tname FROM tab WHERE tabtype <> 'VIEW' ORDER BY tname;
t tables%ROWTYPE;
c INTEGER;
BEGIN
FOR t IN tables LOOP
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' || t.tname INTO c;
DBMS_OUTPUT.PUT(t.tname || ' : ' || c || ' n-uplet');
IF c > 1 THEN
DBMS_OUTPUT.PUT('s');
END IF;
DBMS_OUTPUT.PUT_LINE('');
END LOOP;
END;
-- Exercice 2
CREATE OR REPLACE PROCEDURE schema(nomtable VARCHAR) IS
CURSOR cparam(nomt VARCHAR) IS SELECT column_name FROM user_tab_columns WHERE table_name = nomt;
attribut user_tab_columns.column_name%TYPE;
BEGIN
DBMS_OUTPUT.PUT(nomtable || ' (');
OPEN cparam(nomtable);
FETCH cparam INTO attribut;
WHILE cparam%FOUND LOOP
IF cparam%ROWCOUNT > 1 THEN DBMS_OUTPUT.PUT(', ');
END IF;
DBMS_OUTPUT.PUT(attribut);
FETCH cparam INTO attribut;
END LOOP;
CLOSE cparam;
DBMS_OUTPUT.PUT_LINE(')');
END;
M1 Informatique – Bases de données avancées – TD 5 4/2 -- Exercice 3
CREATE OR REPLACE PROCEDURE deuxAtt(nomtable VARCHAR) IS
CURSOR cparam(nomt VARCHAR) IS SELECT column_name FROM user_tab_columns WHERE table_name = nomt;
TYPE CursDyn IS REF CURSOR;
cdyn CursDyn;
att1 user_tab_columns.column_name%TYPE;
att2 user_tab_columns.column_name%TYPE;
rq VARCHAR(255);
val1 VARCHAR(255);
val2 VARCHAR(255);
BEGIN
-- Récupération des attributs via le curseur paramétré OPEN cparam(nomtable);
FETCH cparam INTO att1;
FETCH cparam INTO att2;
CLOSE cparam;
-- Construction de la requête
rq := 'SELECT ' || att1 || ', ' || att2 || ' FROM ' || nomtable;
DBMS_OUTPUT.PUT_LINE(rq);
-- Parcours du curseur dynamique OPEN cdyn FOR rq;
FETCH cdyn into val1, val2;
WHILE cdyn%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(val1 || ', ' || val2);
FETCH cdyn into val1, val2;
END LOOP;
CLOSE cdyn;
END;
-- Exercice 4
CREATE OR REPLACE PROCEDURE vue_att(nomtable VARCHAR) AUTHID CURRENT_USER IS rq VARCHAR(255);
BEGIN
rq := 'CREATE VIEW ATT_' || nomtable || ' AS SELECT COLUMN_NAME, DATA_TYPE FROM USER_TAB_COLUMNS WHERE TABLE_NAME=''' || UPPER(nomtable) || '''';
EXECUTE IMMEDIATE rq;
END;