\documentclass[a4paper,11pt]{article}
\usepackage[utf8x]{inputenc}
\usepackage[T1]{fontenc} 
\usepackage[french]{babel}
\usepackage[a4paper,hmargin=20mm,vmargin=30mm]{geometry}%\usepackage{fullpage}
\usepackage{lastpage}
\usepackage{tikz,pgflibraryarrows,pgffor,pgflibrarysnakes}
\usetikzlibrary{decorations.pathreplacing}
\usepackage{url}
\usepackage{comment}
\usepackage{amsmath}
\usepackage{amsthm}

\usepackage{eurosym}



\theoremstyle{definition}
\newtheorem{exemple}{Exemple}[section]
\newtheorem{exercice}{Exercice}
\newtheorem{remarque}{Remarque}[section]
\newtheorem{definition}{Définition}[section]

\usepackage{makeidx}
\usepackage[columnsep=9pt]{idxlayout}

\usepackage{fancyvrb}

%\makeindex
\selectlanguage{french}

\usepackage[font=small,labelfont=bf,justification=centering]{caption}
\captionsetup[table]{name=Tableau}

\usepackage{latexsym}
\usepackage{amsfonts}
\usepackage[normalem]{ulem}
\usepackage{array}
\usepackage{amssymb}
\usepackage{graphicx}

\usepackage{subfig}
\usepackage{wrapfig}
\usepackage{wasysym}
\usepackage{enumitem}
\usepackage{adjustbox}
\usepackage{longtable}
\usepackage{changepage}
\usepackage{setspace}
\usepackage{hhline}
\usepackage{multicol}
\usepackage{float}
\usepackage{multirow}
\usepackage{slashbox}

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

\usepackage{fancyvrb} 
\usepackage{fancyhdr}% fancy header
\usepackage{varwidth}
\usepackage{alltt}


 \fancypagestyle{monstyle}{
%\fancyhead{}
\renewcommand{\headrulewidth}{1pt}
%% %\renewcommand{\footrulewidth}{0.4pt}


\newcommand{\plsql}{PL/SQL}
 
% \fancyhead[LE]{\slshape \thepage/ \pageref{LastPage}}
%% \fancyhead[RO]{\slshape \thepage/ \pageref{LastPage}}


%\fancyhf{}          
%\fancyhead[LE]{\slshape LE}
%\fancyhead[CE]{\slshape CE}
%\fancyhead[RE]{\slshape RE}

\fancyhead[LO]{\bfseries\rightmark}   
%\fancyhead[CO]{\slshape APF}
\fancyhead[RO]{\bfseries\leftmark}

%% %\fancyfoot{}
% \fancyfoot[LE,RO]{}
 \fancyfoot[CO,CE]{\slshape\thepage/\pageref{LastPage}}
%% %\fancyfoot[LO,RE]{\small\slshape \ddmmyyyydate version du \today}

}

% \pagestyle{fancy}

 \pagestyle{monstyle}

