Programmation NQC Application à la commande d’un robot RCX ...
Interface de programmation Application / BD - … · Département de génie logiciel et des TI...
Transcript of Interface de programmation Application / BD - … · Département de génie logiciel et des TI...
Département de génie logiciel et des TI
LOG660 - Bases de données de haute performance
Interface de programmation Application / BD
Hiver 2011 C. Desrosiers
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 2
Interface entre SQL et un programme
SQL incomplet
Défaut d'impédance (impedance mismatch)
– modèle de données BD ≠
– modèle de données du langage de programmation
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 3
Interface programmatique (Call-Level Interface - SQL/CLI)
API spécifique au SGBD
– e.g. Oracle Call Interface (OCI)
– non portable
API normalisée
– standard de facto ODBC
développé par Microsoft pour le C
– pilote ODBC pour client/serveur
– SQL/CLI de SQL:1999 inspirée de ODBC
– JDBC pour Java
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 4
SQL enchâssé (Embedded SQL)
Code SQL dans le source du langage hôte Syntaxe spéciale Pré-compilation
– Oracle : pro*C/C++, pro*COBOL, …, SQLJ
Moins portable – pré-compilateur spécifique au SGBD – traduit en API du SGBD
SQLJ (partie 0) traduit en API standard JDBC
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 5
Extension procédurale à SQL (Persistent Stored Modules - SQL/PSM)
SQL + – structures de contrôle – procédures, fonctions, packages – support direct des types SQL pour les variables – exécution au niveau serveur de BD
Oracle – PL/SQL
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 6
Bloc PL/SQL
[DECLARE déclaration [déclaration] ...]
BEGIN séquenceEnoncés[EXCEPTION exception_énoncé [exception_énoncé] ...]END
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 7
Exécution d’un bloc sous SQL*plus
SQL> DECLARE 2 laQuantitéEnStock Article.quantitéEnStock%TYPE; 3 BEGIN 4 SELECT quantitéEnStock INTO laQuantitéEnStock 5 FROM Article 6 WHERE noArticle = 10; 7 IF laQuantitéEnStock = 0 THEN 8 DBMS_OUTPUT.PUT_LINE('L article est en rupture de stock'); 9 ELSE 10 DBMS_OUTPUT.PUT('Quantité en stock :'); 11 DBMS_OUTPUT.PUT_LINE(laQuantitéEnStock); 12 END IF; 13 EXCEPTION 14 WHEN NO_DATA_FOUND THEN 15 DBMS_OUTPUT.PUT_LINE('Numéro d article inexistant'); 16 WHEN OTHERS THEN 17 RAISE_APPLICATION_ERROR(-20001,'Erreur soulevée par le SELECT'); 18 END; 19 /Quantité en stock :20
PL/SQL procedure successfully completed.
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 8
Déclaration de variables PL/SQL (DECLARE)
leNoClient Client.noClient%TYPE;
leNoClient INTEGER;
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 9
Transfert d'une valeur de colonne d'un SELECT dans une variable (clause INTO)
SELECT noClient, dateCommandeINTO leNoClient, laDateCommandeFROM CommandeWHERE noCommande = leNoCommande;
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 10
Affectation en PL/SQL
laQuantitéEnAttente:= laQuantitéCommandée -laQuantitéLivrée;
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 11
Structure de contrôle IF
IF (laQuantitéLivrée IS NULL) THENDBMS_OUTPUT.PUT_LINE(' livraison en attente');
ELSElaQuantitéEnAttente:= laQuantitéCommandée -laQuantitéLivrée;IF (laQuantitéEnAttente = 0) THEN
DBMS_OUTPUT.PUT_LINE(' livraison complétée');ELSE
DBMS_OUTPUT.PUT (' quantité en attente :');DBMS_OUTPUT.PUT_LINE(laQuantitéEnAttente);
END IF ;END IF ;
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 12
Boucles (LOOP, FOR, WHILE)
LOOP séquenceEnoncésEND LOOP ;
FOR indice IN [REVERSE] valeurInitiale..valeurFinale LOOPséquenceEnoncés
END LOOP ;
WHILE condition LOOP séquenceEnoncésEND LOOP ;
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 13
Traitement d'exception (EXCEPTION, RAISE)
Déclarer
Soulever
Attraper
nomException EXCEPTION;
RAISE nomException
WHEN nomException THENséquenceÉnoncés
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 14
Curseur PL/SQL (CURSOR)
CURSOR lignesCommande(unNoCommande Commande.noCommande%TYPE)IS SELECT noArticle, quantité FROM LigneCommande WHERE LigneCommande.noCommande = unNoCommande ;
OPEN lignesCommande(leNoCommande);-- Le OPEN ouvre le CURSOR en lui passant les paramètres
LOOPFETCH lignesCommande INTO leNoArticle, laQuantitéCommandée;-- Le FETCH retourne la ligne suivante
EXIT WHEN lignesCommande%NOTFOUND;-- %NOTFOUND est un attribut du CURSOR qui permet de déterminer-- si le FETCH a atteint la fin de la table
…
END LOOP;
-- Le CLOSE ferme le CURSORCLOSE lignesCommande;
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 15
Boucle FOR pour curseur PL/SQL
FOR uneLigne IN lignesCommande(leNoCommande) LOOP
DBMS_OUTPUT.PUT('noArticle :');DBMS_OUTPUT.PUT(uneLigne.noArticle);DBMS_OUTPUT.PUT(' quantité commandée:');DBMS_OUTPUT.PUT(uneLigne.quantité);
-- Chercher la quantité déjà livréeSELECT SUM(quantitéLivrée)INTO laQuantitéLivréeFROM DétailLivraisonWHERE noArticle = uneLigne.noArticle AND
noCommande = leNoCommande ;
IF (laQuantitéLivrée IS NULL) THENDBMS_OUTPUT.PUT_LINE(' livraison en attente');
ELSElaQuantitéEnAttente:= uneLigne.quantité -laQuantitéLivrée;IF (laQuantitéEnAttente = 0) THEN
DBMS_OUTPUT.PUT_LINE(' livraison complétée');ELSE
DBMS_OUTPUT.PUT (' quantité en attente :');DBMS_OUTPUT.PUT_LINE(laQuantitéEnAttente);
END IF ;END IF ;
END LOOP;
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 16
Procédures et fonctions PL/SQL stockées
SQL> CREATE FUNCTION fQuantitéEnStock 2 (unNoArticle Article.noArticle%TYPE) 3 RETURN Article.quantitéEnStock%TYPE IS 4 5 uneQuantitéEnStock Article.quantitéEnStock%TYPE; 6 BEGIN 7 SELECT quantitéEnStock 8 INTO uneQuantitéEnStock 9 FROM Article 10 WHERE noArticle = unNoArticle; 11 RETURN uneQuantitéEnStock; 12 END fQuantitéEnStock; 13 14 /
Function created.
SQL> select fQuantitéEnStock(10) from dual;
FQUANTITÉENSTOCK(10)-------------------- 10
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 17
Procédure stockée
SQL> CREATE PROCEDURE pModifierQuantitéEnStock 2 (unNoArticle Article.noArticle%TYPE, 3 nouvelleQuantitéEnStock Article.quantitéEnStock%TYPE) IS 4 BEGIN 5 UPDATE Article 6 SET quantitéEnStock = nouvelleQuantitéEnStock 7 WHERE noArticle = unNoArticle; 8 END pModifierQuantitéEnStock; 9 /
Procedure created.
SQL> EXECUTE pModifierQuantitéEnStock(10,20);
PL/SQL procedure successfully completed.
SQL> SELECT * FROM Article WHERE noArticle = 10;
NOARTICLE DESCRIPTION PRIXUNITAIRE QUANTITÉENSTOCK---------- -------------------- ------------ --------------- 10 Cèdre en boule 10,99 20
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 18
Privilèges dans une routine stockée
Privilèges de l'appelant (invoker rights)
Privilèges de la routine (definer rights) – privilèges du créateur – par défaut
CREATE PROCEDURE pModifierQuantitéEnStock(unNoArticle Article.noArticle%TYPE, nouvelleQuantitéEnStock Article.quantitéEnStock%TYPE)AUTHID CURRENT_USER IS
BEGIN UPDATE Article SET quantitéEnStock = nouvelleQuantitéEnStock WHERE noArticle = unNoArticle;END pModifierQuantitéEnStock;
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 19
Exemple privilège de l’appelant SQL> connect godin/oracle Connected. SQL> CREATE OR REPLACE PROCEDURE pModifierQuantitéEnStock 2 (unNoArticle Article.noArticle%TYPE, 3 nouvelleQuantitéEnStock Article.quantitéEnStock%TYPE) 4 AUTHID CURRENT_USER IS 5 BEGIN 6 UPDATE Article 7 SET quantitéEnStock = nouvelleQuantitéEnStock 8 WHERE noArticle = unNoArticle; 9 END pModifierQuantitéEnStock; 10 / Procedure created. SQL> grant execute on pModifierQuantitéEnStock to public; Grant succeeded. SQL> connect test/oracle Connected. SQL> EXECUTE godin.pModifierQuantitéEnStock (10,500); PL/SQL procedure successfully completed. SQL> select * from article; NOARTICLE DESCRIPTION PRIXUNITAIRE QUANTITÉENSTOCK ---------- -------------------- ------------ --------------- 10 Cèdre en boule 10,99 500 20 Sapin 12,99 10 … SQL> select * from godin.article; select * from godin.article * ERROR at line 1: ORA-00942: table or view does not exist
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 20
Exemple privilège du créateur SQL> connect godin/oracle Connected. SQL> CREATE OR REPLACE PROCEDURE pModifierQuantitéEnStock 2 (unNoArticle Article.noArticle%TYPE, 3 nouvelleQuantitéEnStock Article.quantitéEnStock%TYPE) 4 IS 5 BEGIN 6 UPDATE Article 7 SET quantitéEnStock = nouvelleQuantitéEnStock 8 WHERE noArticle = unNoArticle; 9 END pModifierQuantitéEnStock; 10 / Procedure created. SQL> grant execute on pModifierQuantitéEnStock to public; Grant succeeded. SQL> connect test/oracle Connected. SQL> EXECUTE godin.pModifierQuantitéEnStock (10,700); PL/SQL procedure successfully completed. SQL> select * from article; NOARTICLE DESCRIPTION PRIXUNITAIRE QUANTITÉENSTOCK ---------- -------------------- ------------ --------------- 10 Cèdre en boule 10,99 500 20 Sapin 12,99 10 …
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 21
Exemple privilège du créateur (suite)
SQL> select * from godin.article; select * from godin.article * ERROR at line 1: ORA-00942: table or view does not exist SQL> connect godin/oracle Connected. SQL> select * from article; NOARTICLE DESCRIPTION PRIXUNITAIRE QUANTITÉENSTOCK ---------- -------------------- ------------ --------------- 10 Cèdre en boule 10,99 700 20 Sapin 12,99 10 40 Épinette bleue 25,99 10 50 Chêne 22,99 10 60 Érable argenté 15,99 10 70 Herbe à puce 10,99 10 80 Poirier 26,99 10 81 Catalpa 25,99 10 90 Pommier 25,99 10 95 Génévrier 15,99 10 10 rows selected.
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 22
Package PL/SQL CREATE PACKAGE nomPaquetage AS
listeDesSignaturesDesFonctions&ProcéduresEND nomPaquetage ;
CREATE PACKAGE BODY nomPaquetage ASdélaration [déclaration]…
BEGIN séquenceÉnoncésInitialisationEND nomPaquetage;
nomPaquetage.nomObjet
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 23
JDBC
API standard pour JAVA http://java.sun.com/products/jdbc/ Ensemble de classes Besoin d ’installer un pilote JDBC dans
l ’environnement JAVA
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 24
Architecture pour les pilotes JDBC
API JDBC
Type 1Passerelle JDBC-
ODBC
Application Java(import java.sql.*)
Type 2Partie Java
Pilote ODBC(e.g. pilote ODBC
Oracle)
Type 3Pilote JDBCgénérique
Type 4Pilote JDBC tout
Java(e.g. Oracle thin)
ServeurJDBC
API client duSGBD
(e.g. ocijdbc8.dllpour Oracle)
Serveur de BD
Type ?Oracle server-
side thin etinternal driver
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 25
Chargement d'un pilote JDBC et établissement d'une connexion
Charger les pilotes JDBC d ’ Oracle
Établir une connexion avec le pilote OCI8 pour un serveur Oracle local
Class.forName ("oracle.jdbc.driver.OracleDriver");
Connection uneConnection =DriverManager.getConnection("jdbc:oracle:oci8:@", "toto", "secret");
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 26
Création d’un énoncé SQL (Statement)
Statement
executeQuery(arg0 : String) : ResultSetexecuteUpdate(arg0 : St ring) : intclose() : voidgetMaxFieldSize() : intsetMaxFieldSize(arg0 : int) : voidgetMaxRows() : intsetMaxRows(arg0 : int) : voidsetEscapeProcessing(arg0 : boolean) : voidgetQueryTimeout() : intsetQueryTimeout(arg0 : int) : voidcancel() : voidgetWarnings() : SQLWarningclearWarnings() : voidsetCursorName(arg0 : String) : voidexecute(arg0 : String) : booleangetResultSet() : ResultSetgetUpdateCount() : intgetMoreResults() : booleansetFetchDirection(arg0 : int) : voidgetFetchDirection() : intsetFetchSize(arg0 : int) : voidgetFetchSize() : intgetResultSetConcurrency() : intgetResultSetType() : intaddBatch(arg0 : String) : voidclearBatch() : voidexecuteBatch() : int[]getConnection() : Connection
<<Interface>>
Statement unEnoncéSQL = uneConnection.createStatement ();
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 27
Exécution d'une opération de mise à jour (INSERT, DELETE, UPDATE)
import java.sql.*;
class ClientInsertJDBC{ public static void main (String args []) throws SQLException, ClassNotFoundException, java.io.IOException { // Charger le pilote JDBC d'Oracle Class.forName ("oracle.jdbc.driver.OracleDriver");
// Connexion à une BD Connection uneConnection = DriverManager.getConnection ("jdbc:oracle:oci8:@", "godin", "oracle");
// Création d'un énoncé associé à la Connection Statement unEnoncéSQL = uneConnection.createStatement ();
// Insertion d'une ligne dans la table Client int n = unEnoncéSQL.executeUpdate ("INSERT INTO CLIENT " + "VALUES (100, 'G. Lemoyne-Allaire', '911')"); System.out.println ("Nombre de lignes inserees:" + n);
// Fermeture de l'énoncé et de la connexion unEnoncéSQL.close(); uneConnection.close(); }}
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 28
Exécution d'un SELECT (ResultSet)
… Début analogue à l'exemple précédent
// Création d'un énoncé associé à la Connexion Statement unEnoncéSQL = uneConnection.createStatement();
// Exécution d'un SELECT ResultSet résultatSelect = unEnoncéSQL.executeQuery ("SELECT noClient, nomClient "+ "FROM CLIENT " + "WHERE noClient > 40");
// Itérer sur les lignes du résultat du SELECT et extraire les valeurs // des colonnes dans des variables JAVA
while (résultatSelect.next ()){int noClient = résultatSelect.getInt ("noClient");
String nomClient = résultatSelect.getString ("nomClient"); System.out.println ("Numéro du client:" + noClient); System.out.println ("Nom du client:" + nomClient); } }}
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 29
Support des types SQL:1999 sous JDBC 2
CREATE TABLE tableBlob (idBlob INTEGER PRIMARY KEY,imageBLOB)
// Chercher le BLOB locator ResultSet unResultSet = unEnoncéSQL.executeQuery ("SELECT * FROM tableBlob WHERE idBlob = 1"); if (unResultSet.next()){
int idBlob = unResultSet.getInt(1); Blob unBlob = unResultSet.getBlob(2);
// Chercher la taille du BLOB et l'afficher int taille = (int)unBlob.length(); System.out.println("Taille du BLOB" + taille);
// Lire le BLOB dans un tableau d'octets byte octets[] = unBlob.getBytes(1, taille);
// Créer un fichier contenant les octets lus FileOutputStream unFichier = new FileOutputStream("C:/forte4j/Development/ExemplesJDBC/CopieCoq1.gif"); unFichier.write(octets); unFichier.close();
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 30
Compilation et exécutions multiples avec la classe PreparedStatement
Statement unEnoncéSQL = uneConnection.createStatement();ResultSet résultatSelect = unEnoncéSQL.executeQuery ("SELECT noClient, nomClient "+ "FROM CLIENT " + "WHERE noClient > 40");
PreparedStatement unEnoncéSQL = uneConnection.prepareStatement("SELECT noClient, nomClient "+ "FROM CLIENT " + "WHERE noClient > 40");
ResultSet résultatSelect = unEnoncéSQL.executeQuery();
PreparedStatement unEnoncéSQL = uneConnection.prepareStatement("SELECT noClient, nomClient "+
"FROM CLIENT " + "WHERE noClient > ?");unEnoncéSQL.setInt(1,40);ResultSet résultatSelect = unEnoncéSQL.executeQuery();
Compilation + exécution combinée au executeQuery
Compilation au prepareStatement
Compilation avec paramètres CallableStatement
PreparedStatement
Statement
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 31
Exécution en lot (batch) sous JDBC 2
// Création d'un PreparedStatement associé à la Connection PreparedStatement unEnoncéSQL = uneConnection.prepareStatement ("INSERT INTO Client VALUES(?,?,?)");
// Ajout d'un INSERT dans le lot unEnoncéSQL.setInt(1,90); unEnoncéSQL.setString(2,"Edgar Degas"); unEnoncéSQL.setString(3,"(222)222-2222"); unEnoncéSQL.addBatch();
// Ajout d'un autre INSERT dans le lot unEnoncéSQL.setInt(1,100); unEnoncéSQL.setString(2,"Claude Monet"); unEnoncéSQL.setString(3,"(111)111-1111"); unEnoncéSQL.addBatch();
// Exécution du lot en un appel int [] résultats = unEnoncéSQL.executeBatch();
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 32
Exécution d'une procédure ou fonction stockée (CallableStatement)
// Création d'un appel de fonction associé à la Connection CallableStatement unCall =
uneConnection.prepareCall("{ ? = call fQuantitéEnStock(?)}");
// Spécification du paramètre d'entrée unCall.setInt(2,10); // Inscription de la sortie unCall.registerOutParameter(1, java.sql.Types.INTEGER); // Exécution de l'appel unCall.execute(); // Récupération de la sortie int laQuantite = unCall.getInt(1);
System.out.println("Quantité en stock :"+laQuantite); }; unCall.close(); uneConnection.close();
Département de génie logiciel et des TI © R. Godin, C. Desrosiers - Hiver 2011 33
Appel de procédure stockée
CallableStatement unCall =uneConnection.prepareCall("{call pModifierQuantitéEnStock(?,?)}");
// Spécification des paramètres d'entrée unCall.setInt(1,10); unCall.setInt(2,20); // Exécution de l'appel unCall.execute(); unCall.close(); uneConnection.close();