You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1733 lines
41 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

\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}
%% Lobjectif 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 dinstruction de saisie ou daffichage.
\section{Exemple de programme \plsql{}}
Le fichier de commandes ci-dessous permet la saisie de la référence
dun produit et laffichage de sa désignation ou dun  message
derreur si le N° de produit nexiste 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 lexécution du
bloc \plsql{} ou de l ordre \sql{} stocké dans le buffer.
\end{itemize}
Les commandes \code{SET} positionnent des variables denvironnement
pour éviter que le système naffiche des informations « polluant » le
résultat :
\begin{itemize}
\item \code{set echo off} évite que le système naffiche la commande
du bloc \plsql{} au moment où il lexécute,
\item \code{set verify off} évite que le système naffiche lopération
de substitution au moment où il la fait,
\item \code{set feed off} évite que le système naffiche 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 doubli, 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
%% lenvironnement 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 dun 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 dun produit donné. Sil ny 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 nexiste 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 dun 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 quil existe,
\item accès au fournisseur pour vérifier quil existe,
\item accès à la liaison produit-fournisseur pour vérifier quelle nest 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. Lerreur est documentée par un code derreur \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 lerreur :& 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 dintégrité \\ && et les conflits daccè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 derreur retourné par Oracle en cas
dexception.
\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 lexception \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 na pas de produit} ou
\code{le fournisseur a plusieurs produits}, ou le N° du produit sil
nen a quun.
\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 à lissue 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 lanomalie 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 danomalie;
END;
\end{verbatim}
Sortie du bloc après exécution du traitement.
\begin{exemple}
Accèder au stock dun produit de Numéro donné avec Erreur Oracle quand
le produit nexiste 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 nest 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 lerreur 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}
Lorsquune requête \code{SELECT} est susceptible de délivrer plusieurs
lignes, on associe à celle ci un «curseur explicite» qui va permettre
daccéder aux lignes du résultat. Lalgorithme est analogue au
traitement dun 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 dun é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 nont 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}
à laide dun 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 dinterblocage
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}