\newcommand{\code}[1]{\texttt{#1}}

\usepackage{boxedminipage}

\newsavebox\svbx
\newif\ifcache
\long\def\cache#1{\ \newline
  \setbox\svbx=\vbox{\leavevmode \newline \begin{spacing}{1.5}#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

 \makeindex
 
 \begin{document}



\begin{titlepage}
\begin{center}

\textsc{\Large IUT Informatique Aubière \hfill 2019 - 2020} \\[.5cm]

\hrule 

\ \\[.5cm]

\vfill

\textsc{\LARGE Bases de données}

\vfill

\textsc{\LARGE \plsql{}}

\vfill

{\Large Pascale \textsc{Brigoulet}, Franck \textsc{Glaziou}, }

{\Large Pascal \textsc{Lafourcade} et Marie-Fran\c{c}oise
  \textsc{Servajean}}


\vfill


\begin{tikzpicture}

%%% un triangle

%% horizonatale
\draw[blue,line width=1pt] (-1,0) -- (1,0);
\draw[blue,line width=1pt] (-2.5,-.875) -- (1.5,-.875);
\draw[blue,line width=1pt] (-1.5,-1.75) -- (3,-1.75);
\draw[blue,line width=1pt] (0,3.5) -- (1,3.5);

%% Croissante
\draw[blue,line width=1pt] (0,0) -- (1,1.75);
\draw[blue,line width=1pt] (-2.5,-.875) -- (0,3.5);
\draw[blue,line width=1pt] (-1,0) -- (1,3.5);
\draw[blue,line width=1pt] (3,-1.75) -- (3.5,-0.75);

%% Decroissante
\draw[blue,line width=1pt] (0.5,.875) -- (1.5,-.875);
\draw[blue,line width=1pt] (1,1.75) -- (3,-1.75);
\draw[blue,line width=1pt] (1,3.5) -- (3.5,-0.75);
\draw[blue,line width=1pt] (-2.5,-.875) -- (-1.5,-1.75);



\end{tikzpicture}

%% \begin{tikzpicture}

%% %%% un cube

%% \draw[red,line width=1pt] (0,.5) -- (1,0);
%% \draw[red,line width=1pt] (2,.5) -- (1,0);

%% \draw[red,line width=1pt] (0,1.5) -- (1,1);
%% %\draw[red,line width=1pt] (0,1.5) -- (1,2);
%% \draw[red,line width=1pt] (0,1.5) -- (.5,1.75);
%% %\draw[red,line width=1pt] (2,1.5) -- (1,2);
%% \draw[red,line width=1pt] (2,1.5) -- (1.5,1.75);
%% \draw[red,line width=1pt] (2,1.5) -- (1,1);

%% \draw[red,line width=1pt] (1,1) -- (1,0);
%% \draw[red,line width=1pt] (0,1.5) -- (0,.5);
%% \draw[red,line width=1pt] (2,1.5) -- (2,.5);

%% %% droite

%% %\draw[red,line width=1pt] (1.5,1.25) -- (2.5,0.75);
%% \draw[red,line width=1pt] (2,1) -- (2.5,0.75);
%% \draw[red,line width=1pt] (3.5,1.25) -- (2.5,0.75);

%% \draw[red,line width=1pt] (1.5,2.25) -- (2.5,1.75);
%% \draw[red,line width=1pt] (1.5,2.25) -- (2.5,2.75);
%% \draw[red,line width=1pt] (3.5,2.25) -- (2.5,2.75);
%% \draw[red,line width=1pt] (3.5,2.25) -- (2.5,1.75);

%% \draw[red,line width=1pt] (2.5,1.75) -- (2.5,.75);
%% %\draw[red,line width=1pt] (1.5,2.25) -- (1.5,1.25);
%% \draw[red,line width=1pt] (1.5,2.25) -- (1.5,1.75);
%% \draw[red,line width=1pt] (3.5,2.25) -- (3.5,1.25);

%% %% Haut
%% \draw[red,line width=1pt] (0,2) -- (1,1.5);
%% %\draw[red,line width=1pt] (2,2) -- (1,1.5);
%% \draw[red,line width=1pt] (1.5,1.75) -- (1,1.5);

%% \draw[red,line width=1pt] (0,3) -- (1,2.5);
%% \draw[red,line width=1pt] (0,3) -- (1,3.5);
%% \draw[red,line width=1pt] (2,3) -- (1,3.5);
%% \draw[red,line width=1pt] (2,3) -- (1,2.5);

%% \draw[red,line width=1pt] (1,2.5) -- (1,1.5);
%% \draw[red,line width=1pt] (0,3) -- (0,2);
%% %\draw[red,line width=1pt] (2,3) -- (2,2);
%% \draw[red,line width=1pt] (2,3) -- (2,2.5);


%% \end{tikzpicture}

\vfill


\includegraphics[width=5cm]{iut-uca.png}
\end{center}

\vfill

{\Large Nom : \\

Prénom : \\
 
Groupe : \\
}
%\url{http://mocodo.wingi.net/}

%\url{http://mirror.hmc.edu/ctan/graphics/pgf/contrib/tkz-orm/tkz-orm.pdf}



\end{titlepage}

%% \section*{Avant Propos}

%% L’objectif de ce cours de base de données avancées est de
%% présenter 

%% TD 1 : → Exo3
%% TD 2 : Exo 3, 5, 6 7
%% TD 3 : Reste 
%% TD 4 :  Partiel
  
%% \newpage

\tableofcontents

\newpage

\begin{center}
\LARGE {\bf \plsql{}}
\end{center}

PL/SQL (Procedural Language / Structured Query Language) est un
langage fondé sur les paradigmes de programmation procédurale et
structurée. C'est un langage propriétaire, créé par Oracle et utilisé
dans le cadre de bases de données relationnelles. Il permet de
combiner des requêtes SQL et des instructions procédurales (boucles,
conditions...), dans le but de créer des traitements complexes
destinés à être stockés sur le serveur de base de données (objets
serveur), comme des procédures stockées ou des déclencheurs.

\section{Fichier de commandes SQL/PLUS}

SQL/Plus est un utilitaire en ligne de commande d'Oracle qui permet
aux utilisateurs d'exécuter interactivement des commandes SQL et
PL/SQL. Il est ainsi possible de paramètrer les fichiers de commandes
SQL. Pour cela il est important de stocker des informations dans des
variable : \code{variable vnoproduit CHAR(6)}. Cette commande déclare
une «bind variable» utilisable dans une commande SQL. Les diff\'erents
formats autorisés sont : \code{NUMBER}, \code{CHAR(n)} et
\code{VARCHAR2(n)}. Afin d'interagir avec l'utilisateur il existe deux
commandes :

\code{PROMPT   taper le N° du produit}

Cette commande affiche le texte placé après prompt. Attnetion il n'y a
pas de  quote.

\code{ACCEPT  vnoproduit}

Cette commande permet la saisie d'une variable au clavier et la
déclare si elle ne l’était pas.

\code{SELECT  *  FROM tproduit WHERE    N°produit = ‘\&vnoproduit’;}

\code{\&vnoproduit} permet d'acc\'eder \`a la chaîne de caractères
stock\'ee dans la variable \code{vnoproduit}.

\code{PRINT  vnoproduit}

Cette commande affiche le contenu de la variable.



\section{Exécution du code  PL/SQL}


En SQL, les commandes sont transmises les unes après les autres et
traitées séparément par le moteur SQL, comme le montre la
Figure~\ref{fig:plsql1}.

\begin{figure}[htb]
\begin{center}
  \includegraphics[width=12cm]{plsql2.png}
\end{center}
\caption{}\label{fig:plsql1}
\end{figure}


En extension procédurale de SQL (\plsql{}), les blocs de commandes
sont transmis globalement au moteur SQL, comme le montre la
Figure~\ref{fig:plsql2}.

\begin{figure}[htb]
\begin{center}
  \includegraphics[width=12cm]{plsql1.png}
\end{center}
\caption{Interaction entre PL/SQL et SQL.}\label{fig:plsql2}
\end{figure}


\section{Exemple de programme \plsql{}}

Le fichier de commandes ci-dessous permet la saisie de la référence
d’un produit et l’affichage de sa désignation ou d’un  message
d’erreur si le N° de produit n’existe pas.

\begin{verbatim}
set echo off
set verify off
set feed off

variable vnoproduit  char(4)
variable vdesignation varchar2(30)
prompt 		taper la référence du produit à rechercher :
accept  vnoproduit
\end{verbatim}
\begin{SaveVerbatim}{VerbEnv}
declare
dnoproduit char(4);

begin
dnoproduit := ‘&vnoproduit’;
select designation into :vdesignation
from tproduit  where noproduit = dnoproduit;

exception
when no_data_found then
  :vdesignation := ‘référence inconnue’;
end;
\end{SaveVerbatim}
  \fbox{\BUseVerbatim{VerbEnv}}
\begin{verbatim}
.
/
print vdesignation

set verify on
set feed on
set echo on
\end{verbatim}

\begin{remarque}
  Ce fichier comporte trois parties :
  \begin{itemize}
  \item des commandes SQL+ pour la saisie de la référence produit,
  \item un bloc \plsql{} pour accéder à la base,
  \item des commandes SQL+ pour afficher  le résultat.
  \end{itemize}
\end{remarque}

\plsql{} ne comprend pas d’instruction de saisie ou d’affichage. Les
commandes \code{SET} positionnent des variables d’environnement pour
éviter que le système n’affiche des informations « polluant » le
résultat :
\begin{itemize}
\item \code{set echo off} évite que le système n’affiche la commande
  du bloc PL/SQL au moment où il l’exécute,
\item \code{set verify off} évite que le système n’affiche l’opération
  de substitution au moment où il la fait,
\item \code{set feed off} évite que le système n’affiche le nombre de
  lignes sélectionnées,
\item  \code{.}	le point indique la fin du mode PL/SQL,
\item \code{/}   (seul sur une ligne) déclenche l’exécution du bloc PL/SQL ou de l’ ordre SQL stocké dans le buffer.
\end{itemize}

\section{Structure d'un bloc \plsql{}}

\plsql{} n'interprète pas une commande, mais un ensemble de commandes
contenu dans un "bloc" \plsql{}.  Un bloc est composé de trois
sections.
\begin{itemize}
\item Les sections \code{DECLARE} et \code{EXCEPTION} sont facultatives.  
\item Chaque instruction, de n'importe quelle section, est terminée
  par un \code{;}
\item Possibilité de placer des commentaires : \code{/* commentaire
  sur plusieurs lignes commençant par au moins un espace */}
\end{itemize}

Attention aux points virgules: en cas d’oubli, Oracle affiche un N° de
ligne attendant la suite de commande SQL.

\begin{figure}[htb]
\begin{center}
  \includegraphics[width=12cm]{bloc.png}
\end{center}
\caption{Structure d'un programme \plsql{}.}\label{fig:bloc}
\end{figure}

\section{Types de variables utilisés en \plsql{}}

Variables locales déclarées dans \code{DECLARE} et il est important de
mettre le type adapt\'e en suivant la syntaxe suivante :

  \verb+nom_variable   type := valeur;+

Les diff\'erents types possibles sont : \code{CHAR, NUMBER, DATE,
  VARCHAR2}.

Il est n\'ecessaire de choisir le type \`a l'initialisation lors de la
déclaration et aussi sa valeur intiale comme le montre les deux
exemples suivants :
\begin{itemize}
\item  \code{NB NUMBER := 1;}
\item  \verb+nom_variable   nomtable.nomcol %type+
\end{itemize}

\begin{exemple} Cr\'eation de variable.

\code{dnoprod    tproduit.noproduit \%type;}
  
\code{ddesignation  tproduit.designation \%type ;}
\end{exemple}

Il est possible de cr\'eer  des tableaux en \plsql{}. %
%% Variables de l'environnement extérieur à \plsql{}:
%% \begin{itemize}
%% \item champs d'écran en SQL*Forms,
%% \item variables définies en langage hôte dans PRO*.  Les variables de
%%   l’environnement sont toujours préfixées.
%\item
 Les variables définies dans SQL*Plus par \code{VARIABLE} ou
\code{ACCEPT} sont préfixées de : pour affectation, de "\verb+&+" pour
substitution.

%  \end{itemize}

\begin{exemple} Exemple simple d'utilisation de variable.
\begin{verbatim}
dnoproduit := '&vnoproduit';
select designation into :vdesignation     
from tproduit    
where  noproduit = '&vnoproduit';

select designation  into  ddesignation     
from tproduit 
where noproduit = dnoproduit;
\end{verbatim}

Tableaux PL/SQL.

Déclaration :

\begin{verbatim}
DECLARE 
...
TYPE tchar4 IS TABLE OF CHAR(4)
INDEX BY BINARY_INTEGER ;
table_noprod tchar4 ;
p BINARY_INTEGER ;
\end{verbatim}

Utilisation :

\begin{verbatim}
BEGIN
...
p := 1 ;
table_noprod(p) := ‘p001’ ;
\end{verbatim}
\end{exemple}

\section{Les traitements du bloc \code{BEGIN}}
\subsection{L'ordre SELECT :}
\begin{itemize}
\item Syntaxe :
  \begin{verbatim}
		SELECT coll, col2
		INTO var1, var2
		FROM table
		[WHERE condition];
\end{verbatim}
      \item
        Règle :
	\begin{itemize}
	\item La clause \code{INTO} est {\bf obligatoire}.
	\item Le \code{SELECT} doit obligatoirement ramener une ligne
          et une seule, sinon erreur. Pour traiter un ordre
          \code{SELECT} qui pourrait ramener plusieurs lignes, il faut
          utiliser un curseur.
        \end{itemize}
\end{itemize}
	Les autres ordres de manipulation sont inchangés; des
        variables peuvent être utilisées :
\begin{verbatim}
INSERT INTO table VALUES(var1, ‘chaine’, 123, var2);
UPDATE table SET col2 = var1 WHERE col1 = var2;
\end{verbatim}

\begin{exercice}
 Nombre de fournisseurs d’un produit donné : le résultat sera écrit
  dans une table \code{ligne}. Les tables utilis\'ees sont donn\'ees
  dans la Figure~\ref{fig:bd}.
\end{exercice}

\subsection{Traitements conditionnels \code{IF...THEN...END IF;}}
\begin{verbatim}
		IF condition1 THEN traitement1;
		ELSE traitement2;
		END IF;
\end{verbatim}

Les opérateurs utilisés dans les conditions sont les même que dans SQL
:

\verb+ =, <, >, !=, >=, <=, IS NULL, IS NOT NULL, BETWEEN, LIKE, AND, OR, ...+


\begin{exercice}
Nombre de fournisseurs d’un produit donné : s’il n’y a pas de
fournisseur, compter le nombre de produits : il doit être $\geq 1$ ou
0. \'Ecrire dans une table de lignes soit le nombre de fournisseurs
soit le message ‘\code{le produit n’existe pas}’.
\end{exercice}

\subsection{Traitements répétitifs \code{WHILE ...LOOP ...END LOOP;}}

	La boucle \code{WHILE}: L'exécution de la boucle se fait tant
        que la condition de la clause de \code{WHILE} est vérifiée.
\begin{verbatim}
		BEGIN
			WHILE condition
			LOOP
				instructions;
			END LOOP;
		END;
\end{verbatim}
La condition est une combinaison d'expressions au moyen d'opérateurs :
\verb+<, >, =, !=, AND, OR, LIKE, ...+

\begin{exemple}Calcul de factorielle.
\begin{verbatim}
CREATE TABLE tligne (ligne VARCHAR2(200));
VARIABLE n NUMBER
PROMPT taper n
ACCEPT n

DECLARE
fn NUMBER := 1;
i NUMBER :=1;
n NUMBER :='&n';
BEGIN
	WHILE i<n
	LOOP
		i := i + 1;
		fn := fn * i;
	END LOOP;

	INSERT INTO tligne
		VALUES ( 'Factorielle de '|| TO_CHAR(n)||, ‘  ‘,TO_CHAR(fn));
END;
/
SELECT * FROM tligne;
DROP TABLE tligne;
\end{verbatim}
\end{exemple}

\section{Gestion des erreurs : \code{EXCEPTION ... WHEN ... THEN}}
\subsection{La section \code{EXCEPTION}}

La section \code{EXCEPTION} permet d'affecter un traitement approprié
aux erreurs survenues lors de l'exécution du bloc \plsql{}.

Les types d'erreurs sont les suivants :
\begin{itemize}	
\item erreurs Oracle: elles sont prédéfinies,
\item erreur programme utilisateur : à déclarer.
\end{itemize}


\begin{exemple}  Les résultats à afficher sont placés dans
une table \code{tligne}.

\begin{verbatim}
create table tligne ( ligne varchar2(150));
variable vnoproduit char(4)
prompt taper la référence du produit à rechercher :
accept vnoproduit

declare
dnoproduit char(4) ;
ddesignation varchar2(30);
dmessage varchar2(150);

begin
dnoproduit := ‘&vnoproduit’ ;

dmessage := 'Référence inconnue ';
select designation into ddesignation From tproduit  where noproduit = dnoproduit ;

insert into tligne values ('Désignation: ' || ddesignation);

exception
when no_data_found then
	 insert into tligne values ( dmessage);
end ;
.
/
select * from tligne;
drop table tligne;
\end{verbatim}
\end{exemple}

\begin{remarque}  Le message d'erreur est initialisé juste avant la requête SQL qui risque de provoquer l'erreur; la méthode est à utiliser quand plusieurs requêtes SQL sont susceptibles de déclencher la même exception.
\end{remarque}

\begin{exercice}
 Enregistrer une livraison pour un produit donné :
\begin{itemize}
\item  saisie du numéro de produit et de la quantité livrée,
\item accès au stock du produit : exception ‘\code{référence inconnue}’, 
\item calcul du nouveau stock et mise à jour du stock.
\end{itemize}
\end{exercice}

\begin{exercice} Enregistrer  un nouveau produit d’un fournisseur :
\begin{itemize}
\item saisie des références du produit et du fournisseur, du prix
  fournisseur,
\item accès au produit pour vérifier qu’il existe,
\item accès au fournisseur pour vérifier qu’il existe,
\item accès à la liaison produit-fournisseur pour vérifier qu’elle n’est pas déjà enregistrée,
\item  enregistrement de la liaison.
\end{itemize}
\end{exercice}


\subsection{Erreur Oracle}

Dès que l'erreur Oracle est rencontrée, passage automatique à la
section \code{EXCEPTION} pour réaliser le traitement approprié à
l'erreur.  L’erreur est documentée par un code d’erreur \code{SQLCODE}
et un message \code{SQLERRM}.

Syntaxe :			
\begin{verbatim}
EXCEPTION
WHEN nom erreur THEN traitement;
[WHEN nom erreur THEN traitement;]
...
[WHEN OTHERS THEN traitement;]
\end{verbatim}
	Sortie du bloc après exécution du traitement.

Les principales erreurs Oracle prédéfinies sont d\'ecrires dans le
tableau ci-dessous.

\begin{tabular}{l|l|l}
déclenchée par : & nom de l’erreur :& valeur correspondante du
\code{sqlcode}\\
\hline 
\code{insert}, \code{update}	&	\verb+DUP_VAL_ON_INDEX+ &	-1\\
		&	\verb+INVALID_CURSOR+  & 	-1001 \\
		&	\verb+INVALID_NUMBER+ &	-1722 \\
		&	\verb+LOGIN_DENIED+ & 	-1017 \\
\code{select}	 &	\verb+NO_DATA_FOUND+ &  	+100	(non
déclenché par \code{update} ou \code{delete},\\
& & \phantom{+100 (}ni par \verb+select count+, \code{select sum})\\
		& \verb+NO_LOGGED_ON+  & -1012\\
		& \verb+PROGRAM_ERROR+ & -6501\\
		& \verb+STORAGE_ERROR+ & -6500 \\
		& \verb+TIMEOUT_ON_RESOURCE+ & -51 \\
\code{select}   	& \verb+TOO_MANY_ROWS+ & -1422 \\
		&\verb+VALUE_ERROR+  & 	-6502\\
		&\verb+ZERO_DIVIDE+ & -1476\\
		& \verb+OTHERS+ &  toutes les autres erreurs non
explicitement nommées, \\ && en particuliers celles concernant les
contraintes d’intégrité \\ && et les conflits d’accès.  \code{Others}
doit être la dernière erreur \\ &&  de la section \code{exception}.\\
\end{tabular}

                        
\begin{exemple}[Détection de doublons sur une clé primaire.]
La séquence suivante crée une ligne dans  la table \code{tproduit (noproduit char(4) primary key, ...)} et stocke les erreurs dans une table \code{tligne (ligne varchar2(150));}
	
\begin{verbatim}
BEGIN		    	
INSERT INTO tproduit VALUES (dnoproduit, ddesignation ...);				
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
INSERT INTO tligne VALUES (dnoproduit  ||  'déjà inséré');
END;
\end{verbatim}
\end{exemple}

\begin{exemple} Récupération du message d’erreur retourné par Oracle en cas
  d’exception.
  
  Attention : \code{SQLERRM} et \code{SQLCODE} ne peuvent être
  utilisés directement dans une instruction SQL. Il faut les récupérer
  dans une variable.
\begin{verbatim}
		DECLARE
			dnom	tproduit.designation%type;
			dmess1	VARCHAR2(100);
			dmess2	VARCHAR2(100);
		BEGIN
			dmess1 := 'Référence inconnue';			
			SELECT designation INTO dnom FROM tproduit
			WHERE noproduit = ‘&vnoproduit’;

		EXCEPTION
			WHEN OTHERS THEN
			dmess2 := SQLERRM;
			INSERT INTO tligne VALUES (dmess1);
			INSERT INTO tligne VALUES (dmess2);
			COMMIT;
		END;
\end{verbatim}
\end{exemple}

\begin{exercice}	Mise en évidence des  exceptions \verb+TOO_MANY_ROWS, OTHERS+
				
Pour mettre en évidence l’exception \verb+TOO_MANY_ROWS+, créez un
fichier de commandes SQL qui: demande un numéro de fournisseur, accède
aux N° des produits de ce fournisseur (par \code{select into}) retourne le
message ‘\code{le fournisseur n’a pas de produit}’ ou ‘\code{le fournisseur a plusieurs
produits}’, ou le N° du produit s’il n’en a qu’un.

Le résultat sera placé dans une table \code{TLIGNE (LIGNE
  varchar2(200))} Placez aussi dans cette table le \code{SQLCODE} et
le message Oracle obtenus à l’issue de \code{SELECT}.

Modifiez le programme en remplaçant une des deux exceptions  par \code{OTHERS}.
\end{exercice}


\section{Les curseurs}
\subsection{\code{DECLARE, OPEN, FETCH, CLOSE}}

Lorsqu’une requête \code{SELECT} est susceptible de délivrer plusieurs
lignes, on associe à celle ci un «curseur explicite» qui va
permettre d’accéder aux lignes du résultat. L’algorithme est analogue
au traitement d’un fichier séquentiel.

\begin{exemple} Traitement des rayons d’un étage donné.

\begin{verbatim}
DECLARE 
detage trayon.etage%TYPE;
dcode_rayon trayon.code_rayon%TYPE;
dnom_rayon trayon.nom_rayon%TYPE;

CURSOR r IS select code_rayon, nom_rayon from trayon where etage = detage;

BEGIN
detage := 2;
 OPEN r;
FETCH  r  INTO dcode_rayon, dnom_rayon;

WHILE r%FOUND
LOOP	
 ... traitement de la ligne lue ...
FETCH r INTO dcode_rayon, dnom_rayon;
END LOOP;
CLOSE r;
END;
\end{verbatim}
\end{exemple}

\begin{exercice} Pourcentage de produits ayant un stock nul (une solution avec curseur et une sans).
\end{exercice}

\begin{exercice} Créer une table des produits classés par valeur du stock : No de produit, désignation, valeur du stock, classement.
\end{exercice}

\begin{exercice} Créer une table des produits qui n’ont pas de fournisseur et une table des produits qui en ont avec les noms de leurs fournisseurs.
\end{exercice}

\subsection{\code{UPDATE, DELETE ... WHERE CURRENT OF curseur}}
Lors du parcours d'une table (ou une vue modifiable) par
\code{FETCH} à l’aide d’un curseur, il est possible de demander à mettre à jour
ou supprimer la ligne courante par la condition \code{WHERE CURRENT
  OF} nom du curseur. Le curseur doit avoir été déclaré \code{FOR
  UPDATE}

\begin{verbatim}
CURSOR  r  IS 
select code_rayon, nom_rayon from trayon where etage = detage FOR UPDATE;
\end{verbatim}

La mise à jour se fera par :
\begin{verbatim}
UPDATE trayon SET nom_rayon = dnom_rayon WHERE CURRENT OF r;
COMMIT;
\end{verbatim}

Attention, terminer par \code{COMMIT}, sinon risque d’interblocage
entre deux exécutions qui voudraient écrire dans la même table.

\begin{exercice}
  augmenter de 10\% les produits de plus de 1000\euro{}, et de 5\% les autres.
\end{exercice}

Erreur utilisateur : \code{EXCEPTION, RAISE}

Le traitement de l’anomalie doit être déclenché en passant dans la
partie \code{EXCEPTION} par \code{RAISE}.
\begin{verbatim}
DECLARE
...
nom_erreur EXCEPTION;
...
BEGIN
...
IF anomalie
THEN RAISE nom_erreur;
...
EXCEPTION
WHEN nom_erreur THEN
traitement à effectuer en cas d’anomalie;
END;
\end{verbatim}

Sortie du bloc après exécution du traitement.

\begin{exemple}
Accèder au stock d’un produit de Numéro donné avec Erreur Oracle quand
le produit n’existe pas et Erreur utilisateur quand le stock est
nul. Les anomalies sont placées dans une table \code{terreur(z1
  varchar2(30), z2 varchar2(30))}

\begin{verbatim}
DECLARE
...
stock_nul EXCEPTION;
dstock number;
...
BEGIN
SELECT stock INTO dstock FROM tproduit WHERE noproduit = ‘&vnoproduit’;
IF stock = 0
THEN RAISE stock_nul;
traitement quand le stock n’est pas nul...
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO terreur VALUES (‘&vnoproduit’, ‘produit inconnu’);
WHEN stock_nul THEN
INSERT INTO terreur VALUES (‘&vnoproduit’, ‘stock nul’);
END;
\end{verbatim}
\end{exemple}

\begin{exercice} Pour remplacer l’erreur Oracle par une erreur utilisateur, compter le nombre de produits ayant le numéro donné et déclencher une exception si ce nombre est nul.
\end{exercice}


\newpage

\begin{figure}[htb]
\begin{center}
  \includegraphics[width=18cm]{BD.png}
\end{center}
\caption{Base de donn\'ees pour les exercices.}\label{fig:bd}
\end{figure}

\newpage


\begin{center}
  {\bf Commandes utiles pour les TP}
\end{center}

\paragraph{Premi\`ere s\'eance :}  Connexion : \verb+sqlplus <user>/<password>@KIROV+

\verb+source /etc/profile+

Lancer \verb+sqlplus+ avec cette commande \verb+rlwrap sqlplus+ vous
permet d'avoir l'historique.


Lors de la première connexion modifier le mot de passe avec la
commande SQL : \verb+PASSWORD;+

Ce qui est équivalent à :
\verb+ALTER USER dupond IDENTIFIED BY password;+

Si le mot de passe est \'egar\'e quelque part, il faut se connecter en
\code{ssh} sur \code{londres} et faire \code{oracle\_passwd}


Pour lancer un fichier \verb+.sql+ en sqlplus, il suffit de taper :
\verb+@toto.sql;+

Pour quitter sqlplus, il suffit de taper : \verb+quit;+


\paragraph{Mise en forme : }

Sous SQL/PLUS :
\begin{verbatim}
Set linesize 150 -- positionne la taille d'une ligne
Set pagesize 300 --  positionne le nombre de lignes avant de réafficher les entêtes
Set pages 0 --  n'affiche pas les entêtes
Col <nom_colonne> for A10 --  défini que la colonne nom_colonne va être affiché sur 10 caractères
alphanumériques, 999.99 pour les valeurs numériques.
\end{verbatim}


\paragraph{Corbeille :} Vider les tables \verb+BIN$$xxxx+ : avec la
commande \verb+PURGE RECYCLEBIN;+


\paragraph{D\'ebug :} Afficher la strucutre de la table \code{nba} : \verb+describle nba;+

Connaître l'utilisateur connect\'e : \verb+show user;+

Liste des tables d'un \verb+user+ : \verb+SELECT table_name FROM user_tables;+

Lister les tables accessibles par l'utilisateur
: \verb+ SELECT table_name FROM all_tables;+

Lister toutes les tables possédées par un utilisateur
\verb+SELECT * FROM all_tables WHERE owner='PALAFOUR';+

Liste des vues d'un \code{user} : \verb+SELECT view_name FROM user_views;+

Liste des contraintes : \verb+SELECT * FROM user_constraints WHERE table_name=’<table>’;+

\verb+SELECT * FROM user_cons_columns WHERE table_name='<table>";+

\verb+show errros+ affiche les erreurs des fonctions.

\paragraph{Contraintes :} Description d'une table : \verb+describe <table>+ ou
\verb+desc <table>+;

Liste des colonnes concernées par les contraintes :
\verb+SELECT * FROM user_cons_columns;+

Lire une table d'un autre schéma :

\verb+SELECT * FROM <schema>.<table_name>; -- ou schma = login de connexion de l'utilisateur+



\paragraph{Affichage :}
\verb+SET HEADING OFF+

\verb+SET FEEDBACK OFF+

\paragraph{Travailler \`a la maison}

Il est possible d'acc\`eder par SSH \`a la machine
\texttt{londres}. L'adresse de la passerelle est
\texttt{ssh.iut-clermont.uca.fr} qui n'est accessible que par une
authentification avec des clefs SSH.

Cet acc\`es vous permettra d'acc\`eder au serveur de base de donn\'ees
comme lorsque vous travailler \`a l'IUT. Avant de pouvoir se
connecter, il faut activer l'acc\`es \`a l'IUT sur
\texttt{http://erlin.iut.local} ce qui peut prendre 30 minutes.

Pour  d\'eposer vos clefs vous pouvez utiliser
\url{https://homeweb.iut-clermont.uca.fr}

%.ssh/authorized_keys
%londres.iut.local
%SSH http://cr2i.intranet.iut.local/site/page/documentation/ssh/


%% Faire du SQLPLUS depuis chez-vous en faisant du SSH en tapant cette
%% commande où vous devez remplacer LOGIN par votre login pour vous
%% connecter sur Linux à l'IUT: \verb+ssh LOGIN@193.49.118.206+

%% Le workflow le plus propre est d'avoir un fichier sur votre machine
%% personnelle que vous copier en faisant un \code{scp} sur la machine

%% Par exemple la commande ci-dessous copie le fichier
%% creation-donnees.sql de mon ordintaeur sur la machine virtuelle

%% \verb+scp creation-donnees.sql palafour@193.49.118.206:.+

%% Par contre une fois que je suis déconnecté de ma connexion ssh tous
%% les fichiers peuvent \^etre détruits car votre repertoire personnel
%% (home) sur ce serveur est TEMPORAIRE.  Vos donnees peuvent etre
%% perdues a tout moment.  Ne stocker RIEN ici.



\paragraph{En cas de blocage :}

Dans un terminal executer la commande suivante pour voir les \code{pid}
des processus zombies : \verb+ps -aux | grep sqlplus+

Ensuite tuer ces zombies gr\^ace \`a la commande \code{kill -9 numerodepid}
 \newpage
 %\newpage
 
%\printindex
 \end{document}
