\documentclass[a4paper,11pt]{article}

\usepackage[utf8x]{inputenc}
\usepackage[T1]{fontenc} 
\usepackage[french]{babel}
\usepackage[a4paper,hmargin=20mm,vmargin=30mm]{geometry}%\usepackage{fullpage}
\usepackage{url}
\usepackage{comment}
\usepackage{fancyhdr}
\usepackage{adjustbox}
\usepackage{slashbox}
%\usepackage{times}
\usepackage{amsmath}
\usepackage{amsthm}


\usepackage{tikz,pgflibraryarrows,pgffor,pgflibrarysnakes}
\usetikzlibrary{decorations.pathreplacing}

\usepackage{color, colortbl}
\definecolor{Gray}{gray}{0.9}

\usepackage{fancyvrb}

\fancypagestyle{monstyle}{
\renewcommand{\headrulewidth}{1pt}

\fancyhead[LO]{\bfseries 2019-2020 BD PLS/SQL\rightmark}   
\fancyhead[RO]{\bfseries ~\leftmark }
 \fancyfoot[CO,CE]{}
}

\theoremstyle{definition}
\newtheorem{exercice}{Exercice}

\pagestyle{monstyle}

\newcommand{\code}[1]{\texttt{#1}}
\usepackage{boxedminipage}
\usepackage{setspace}

\newsavebox\svbx
\newif\ifcache
\long\def\cache#1{\ \newline
  \setbox\svbx=\vbox{\leavevmode \newline \begin{spacing}{1}#1\end{spacing}}
 \smallskip\par\noindent
 \begin{boxedminipage}{\linewidth}
  \ifcache    
  \leavevmode\hrule height 0pt\vskip \ht\svbx\hrule height 0pt
  \else \unvbox\svbx
  \fi
 \end{boxedminipage}
 \par\smallskip}


%\cachefalse % version prof
\cachetrue % version  etudiant

\begin{document}
\begin{center}
 NOM : \hfill Partiel \hfill~\\
 PRENOM : \hfill 90 minutes, 90 points \hfill ~\\
 GROUPE : \hfill  Aucun document autoris\'e \hfill~\\
\end{center}

\begin{exercice}[Curseur (20 points)] \ \\
  \begin{enumerate}
  \item (3 points) Expliquer \`a quoi sert un curseur.
    \cache{Un curseur  permet de  r\'ecup\'erer des donn\'ees multiples.}
  \item (5 points) Donner un exemple simple de requ\^ete en
    pr\'ecisant la table utilis\'ee qui n’est pas possible de traiter
    sans un curseur, et expliquer pourquoi.  \cache{SELECT *

      from ETUDIANTS      WHERE
      
      Une requete qui
      renvoie plein de donn\'ees.}
  \item (12 points) Cr\'eer un curseur permettant de traiter l'exemple
    de la question pr\'ec\'edente.
    \newsavebox\dd
    \begin{lrbox}{\dd}
      \begin{minipage}{\textwidth}
\begin{small}
\begin{verbatim}
DROP TABLE ETUDIANT2020;
CREATE TABLE ETUDIANT2020(nom varchar2(100), age number);
INSERT INTO ETUDIANT2020 VALUES('Alice', 12);
INSERT INTO ETUDIANT2020 VALUES('Bob', 15);
INSERT INTO ETUDIANT2020 VALUES('Charlie', 18);
INSERT INTO ETUDIANT2020 VALUES('Dave', 21);
INSERT INTO ETUDIANT2020 VALUES('Eve', 11);
DROP TABLE tligne;
CREATE TABLE tligne(DESCRIPTION VARCHAR2(300));
SET echo off;SET verify off;SET feedback off;

DECLARE
dnom VARCHAR2(100);
CURSOR C IS SELECT nom from ETUDIANT2020 WHERE (age >= 18);

BEGIN
OPEN C;
FETCH C into dnom;
WHILE C%FOUND LOOP
 INSERT INTO tligne VALUES(dnom);
 FETCH C into dnom;
END LOOP;
CLOSE C;
END;
.
/
SET echo on;SET verify on;SET feedback on; SELECT * FROM TLIGNE;
\end{verbatim}
\end{small}
      \end{minipage}
    \end{lrbox}
     \cache{\usebox\dd}
  \end{enumerate}
\end{exercice}


\newpage

\begin{exercice}[Exception (15 points)]
  \ \\
  \begin{enumerate}
  \item (3 points) Expliquer ce qu'est une exception.
    \cache{Une exception permet de r\'ealiser un traitement

      lors qu'une erreur SQL se produit.

    ou lorsque l utilisateur le decide}
  \item (12 points) Donner un exemple de cr\'eation d'exception
    \code{MINEUR} qui est lev\'ee si la table \code{ETUDIANT (NOM
      VARCHA2(100), AGE NUMBER);} contient au moins un mineur
    (personne de moins de 18 ans) et affiche le nombre de mineurs.
    \newsavebox\avecalter
    \begin{lrbox}{\avecalter}
      \begin{minipage}{\textwidth}
\begin{verbatim}
DROP TABLE ETUDIANT2020;
CREATE TABLE ETUDIANT2020(nom varchar2(100), age number);
INSERT INTO ETUDIANT2020 VALUES('Alice', 12);
INSERT INTO ETUDIANT2020 VALUES('Bob', 15);
INSERT INTO ETUDIANT2020 VALUES('Charlie', 18);
INSERT INTO ETUDIANT2020 VALUES('Dave', 21);
INSERT INTO ETUDIANT2020 VALUES('Eve', 11);
DROP TABLE tligne;
CREATE TABLE tligne(DESCRIPTION VARCHAR2(300));

SET echo off;SET verify off; SET feedback off;

DECLARE
Dnbmineur number;
MINEUR EXCEPTION;

BEGIN
SELECT count(*) into Dnbmineur 
FROM ETUDIANT2020 
WHERE  AGE < 18;

IF (Dnbmineur > 0) THEN RAISE MINEUR;
END IF;

EXCEPTION 
WHEN MINEUR THEN
INSERT INTO tligne VALUES(Dnbmineur); 
END;
.
/

SET echo on;SET verify on; SET feedback on; SELECT * FROM TLIGNE;
\end{verbatim}
  \end{minipage}
\end{lrbox}
    \cache{\usebox\avecalter}

%%   \item (2+2+4=8 points) Donner un exemple simple qui n’est pas possible de
%%     traiter sans un curseur, expliquer pourquoi et montrer comment
%%     créer un curseur et comment l'utiliser dans ce cas là.
       
%%       \begin{SaveVerbatim}{VerbEnv}
%% Declare 
%% dnom Etudaint.nom%TYPE ;
%% Cursor r is Select nom from Etudiant FOR UPDATE;
%% BEGIN
%% OPEN r ;
%% FETCH r INTO dnom ;
%% WHILE r%FOUND
%% LOOP
%%  UPDATE Etudiant SET nom=dnom||'old' WHERE CURRENT of r ; 
%%  FETCH r INTO dnom ;
%% END LOOP ;
%% COMMIT;
%% CLOSE R ;
%% END ;
%%       \end{SaveVerbatim}
%%       \cache{\code{Select nom into dnom from Etudiant ;}

%% \BUseVerbatim{VerbEnv}
   
%% }  \end{enumerate}
  \end{enumerate}
  
  \end{exercice}

\newpage

\section*{PL/SQL : NBA Statistiques}
Ci-dessous un mod\`ele de la base de donn\'ees de statistiques de la
NBA (National Basketball Association), o\`u PG, SG, SF, PF et C sont
les diff\'erents postes occup\'es par les joueurs sur le terrain. Un
joueur ne peut pas \^etre en activit\'e dans deux \'equipes en m\^eme temps.

\begin{center}
     	   \begin{tikzpicture}[every node/.style={inner sep=0,outer sep=0}]

\node (i) at (6,0) {\begin{varwidth}{1.5in}
\begin{tabular}{|l|}
\hline
\rowcolor{Gray}APPARTIENT\\
\hline
\underline{id\_contrat}\\
\#id\_joueur\\
\#id\_equipe\\
Date\_debut\\
Date\_fin\\
Salaire\_jour\\ \hline
\end{tabular}
\end{varwidth}
};


\node (a) at (0,0) {\begin{varwidth}{2.5in}
\begin{tabular}{|l|}
\hline
\rowcolor{Gray}JOUEUR\\
\hline
\underline{id\_joueur}\\
Nom\\
Pénom\\
Date\_de\_naissance\\
Taille\\
Poste('PG','SG','SF','PF','C')\\
\hline
\end{tabular}
\end{varwidth}
};


\node (f) at (8,-5) {\begin{varwidth}{2.5in}
\begin{tabular}{|l|}
\hline
\rowcolor{Gray}Game\\
\hline
\underline{id\_game}\\
Date\_game\\
\#id\_equipe\_domicile\\
\#id\_equipe\_exterieur\\
Ville\\
Categorie(Amical,Saison,Playoff,Allstar)\\
Score\_domicile\\
Score\_exterieur\\
Prolongation\\
\hline
\end{tabular}
\end{varwidth}
};

\node[draw,rectangle] (g) at (0,-5) {\begin{varwidth}{2in}
\begin{tabular}{l}
 \rowcolor{Gray}JOUE\\
  \hline
  \underline{\#id\_joueur}\\
  \underline{\#id\_game}\\
  Points\\
  Rebonds\\
  Interceptions\\
  Contres\\
  Passes\\
  Balles\_perdues\\
  Fautes\\
\end{tabular}
\end{varwidth}};



\node[draw,rectangle] (c) at (11,0) {
\begin{tabular}{|l|}
\hline
\rowcolor{Gray}EQUIPE\\
\hline
\underline{id\_equipe}\\
Nom\\
Ville\\
Conference('Est','Ouest')\\
Date\_creation\\
\hline
\end{tabular}
};

\draw[-latex]  (i) --  (a);
\draw[-latex]  (i) -- (c);
\draw[-latex]  (10,-2.6) -- (10.65,-1.5);
\draw[latex-] (c) -- (f);
\draw[latex-] (f) -- (g);
\draw[latex-] (a) -- (g);

           \end{tikzpicture}
\end{center}



  
\begin{exercice}[NBA, PLSQL] (60 points)
Le MLD ci-dessus stocke les donn\'ees des matchs  NBA.

\begin{enumerate}

\item (20 points) Lister dans une table \code{TLIGNES} tous les
  joueurs d'un match donn\'e par l'utilisateur, afficher leur nom,
  pr\'enom, poste et le nombres de match o\`u il a fait 0, 1, 2, 3, 4
  ou 5 fautes, durant sa carri\`ere :
\begin{center}    
  \begin{small}
\begin{verbatim}
  GAME XXX
  Nom      Prenom    Poste     
  XXXXXX   XXXXXXX   XXXXXX
  Fautes   Nb Matchs
  0        YYY
  1        YYY
  2        YYY
  3        YYY
  4        YYY
  5        YYY 

  XXXXXX   XXXXXXX   XXXXXX
  Fautes   Nb Matchs
  0        YYY
  1        YYY
  2        YYY
  3        YYY
  4        YYY
  5        YYY   
\end{verbatim}
  \end{small}
\end{center}


\begin{SaveVerbatim}{eqpts}
@2020nba-setup.sql;
DROP TABLE TLIGNE;
CREATE TABLE TLIGNE(LIGNE VARCHAR2(200));

variable vidgame varchar2(10)
prompt Entrer un game
accept vidgame

DECLARE
dnom varchar2(200);
dprenom varchar2(200);
dposte char(2);
didjoueur varchar2(20);
dnbfautes number;
dfautes number;

CURSOR Cnom IS SELECT j.id_joueur, j.Nom, j.Prenom, j.Poste
FROM JOUEUR j, JOUE e
WHERE j.id_joueur = e.id_joueur AND e.id_game = '&vidgame';

CURSOR Cfaute IS SELECT FAUTES, COUNT(ID_game) FROM JOUE WHERE id_joueur = didjoueur GROUP BY FAUTES ORDER BY FAUTES;


BEGIN
INSERT INTO tligne VALUES ('Nom  Prenom Poste');

OPEN Cnom;
FETCH Cnom INTO didjoueur, dnom, dprenom, dposte;
WHILE Cnom%found LOOP
  INSERT INTO tligne VALUES (dnom||' '||dprenom||' '||dposte);
  OPEN Cfaute;
  INSERT INTO tligne VALUES ('Faute  Nb Matchs');
  FETCH Cfaute INTO dfautes, dnbfautes;
  WHILE Cfaute%found LOOP
    INSERT INTO tligne VALUES (TO_CHAR(dfautes)||' '||TO_CHAR(dnbfautes));
    FETCH Cfaute INTO  dfautes, dnbfautes;
  END LOOP;
  CLOSE Cfaute;
  FETCH Cnom INTO didjoueur, dnom, dprenom, dposte;
END LOOP;
CLOSE Cnom;
END;
.
/
SELECT * FROM tligne ;
\end{SaveVerbatim}


 \cache{\begin{footnotesize}
     \BUseVerbatim{eqpts}
   \end{footnotesize}
 }




 \newpage
 
\item (10 points) \'Ecrire un code PL/SQL qui permet de saisir un
  nouveau joueur en entrant les six champs n\'ecessaires. Lever une
  exception si la clef primaire saisie n'est pas valide.


\begin{SaveVerbatim}{saisie}
@2020nba-setup.sql;
DROP TABLE tligne ;
CREATE TABLE tligne (ligne varchar2(100));
set echo off; set verify off; set feedback off;

variable vidjoueur varchar2(10)
prompt Entrer l idjoueur
accept vidjoueur
variable vnom varchar2(300)
prompt Entrer le nom du joueur
accept vnom
variable vprenom varchar2(200)
prompt Entrer le prenom du joueur
accept vprenom
variable vdate varchar2(20)
prompt Entrer sa datee de naissance
accept vdate
variable vposte varchar2(2)
prompt Entrer le poste
accept vposte
variable vtaille NUMBER
prompt Entrer sa taille
accept vtaille

DECLARE
dnbid number;
EXISTEDEJA EXCEPTION;

BEGIN
SELECT count(*) INTO dnBid FROM JOUEUR WHERE id_joueur ='&vidjoueur';
IF dnbid > 0 THEN RAISE EXISTEDEJA;
ELSE
INSERT INTO tligne VALUES ('&vidjoueur'||'&vnom'||'&vprenom'||to_date('&vdate','DD/MM/YYYY')||'&vtaille'||'&vposte');
END IF;
EXCEPTION
WHEN EXISTEDEJA THEN
INSERT INTO tligne VALUES ('ID joueur existe');
END;
./
set echo on; set verify on; set feedback on;
SELECT * FROM TLIGNE;
\end{SaveVerbatim}


\cache{\begin{small}
     \BUseVerbatim{saisie}
  \end{small}
}


  \newpage
  
\item (15 points) \'Ecrire un code PL/SQL qui, pour un
  \code{id\_joueur} saisi par l'utilisateur, liste dans une table
  \code{TLIGNES} son maximum de points inscrits lors d'un match durant
  toute sa carri\`ere. La solution propos\'ee doit mettre en place
  {\bf deux} m\'ecanismes un {\bf avec} et un {\bf sans}
  \code{EXCEPTION} pour traiter les cas d'erreurs suivants :
  \begin{itemize}
  \item \code{'joueur inconnu'}, il n'y a pas le joueur dans la table \code{JOUEUR},
  \item \code{'joueur n a pas fait de match'}, il n'apparait pas
    dans la table \code{JOUE}. 
  \end{itemize}

\begin{SaveVerbatim}{Maxpoints}
@2020nba-setup.sql;
DROP TABLE tligne ;
CREATE TABLE tligne (ligne varchar2(300)) ;
set echo off; set verify off; set feedback off;

variable vidjoueur char(4)
prompt Entrer la reference du joueur :
accept vidjoueur

DECLARE
dmaxpoint number;
dnbjoueur number;
didjoueur char(4);

BEGIN

SELECT count(Nom) INTO dnbjoueur FROM JOUEUR
WHERE id_joueur ='&vidjoueur';

if dnbjoueur != 0 then

SELECT max(points) INTO dmaxpoint FROM JOUE
WHERE id_joueur ='&vidjoueur';

INSERT INTO tligne VALUES ('Le maximum de point du joueur '||'&vidjoueur'||' est '||to_char(dmaxpoint));
ELSE
INSERT INTO tligne VALUES('AVEC COUNT : Joueur inconnu'); 

SELECT id_joueur INTO didjoueur FROM JOUE
WHERE id_joueur ='&vidjoueur';
END if;


EXCEPTION 
when no_data_found then
INSERT INTO tligne VALUES('AVEC EXCEPTION : Joueur n a pas fait de match'); 
when too_many_rows then
INSERT INTO tligne VALUES('AVEC EXCEPTION : TOO MANY ROWS'); 
end ;
.
/
SELECT * FROM tligne ;
set verify on; set feedback on; set echo on;
\end{SaveVerbatim}

\cache{\begin{small}
     \BUseVerbatim{Maxpoints}
  \end{small}
}

\newpage
  
\item (15 points) \'Ecrire un code PL/SQL qui liste dans une table
  \code{TLIGNES} les joueurs en activit\'e (ayant une date de fin de
  contrat non nulle) du plus vieux au plus jeune.
  
\begin{center}    
\begin{verbatim}
  Nom      Prenom    Date de naissance      Nom Equipe Actuelle
  XXXXXX   XXXXXXX   XX/XX/XXXX             XXXXXXXX
  XXXXXX   XXXXXXX   XX/XX/XXXX             XXXXXXXX
  XXXXXX   XXXXXXX   XX/XX/XXXX             XXXXXXXX
  ...
\end{verbatim}
\end{center}

\begin{SaveVerbatim}{Joueur}
DROP TABLE tligne ;
CREATE TABLE tligne (ligne varchar2(100)) ;

set echo off;
set verify off;
set feedback off;

DECLARE
dnom varchar2(20);
dprenom varchar2(20);
ddate date;
dnomequipe varchar2(20);

CURSOR c IS SELECT j.Nom, j.Prenom, j.Date_de_naissance, e.Nom  FROM JOUEUR j, APPARTIENT a, EQUIPE e 
WHERE a.id_joueur = j.id_joueur and e.id_equipe =  a.id_equipe and a.Date_fin is NULL
Order by Date_de_naissance;

BEGIN
OPEN c;

INSERT INTO tligne VALUES ('Nom  Prenom Date de naissance Nom Equipe Actuelle');
FETCH c INTO dnom, dprenom, ddate, dnomequipe;

WHILE c%found
LOOP  
  INSERT INTO tligne VALUES (dnom||' '||dprenom||' '||to_char(ddate)||' '||dnomequipe); 
  FETCH c INTO dnom, dprenom, ddate, dnomequipe;
END LOOP;

CLOSE C;
END;
.
/

SELECT * FROM tligne ;
set verify on;
set feedback on;
set echo on;
\end{SaveVerbatim}

 \cache{%\begin{small}
     \BUseVerbatim{Joueur}
  %\end{small}
 }

%% \item (20 points) Lister dans une table \code{TLIGNES} tous les
%%   joueurs ayant particip\'e \`a un ALLSTAR de la conf\'erence Est et
%%   ceux de la conf\'erence Ouest avec les informations suivantes :
%% \begin{center}    
%%   \begin{small}
%% \begin{verbatim}
%%   ALLSTAR MATCH 
%%   EQUIPE de l'EST
%%   Nom      Prenom    Poste     Equipe Actuelle
%%   XXXXXX   XXXXXXX   XXXXXX    XXXXXXXX
%%   XXXXXX   XXXXXXX   XXXXXX    XXXXXXXX
%%   EQUIPE de l'EST
%%   Nom      Prenom    Poste     Equipe Actuelle
%%   XXXXXX   XXXXXXX   XXXXXX    XXXXXXXX
%%   XXXXXX   XXXXXXX   XXXXXX    XXXXXXXX
%% \end{verbatim}
%%   \end{small}
%% \end{center}


%% \begin{SaveVerbatim}{Allstar}
%% DECLARE
%% dnom varchar2(20); dprenom varchar2(20);
%% dposte char(2); dnomequipe varchar2(20);

%% CURSOR Cest IS SELECT j.Nom, j.Prenom, j.Poste, e.Nom FROM JOUEUR j,
%% APPARTIENT a, EQUIPE e WHERE a.id_joueur = j.id_joueur and e.id_equipe
%% = a.id_equipe and e.conference='Est' and j.id_joueur in (SELECT
%% id_joueur FROM JOUE je, GAME g where g.Categorie='Allstar' and
%% g.id_game=je.id_game);

%% CURSOR Couest IS SELECT j.Nom, j.Prenom, j.Poste, e.Nom FROM JOUEUR j,
%% APPARTIENT a, EQUIPE e WHERE a.id_joueur = j.id_joueur and e.id_equipe
%% = a.id_equipe and e.conference='Ouest' and j.id_joueur in (SELECT
%% id_joueur FROM JOUE je, GAME g where g.Categorie='Allstar' and
%% g.id_game=je.id_game);

%% BEGIN
%% INSERT INTO tligne VALUES ('ALLSTAR GAME);
%% INSERT INTO tligne VALUES ('Conference Est');
%% INSERT INTO tligne VALUES ('Nom  Prenom Poste Nom Equipe Actuelle');
%% OPEN Cest;
%% FETCH Cest INTO dnom, dprenom, dposte, dnomequipe;
%% WHILE Cest%found LOOP  
%%   INSERT INTO tligne VALUES (dnom||' '||dprenom||' '||dposte||' '||dnomequipe); 
%%   FETCH Cest INTO dnom, dprenom, dposte, dnomequipe;
%% END LOOP;
%% CLOSE Cest;
%% INSERT INTO tligne VALUES ('Conference Ouest');
%% OPEN Couest;
%% INSERT INTO tligne VALUES ('Nom  Prenom Poste Nom Equipe Actuelle');
%% FETCH Couest INTO dnom, dprenom, dposte, dnomequipe;	 
%% WHILE Couest%found LOOP  
%%   INSERT INTO tligne VALUES (dnom||' '||dprenom||' '||dposte||' '||dnomequipe); 
%%   FETCH Couest INTO dnom, dprenom, dposte, dnomequipe;
%% END LOOP;
%% CLOSE Couest;
%% END;
%% .
%% /
%% SELECT * FROM tligne ;
%% \end{SaveVerbatim}

%%  \cache{\begin{footnotesize}
%%      \BUseVerbatim{Allstar}
%%    \end{footnotesize}
%%  }

\end{enumerate}

\end{exercice}



\end{document}
