\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}

\usepackage{fourier}
\usepackage{fontawesome}




\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}
\newcommand{\sql}{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.25}#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 2020 - 2021} \\[.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}

\plsql{} (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}

\sql{} est un utilitaire en ligne de commande d'Oracle qui permet
aux utilisateurs d'exécuter interactivement des commandes \sql{} et
\plsql{}. Il est ainsi possible de paramètrer les fichiers de commandes
\sql{} pour avoir plus d'interaction avec l'utilisateur.

\paragraph{Variables.}
Il possible de stocker des donn\'ees dans des variables. La commande
\code{variable vnoproduit CHAR(6)} d\'eclare une variable appell\'ee
\code{vnoproduit} de type cha\^ine de caract\`eres de longueur
$6$. Afin de se souvenir qu'une variable est d\'eclar\'ee par le mot
cl\'e \code{variable} \`a l'ext\'erieur d'un bloc \plsql{}, il est
conseill\'e de pr\'efixer les noms de ces variables par la lettre
\code{v}. 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)}.


Pour acc\'eder \`a une variable il faut pr\'efixer son nom par la
caract\`ere sp\'ecial \& ainsi \code{\&vnoproduit} permet d'acc\'eder
\`a la chaîne de caractères stock\'ee dans la variable
\code{vnoproduit}. Il est alors possible de faire des requ\^etes SQL
qui utilisent le contenu de ces varaibles :

\code{SELECT * FROM tproduit WHERE Nproduit = ‘\&vnoproduit’;}



\paragraph{Interaction avec l'utilisateur.}

Afin d'interagir avec l'utilisateur, il existe deux types de commandes.

\begin{description}
\item[Affichage :] Il est possible d'\'ecrire le contenu d'une
  variable et d'afficher du texte.
  \begin{itemize}
\item  Pour afficher le contenu d'une variable, il faut utiliser la commande
\code{PRINT} comme suit :

\code{PRINT  vnoproduit}

  \item Pour \'ecrire un message visible par l'utilisateur,
  il faut utiliser le mot cl\'e \code{prompt}. Par exemple la commande
  suivante affiche le texte placé après \code{prompt} :

\code{PROMPT taper le nom du produit}

\faWarning{} Attention il n'y a pas de quote.

  \end{itemize}
\item[Saisie :] La seconde commande permet de saisir des donn\'ees par un
  utilisateur.  La commande suivante permet la saisie d'une variable
  au clavier et la déclare si elle ne l’était pas.
  
\code{ACCEPT  vnoproduit}
\end{description}



\section{Exécution du code  \plsql{}}

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}
\begin{tikzpicture}
\node[draw] (a) at  (0,1)  {\begin{minipage}[h][2cm][t]{5cm} 
Fichier de commandes SQL\\
~\quad  \code{SELECT} ...\\
~\quad  \code{UPDATE} ...\\
~\quad  \code{UPDATE} ...\\
  \end{minipage}
};

\draw[thick,-latex] (2.75,1.75) -- (7.75,1.75) node[midway,above] {\code{SELECT} ...};

\draw[thick,-latex] (2.75,1) -- (7.75,1) node[midway,above] {\code{UPDATE} ...};

\draw[thick,-latex] (2.75,.25) -- (7.75,.25) node[midway,above] {\code{UPDATE} ...};
\node[draw] (b) at (10,1) {
\begin{minipage}[h][2cm][t]{4cm} 
\ \\
\ \\
\centering MOTEUR SQL\\
  \end{minipage}
};
\end{tikzpicture}
%  \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}
\begin{tikzpicture}
\node[draw] (a) at  (0,1)  {\begin{minipage}[h][3.25cm][t]{5cm} 
Bloc \plsql{}\\
\code{BEGIN} \\
~~~~~~\code{SELECT} ...\\
~\quad  \code{IF} ... \code{THEN}\\
~\quad \code{UPDATE} ...\\
~\quad \code{UPDATE} ...\\
~\quad \code{END;}\\
  \end{minipage}
};


\draw[thick,-latex] (2.75,1) -- (7.75,1) node[midway,above] {
  \begin{minipage}[h][1.22cm][t]{3cm}
\code{BEGIN} \\
~~~~~~\code{SELECT} ...\\
~\quad  \code{IF} ... \code{THEN}\\
~\quad \code{UPDATE} ...\\
~\quad \code{UPDATE} ...\\
~\quad \code{END;}\\
  \end{minipage}
};

\node[draw] (b) at (10,1) {
\begin{minipage}[h][3.25cm][t]{4cm} 
\ \\
\ \\
\ \\
\centering MOTER SQL\\
  \end{minipage}
};
\end{tikzpicture}
%  \includegraphics[width=12cm]{plsql1.png}
\end{center}
\caption{Interaction entre \plsql{} et SQL.}\label{fig:plsql2}
\end{figure}

\faWarning{}  \plsql{} ne comprend pas d’instruction de saisie ou d’affichage.

\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. Ce fichier comporte trois
parties :
  \begin{itemize}
  \item des commandes SQL+ pour la saisie de la référence produit,
  \item un bloc \plsql{} encadr\'e dans l'exemple, il permet d'accéder
    à la base de donn\'ees,
  \item des commandes SQL+ pour afficher le résultat.
  \end{itemize}


\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}

\faWarning{} Apr\`es la fin du bloc il faut imp\'erativement  mettre :

\begin{itemize}
\item  \code{.}	: ce point indique la fin du mode \plsql{},
\item \code{/} (seul sur une ligne) : cela déclenche l’exécution du
  bloc \plsql{} ou de l’ ordre \sql{} stocké dans le buffer.
\end{itemize}



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 \plsql{} 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,
\end{itemize}



Les variables définies dans \sql{} par \code{VARIABLE} ou
\code{ACCEPT} sont préfixées de : pour affectation, de "\verb+&+" pour
substitution.


\begin{exercice}
  \'Ecrire un fichier \sql{} qui permet d'afficher le message ``Entrer
  votre age :'', de saisir l'\^age de l'utilisateur dans la variable
  \code{vage}, d'ajouter un \`a cette valeur et d'afficher ``Votre age
  plus un est 20 ans'' si $19$ est la valeur saisie par l'utilisateur
  et $20$ le contenu de la variable \code{vage}.
\end{exercice}

\cache{
variable vage NUMBER
  
PROMPT Entrer votre age

ACCEPT vage

begin

:vage:= 1 + \&vage;

end;

.

/

PROMPT Votre age est

PRINT vage

PROMPT ans
}


\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 */}
\item Il est conseill\'e d'utiliser \code{-}\code{-} en d\'ebut de ligne pour les commentaires.
\end{itemize}

\faWarning{} Attention aux points virgules: en cas d’oubli, Oracle affiche un
num\'ero de ligne attendant la suite de commande SQL.

\begin{figure}[htb]
\begin{center}
  \fbox{
    \begin{minipage}[h][2cm][t]{15cm} 
  \code{DECLARE} \\
  D\'eclartion des variables locales au bloc, des constantes, des
  execeptions, des cureurs.\\
\  \\
  (facultative)
    \end{minipage}
  }

  \ \\
  \ \\
  
  \fbox
      {
        \begin{minipage}[h][7.25cm][t]{15cm} 
   \qquad     \fbox{
    \begin{minipage}[h][3cm][t]{10cm} 
  \code{BEGIN} \\
  \ \\
Instructions \plsql{} et \sql{} \\
Possibilit\'es de blocs imbriqu\'es\\
\  \\
  (obligatoire)
    \end{minipage}
   }
   
   
\qquad    \fbox{
    \begin{minipage}[h][3cm][t]{10cm} 
  \code{EXCEPTION} \\
Traitements des erreurs, des cas particuliers\\
\  \\
  (facultative)
    \end{minipage}
   }
\ \\

   \code{END ;}
\end{minipage}
   }
  %  \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{}}

En \plsql{} les diff\'erents types possibles sont : \code{CHAR,
  NUMBER, DATE, VARCHAR2}. Les variables locales sont 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;+


  
\paragraph{Cr\'eation de variable.}

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{Nom VARCHAR2(100);}
\item  \code{NB NUMBER := 1;}
\item  \verb+dnoproduit tproduit.noproduit %type;+
\end{itemize}

La dereni\`ere d\'eclaration de la variable \verb+dnoproduit+ avec le
type \verb+tproduit.noproduit %type+ permet de prendre le m\^eme type
que le champs \code{noproduit} de la table \code{tproduit}.



\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}
\end{exemple}


%% 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


%  \end{itemize}


\paragraph{Tableaux \plsql{}.}

Il est possible de cr\'eer des tableaux en \plsql{}. Pour cela il faut
d\'efinir un type avec la commande \verb+IS TABLE OF+ et
\verb+INDEX BY BINARY_INTEGER+. Ensuite il faut utiliser la syntaxe
adapt\'ee pour acc\'eder aux \'el\'ements du tableau ainsi cr\'e\'e.

\begin{exemple} Exemple de cr\'eation et  d'utilisation d'un tableau.

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

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

\section{Les traitements du bloc \code{BEGIN}}

Dans le bloc \plsql{}, il est possible de d'affecter les r\'esultats
de \code{SELECT} dans des varaibles, de faire des tests et de boucles.

\subsection{SELECT ... INTO ...}

Les r\'esultats monolignes des commandes \code{SELECT} peuvent \^etre
strock\'es dans des variables du m\^emes types gr\^ace au mot cl\'e
\code{INTO}. Par contre si un \code{SELECT} retourne plusieurs lignes
alors il n'est pas possible de stocker ce r\'esultat dans une
variable. Pour cela il faut utiliser un \emph{curseur} comme indiqu\'e
dans la section~\ref{sec:curseur}.

\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 \sql{} de manipulation sont inchangés et 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}
Calculer le nombre de fournisseurs d’un produit entr\'e par
l'utilisateur.  Le résultat sera écrit dans une table
\code{Tligne}. Les tables utilis\'ees sont donn\'ees dans la
Figure~\ref{fig:bd}.
\end{exercice}

\cache{
variable vnoproduit char(4)

PROMPT Saisir un numero de produit

ACCEPT vnoproduit

DECLARE

dnbfournisseurs number ;

BEGIN

SELECT COUNT(*) INTO dnbfournisseurs FROM tProduitfourn
WHERE noproduit = '\&vnoproduit' ;

INSERT INTO Tligne VALUES('Le nombre de fournisseur du produit'
||'\&vnoproduit'||' est '|| dnbfournisseurs) ; END ;

.

/

SELECT * FROM Tligne ;
}

\subsection{Traitements conditionnels \code{IF ... THEN ... END IF;}}


Les opérateurs utilisés dans les conditions en \plsql{} sont les mêmes que dans \sql{} :

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

La syntaxe pour \'ecrire une condition est la suivante :

\begin{verbatim}
		IF condition1 THEN traitement1;
		ELSE traitement2;
		END IF;
\end{verbatim}


\begin{exercice}
Calculer le 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 \code{Tligne} soit le nombre de
fournisseurs soit le message ‘\code{le produit n’existe pas}’.
\end{exercice}

\cache{
variable vnoproduit char(4)

PROMPT Saisir un numero de produit

ACCEPT vnoproduit

DECLARE

dnbfournisseur number;

dnbproduit number;

BEGIN

SELECT COUNT(*) INTO dnbfournisseur FROM TPRODUITFOURN WHERE noproduit = '\&vnoproduit';

IF dnbfournisseur = 0

THEN SELECT COUNT(*) INTO dnbproduit FROM TPRODUIT WHERE noproduit = '\&vnoproduit';

  END IF;
  
  IF dnbproduit  = 0 THEN INSERT INTO Tligne VALUES('Pas de produit'||'\&vnoproduit');

ELSE

INSERT INTO Tligne VALUES('Le nombre de fournisseur du produit'
||'\&vnoproduit'||' est '|| dnbfournisseur);

END IF;

END;

.

/

SELECT * FROM Tligne;
}

\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 TABLEl Tligne;
\end{verbatim}
\end{exemple}

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

Lorsqu'une instruction se passe mal en \plsql, une \emph{exception}
est lev\'ee. Il est possible de sp\'ecifier une comportement adpat\'e
dans ce cas dans la section \code{EXCEPTION}.

\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}. Lorsque la requ\^ete \sql{} ne produit pas de
r\'esultats alors une exception est lev\'ee.

\begin{verbatim}
drop table Tligne;
create table Tligne (Tligne 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;
\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 si ‘\code{référence inconnue}’, 
\item calcul du nouveau stock et mise à jour du stock.
\end{itemize}
\end{exercice}

 \cache{
CREATE TABLE tLigne(

 designation VARCHAR2(500)

 );

set echo off

set verify off

set feed off

variable vnoP CHAR(5)

variable vql NUMBER

PROMPT Entrer le num du prod :

ACCEPT vnoP

PROMPT Entrer la quantitée livré :

ACCEPT vql

DECLARE

dCo NUMBER;

BEGIN

SELECT stock INTO dCo

FROM tProduit

WHERE noprod = '\&vnoP';

dCo:= dCo + \&vql;

UPDATE tProduit SET stock = dCo WHERE noprod = '\&vnoP';

EXCEPTION

when no\_data\_found then

insert into Tligne values('référence inconnue');

end;

.

/


set echo on

set verify on

set feed on
}


 
\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 (Exception \`a g\'erer),
\item  enregistrement de la liaison.
\end{itemize}
\end{exercice}


 \cache{
set echo off set verify off set feed off

CREATE TABLE tLigne(designation VARCHAR2(500));

variable vRefProduit CHAR(5);

variable vRefFournisseur CHAR(5);

variable vPrixFournisseur NUMBER;

prompt Tappez la référence du nouveau produit:

accept vRefProduit

prompt Tappez la référence du fournisseur du nouveau produit:

accept vRefFournisseur

prompt Tappez le prix du produit:

accept vPrixFournisseur

DECLARE

dCount NUMBER;

NO\_PRODUIT EXCEPTION;

NO\_FOURNISSEUR EXCEPTION;

PRODUIT\_FOURNISSEUR\_ALREADY\_EXIST EXCEPTION;


BEGIN

SELECT COUNT(*) INTO dCount FROM tProduit WHERE noProduit = '\&vRefProduit';

IF dCount = 0 THEN  RAISE NO\_PRODUIT;

SELECT COUNT(*) INTO dCount FROM tFournisseur WHERE ref = '\&vRefFournisseur';

IF dCount = 0 THEN  RAISE NO\_FOURNISSEUR;

SELECT COUNT(*) INTO dCount FROM tProduitFourn WHERE noProduit = '\&vRefProduit' AND ref = '\&vRefFournisseur';

IF dCount != 0 THEN  RAISE PRODUIT\_FOURNISSEUR\_ALREADY\_EXIST;

INSERT INTO tProduitFourn VALUES('\&vRefProduit', '\&vRefFournisseur', '\&vPrixFournisseur', NULL, NULL);

INSERT INTO tLigne VALUES('La liaison entre le produit et le fournisseur a ete ajoute');

EXCEPTION

when NO\_PRODUIT then

INSERT INTO tLigne VALUES('La liaison ne peut exister car le produit renseigne n existe pas');

when NO\_FOURNISSEUR then

INSERT INTO tLigne VALUES('La liaison ne peut exister car le fournisseur renseigne n existe pas');

when PRODUIT\_FOURNISSEUR\_ALREADY\_EXIST then

INSERT INTO tLigne VALUES('La liaison existe deja, et n a donc pas ete ajoute une seconde fois.')

END;

.

/

SELECT * FROM tLigne;
   
}


\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.
  
\faWarning{}  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} Pour mettre en évidence l’exception \verb+TOO_MANY_ROWS+, créez un fichier de commandes \sql{} qui:
  \begin{itemize}
  \item demande un numéro de fournisseur,
  \item accède aux N° des produits de ce fournisseur (par \code{select into})
  \item 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. 
  \end{itemize}
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}

\cache{
SET echo OFF
SET verify OFF
SET feed OFF

DROP TABLE tligne;

CREATE TABLE Tligne(ligne VARCHAR2(200));

variable Vref CHAR(5)

PROMPT Donner un numero de fournisseur:

ACCEPT Vref

declare

DnoProduit char(5);

BEGIN

SELECT noProduit INTO DnoProduit FROM tProduitFourn WHERE ref = '\&Vref';

INSERT INTO Tligne VALUES('Le fournisseur'||' \&Vref '||' a un produit :'|| DnoProduit);

exception

when no\_data\_found then

INSERT INTO Tligne VALUES('Le fournisseur n a pas de produit');

WHEN too\_many\_rows then

INSERT INTO Tligne VALUES('Le fournisseur a plusieurs produits');

END;

.

/

SELECT * FROM Tligne;

SET echo ON
SET verify ON
SET feed ON
  }


\subsection{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}

\cache{
set echo off set verify off set feed off

CREATE TABLE tLigne(designation VARCHAR2(200));

variable vNumProduit CHAR(5);

prompt Choisissez un numero de produit

accept vNumProduit

DECLARE

NO\_PRODUCTS\_SELECTED EXCEPTION;

dCountProduit NUMBER;

BEGIN

SELECT COUNT(*) INTO dCountProduit FROM tProduit WHERE noProduit = '\&vNumProduit';

IF dCountProduit = 0 THEN   RAISE NO\_PRODUCTS\_SELECTED;

EXCEPTION

when NO\_PRODUCTS\_SELECTED then

INSERT INTO tLigne VALUES('Le produit n existe pas');

  END;

.

/

SELECT * FROM tLigne;

set echo on
set verify on
set feed on  
}

\section{Les curseurs}\label{sec:curseur}

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.

\subsection{\code{DECLARE, OPEN, FETCH, CLOSE}}
Il faut d'abord d\'eclarer le curseur dans le bloc \code{DECLARE},
ensuite ouvrir le curseur avec la commande \code{OPEN} et penser \`a
le ferm\'e une fois celui-ci utilis\'e. Pour acc\'eter aux donn\'ees
les unes apr\`es les autres il faut utiliser la commande \code{FETCH}.

\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} Caculer le pourcentage de produits ayant un stock nul. Proposer une solution  avec curseur et une sans.
\end{exercice}

\cache{


set echo off
set verify off
set feed off

CREATE TABLE tLigne(designation VARCHAR2(200));

DECLARE

dStockNull NUMBER := 0;

bin NUMBER;

dNbProduit NUMBER := 0;

CURSOR r IS SELECT stock FROM tProduit;

BEGIN

OPEN r;

FETCH r INTO bin;

WHILE r\%FOUND

LOOP

IF bin = 0 then dStockNull := dStockNull + 1;  END IF;

dNbProduit := dNbProduit + 1;

FETCH r INTO bin;

END LOOP;

CLOSE r;

-- Solution sans curseur

-- SELECT COUNT(*) INTO dStockNull FROM tProduit WHERE stock = 0;

-- SELECT COUNT(*) INTO dNbProduit FROM tProduit;

dStockNull := (dStockNull * 100) / dNbProduit;

INSERT INTO tLigne VALUES('Il y a '||dNbProduit||'pourcentage de produits avec un stock vide.');

END;
.
/

SELECT * FROM tLigne;
}


\begin{exercice} Afficher les produits classés par valeur du stock : No de produit, désignation, valeur du stock, classement.
\end{exercice}

\cache{SET echo OFF
SET verify OFF
SET feed OFF

DROP TABLE tligne;

CREATE TABLE Tligne(ligne VARCHAR2(200));

DECLARE

DnoProduit tProduit.noProduit\%TYPE;

Ddesignation tProduit.designation\%TYPE;

Dstock tProduit.stock\%TYPE;

Dclassement NUMBER;

CURSOR r IS SELECT noProduit,designation,stock FROM tProduit ORDER BY stock;

BEGIN

Dclassement := 1;

INSERT INTO Tligne VALUES('noProduit designation stock classement');

OPEN r;

FETCH r INTO DnoProduit,Ddesignation,Dstock;

WHILE r\%FOUND

LOOP
	INSERT INTO Tligne VALUES(DnoProduit||' '||Ddesignation||' '||Dstock||' '||Dclassement);

	Dclassement := Dclassement + 1;

        FETCH r INTO DnoProduit,Ddesignation,Dstock;

END LOOP;

CLOSE r;

END;

.

/
}

\begin{exercice} Afficher les produits qui n’ont pas de fournisseur et les produits qui en ont avec les noms de leurs fournisseurs.
\end{exercice}

\cache{
SET echo OFF
SET verify OFF
SET feed OFF

DROP TABLE tligne;
CREATE TABLE Tligne(ligne VARCHAR2(200));

DROP TABLE tligne2;
CREATE TABLE Tligne2(ligne VARCHAR2(200));


DECLARE

DnoProduit tProduit.noProduit\%TYPE;

Ddesignation tProduit.designation\%TYPE;

Dstock tProduit.stock\%TYPE;

Dref tFournisseur.ref\%TYPE;

DlistFourn VARCHAR(1000);

CURSOR r IS SELECT noProduit,designation,stock FROM tProduit WHERE noProduit NOT IN (SELECT noProduit FROM tProduitFourn);

CURSOR t IS SELECT noProduit,designation,stock FROM tProduit;

CURSOR s IS SELECT ref FROM tProduitFourn WHERE noProduit = DnoProduit;

BEGIN

OPEN r;

INSERT INTO Tligne VALUES('noProduit    designation    stock');

FETCH r INTO DnoProduit,Ddesignation,Dstock;

WHILE r\%FOUND

LOOP
	INSERT INTO Tligne VALUES(DnoProduit||' '||Ddesignation||' '||Dstock);

	FETCH r INTO DnoProduit,Ddesignation,Dstock;

END LOOP;

CLOSE r;

OPEN t;

INSERT INTO Tligne2 VALUES('noProduit    designation    stock      reference fournisseur');

FETCH t INTO DnoProduit,Ddesignation,Dstock;

WHILE t\%FOUND

LOOP

DlistFourn :='';

OPEN s;

FETCH s INTO Dref;

WHILE s\%FOUND

LOOP

DlistFourn := DlistFourn||'   '||Dref;

FETCH s INTO Dref;

END LOOP;

CLOSE s;

INSERT INTO Tligne2 VALUES(DnoProduit||' '||Ddesignation||' '||Dstock||' 		 '||DlistFourn);

FETCH t INTO DnoProduit,Ddesignation,Dstock;

END LOOP;

CLOSE t;

END;

.

/

SELECT * FROM Tligne;
SELECT * FROM Tligne2;
SET echo ON
SET verify ON
SET feed ON
}

\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}

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

\begin{exercice}
  \'Ecrire un code \plsql{} qui augmente de 10\% les produits de plus
  de 1000\euro{}, et de 5\% les autres.
\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{} :
\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://berlin.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}
