Annonce 1

1ère Générale NSI

Annonce 2

Term. Générale NSI

Annonce 3

Terminale STI2D SIN

Annonce 4

Bts Ccst Technico-commercial 3.0

[[{"text":"
\"Download-World-Wide-Web-PNG-Image\"

Le \"World Wide Web\", plus communément appelé \"Web\" a été développé au CERN (Conseil Européen pour la Recherche Nucléaire) par le Britannique Sir Timothy John Berners-Lee et le Belge Robert Cailliau au début des années 90. À cette époque les principaux centres de recherche mondiaux étaient déjà connectés les uns aux autres, mais pour faciliter les échanges d'information Tim Berners-Lee met au point le système hypertexte. Le système hypertexte permet, à partir d'un document, de consulter d'autres documents en cliquant sur des mots clés. Ces mots \"cliquables\" sont appelés hyperliens et sont souvent soulignés et en bleu. Ces hyperliens sont plutôt connus aujourd'hui sous le simple terme de \"liens\".

\"première
première page web, les hyperliens sont soulignés et en bleu

Cette première page web est toujours consultable à l'adresse suivante : http://info.cern.ch/hypertext/WWW/TheProject.html


","posi":2}],[{"text":"

Tim Berners-Lee développe le premier navigateur web (logiciel permettant de lire des pages contenant des hypertextes), il l'appelle simplement \"WorldWideWeb\". Il faudra attendre 1993 et l'arrivée du navigateur web \"NCSA Mosaic\" pour que le web commence à devenir populaire en dehors du petit monde de la recherche.

Techniquement le web se base sur trois choses : le protocole HTTP (HyperText Transfert Protocol), les URL (Uniform Resource Locator) et le langage de description HTML (HyperText Markup Language). Nous aurons, très prochainement l'occasion de revenir sur ces trois éléments.

Une chose très importante à bien avoir à l'esprit : beaucoup de personnes confondent \"web\" et \"internet\". Même si le \"web\" \"s'appuie\" sur internet, les deux choses n'ont rien à voir puisqu'\"internet\" est un \"réseau de réseau\" s'appuyant sur le protocole IP alors que, comme nous venons de le voir, le web est la combinaison de trois technologies : HTTP, URL et HTML. D'ailleurs on trouve autre chose que le \"web\" sur internet, par exemple, les emails avec le protocole SMTP (Simple Mail Transfert Protocol) et les transferts de fichiers avec le protocole FTP (File Transfert Protocol).

"}],[{"text":"

Dans la barre d'adresse de votre navigateur web vous trouverez, quand vous visitez un site, des choses du genre : \"http://www.ac-grenoble.fr/disciplines/informatiquelycee/index.html\". Nous aurons l'occasion de reparler du \"http\" et du \"www.ac-grenoble.fr\" plus tard. La partie \"/disciplines/informatiquelycee/index.html\" s'appelle une URL.

Une URL (Uniform Resource Locator) permet d'identifier une ressource (par exemple un fichier) sur un réseau.

L'URL indique « l'endroit » où se trouve une ressource sur un ordinateur. Un fichier peut se trouver dans un dossier qui peut lui-même se trouver dans un autre dossier... On parle d'une structure en arborescence, car elle ressemble à un arbre à l'envers :

\"arbo\"
structure en arborescence

Comme vous pouvez le constater, la base de l'arbre s'appelle la racine de l'arborescence et se représente par un /


","title":"L'url","tagtitle":"h1"}],[{"text":"


Pour indiquer la position d'un fichier (ou d'un dossier) dans l'arborescence, il existe 2 méthodes : indiquer un chemin absolu ou indiquer un chemin relatif. Le chemin absolu doit indiquer « le chemin » depuis la racine. Par exemple l'URL du fichier fichier3.jpg sera : /dossier2/dossier3/fichier3.jpg

Remarquez que nous démarrons bien de la racine / (attention les symboles de séparation sont aussi des /)

Imaginons maintenant que le fichier fichier1.css fasse appel au fichier fichier3.jpg (comme un fichier HTML peut faire appel à un fichier CSS). Il est possible d'indiquer le chemin non pas depuis la racine, mais depuis le dossier (dossier2) qui accueille le fichier1.css, nous parlerons alors de chemin relatif :

dossier3/fichier3.jpg

Remarquez l’absence du / au début du chemin (c'est cela qui nous permettra de distinguer un chemin relatif et un chemin absolu).

Imaginons maintenant que nous désirions indiquer le chemin relatif du fichier fichier1.css depuis l'intérieur du dossier dossier4.

Comment faire ?

Il faut « remonter » d'un « niveau » dans l'arborescence pour se retrouver dans le dossier dossier2 et ainsi pouvoir repartir vers la bonne « branche ». Pour ce faire il faut utiliser 2 points : ..

../dossier2/fichier1.css

Il est tout à fait possible de remonter de plusieurs « crans » : ../../ depuis le dossier dossier4 permet de « retourner » à la racine.

","title":"Chemin absolu ou chemin relatif ?"}],[{"text":"

Exercice : 

Soit la structure en arborescence suivante:

\"arbo\"

Le contenu du fichier \"fichier7.odp\" utilise le fichier \"fichier5.svg\". Donnez le chemin relatif qui devra ẽtre renseigner dans le fichier \"fichier7.odp\" afin d'atteindre le fichier \"fichier5.svg\".

Donnez le chemin absolu permettant d'atteindre le fichier \"fichier6.html\".

"},{"edit":"

Vos réponses ici.

"}],[{"text":"Remarque : la façon d'écrire les chemins (avec des slash (/) comme séparateurs) est propre aux systèmes dits « UNIX », par exemple GNU/Linux ou encore Mac OS. Sous Windows, ce n'est pas le slash qui est utilisé, mais l'antislash (\\). Pour ce qui nous concerne ici, les chemins réseau (et donc le web), pas de problème, c'est le slash qui est utilisé."}],[{"text":"
\"Vector

Deux ordinateurs en réseau peuvent s'échanger des données. Dans la plupart des cas ces échanges ne sont pas \"symétriques\" : en effet un ordinateur A va souvent se contenter de demander des ressources (fichiers contenant du texte, photos, vidéos, sons...) à un ordinateur B. L'ordinateur B va lui se contenter de fournir des ressources à tous les ordinateurs qui lui en feront la demande. On dira alors que l'ordinateur A (celui qui demande des ressources) est un client alors que l'ordinateur B (celui qui fournit les ressources) sera qualifié de serveur.

En tapant «http://www.google.fr», votre machine va chercher à entrer en communication avec le serveur portant le nom «www.google.fr» (en faite c'est plus compliqué, pour les puristes nous dirons donc que la communication va être établie avec le serveur www du domaine google.fr, mais bon, pour la suite nous pourrons nous contenter de l'explication « simplifiée »).

Une fois la liaison établie, le client et le serveur vont échanger des informations en dialoguant :

client : bonjour www.google.fr (ou bonjour www se trouvant dans le domaine google.fr), pourrais-tu m'envoyer le fichier index.html

serveur : OK client, voici le fichier index.html

client : je constate que des images, du code css sont utilisés, peux-tu me les envoyer

serveur : OK, les voici

Évidemment ce dialogue est très imagé, mais il porte tout de même une part de « vérité ».

Sur internet, ce modèle client/serveur domine assez largement, même s'il existe des cas où un ordinateur pourra jouer tour à tour le rôle de client et le rôle de serveur, très souvent, des ordinateurs (les clients) passeront leur temps à demander des ressources à d'autres ordinateurs (les serveurs) . Par exemple, comme expliqué dans l'exemple ci-dessus on retrouve cet échange client/serveur à chaque fois que l'on visite une page web. Il y a de fortes chances pour que votre ordinateur personnel joue quasi exclusivement le rôle de client (sauf si vous êtes un adepte du \"peer to peer\").

N'importe quel type d'ordinateur peut jouer le rôle de serveur, mais dans le monde professionnel les serveurs sont des machines spécialisées conçues pour fonctionner 24h sur 24h. Ils peuvent aussi avoir une grosse capacité de stockage afin de stocker un grand nombre de ressources (vidéos, sons,...).

","title":"Client / Serveur"}],[{"text":"

Afin assurer une continuité de service, dans les sociétés, plusieurs serveurs assurent exactement le même rôle (on parle de redondance). Vous vous doutez bien que Google ne possède pas qu'un seul serveur, en effet, en moyenne, chaque seconde, c'est environ 65000 clients qui se connectent aux serveurs du moteur de recherche de Google. Aucun serveur, même extrêmement performant, ne serait capable de répondre à toutes ces requêtes. Google, Amazon ou encore Facebook possèdent un très grand nombre de serveurs afin de pouvoir satisfaire les demandes des utilisateurs en permanence. Ces entreprises possèdent d'immenses salles contenant chacune des centaines ou des milliers de serveurs (ces serveurs sont rangés dans des armoires appelées \"baie serveur\").

\"CERN

salle serveur

Souvent les serveurs sont spécialisés dans certaines tâches, par exemple, les serveurs qui envoient aux clients des pages au format HTML sont appelés \"serveur web\".

Il y a quelques années, le web était dit « statique » : le concepteur de site web écrivait son code HTML et ce code était simplement envoyé par le serveur web au client. Les personnes qui consultaient le site avaient toutes le droit à la même page, le web était purement « consultatif » ou statique.

"}],[{"text":"

Les choses ont ensuite évolué : les serveurs sont aujourd'hui capables de générer eux-mêmes du code HTML. Les résultats qui s'afficheront à l'écran dépendront donc des demandes effectuées par l'utilisateur du site : le web est devenu dynamique.

\"frontend.pngDifférents langages de programmation peuvent être utilisés « côté serveur » afin de permettre au serveur de générer lui-même le code HTML à envoyer. Le plus utilisé encore aujourd'hui se nomme PHP. D'autres langages sont utilisables côté serveur (pour permettre la génération dynamique de code HTML) : Java, Python, nodejs...

","title":"Pages web dynamiques"}],[{"text":"


Le lien ci-dessous renvoie la température d'une salle :

http://sciencesappliquees.com/templates/php/temp.php

Réaliser une page html qui affiche la température dans un div toutes les secondes.

Aide : 

  • Utiliser innerHTML pour mettre la valeur de la température dans le div;
  • Utiliser la fonction XMLHttpRequest() avec la script ci-dessous pour récupérer la température  1 fois sur le serveur:
<script type=\"text/javascript\">
//declaration de l'objet pour la requete
var maRequete = new XMLHttpRequest();
//l'adresse email du serveur
var url = \"http://sciencesappliquees.com/templates/php/temp.php\";

//gestion de la reponse du serveur
maRequete.onload = function() {
//reponse du serveur
alert(this.responseText); //Affiche la reponse du seveur dans une fenêtre \"alert\"

};//fin de la fonction reponse (get ou post, adresse , asynchrone)

//Choisir le type de requete
maRequete.open(\"GET\", url, true);
//envoyer la requete au serveur
maRequete.send();
</script>


Essayez ce code. Expliquez, en détail, ce qu'il fait.","title":"Les requête entre le serveur et le client"},{"edit":"

Commentez ici.

"},{"htm":"","css":"","js":""}],[{"text":"
  • Utiliser la fonction XMLHttpRequest() avec la script ci-dessous pour récupérer la température  toutes les 2 secondes sur le serveur: 
<script>
function lancerRequete(){
var maRequete = null; //initialiser l'objet

//déclare l'objet requete
if(window.XMLHttpRequest){
maRequete = new XMLHttpRequest();
}

//url du serveur
var url = \"http://sciencesappliquees.com/templates/php/temp.php\";

//Choisir le type de requete
maRequete.open(\"GET\", url, true);
//gestion de la reponse du serveur
maRequete.onreadystatechange = function(){
if(maRequete.readyState == 4){
//affiche la réponse du serveur
alert(maRequete.responseText);

}
}

   //envoyer la requete au serveur
maRequete.send();

//relance la fonction au bout de 2 secondes
setTimeout('lancerRequete()', 2000);
}
//lance la fonction
lancerRequete();
</script>

 

Faire valider votre travail par le professeur.

"},{"edit":"

Commentez ici.

"},{"htm":"","css":"","js":""}],[{"text":"

 

A l'aide de la bibliothèque RGraph, afficher la température dans une jauge toutes les secondes.

Aide :

  • Il faut ajouter dans le body de la page html une balise canvas avec l'id \"monCanvas\" pour afficher la jauge à l'intérieur :
<canvas id=\"monCanvas\" width=\"100\" height=\"400\">
[No canvas support]
</canvas>
  • Pour utiliser RGraph, il faut importer les librairies suivantes :

<script src=\"https://www.rgraph.net/libraries/RGraph.common.core.js\" ></script>
<script src=\"https://www.rgraph.net/libraries/RGraph.thermometer.js\" ></script>

  • Pour créer l'objet jauge, vous devez utilisez le script ci-dessous :
<script type=\"text/javascript\">
var thermometre = new RGraph.Thermometer({
   id: 'monCanvas',
   min: 0,
   max: 30,
   value: 20.3,
   options: {
   }
   }).draw();

</script>
  • Pour mettre à jour la valeur de la jauge, vous devez utiliser les instructions suivantes :
thermometre.value = laNouvelleValeur;
RGraph.Redraw();

 

Faire valider votre travail par le professeur.

","title":"La requête dans une Jauge"},{"edit":"

Commentez ici.

"},{"htm":"","css":"","js":""}],[{"text":"


Nous avons 2 \"input text\" sur une page html :

<label>Température</label><input type=\"text\" name=\"temp\" id=\"temp\" value=\"19\"><label>°C</label><br/>

<label>humidité</label><input type=\"text\" name=\"humi\" id=\"humi\" value=\"45\"><label>%</label>

Nous souhaitons envoyer leur contenu, au serveur ci-dessous, par la méthode Get.

http://sciencesappliquees.com/templates/php/metGet.php 

Réaliser le programme. 

Aide : 

  • Pour la méthode Get, l'url doit être sous la forme : adresseServeur?parametre1=valeur1&parametre2=valeur2
  • Pour récupérer la valeur d'un \"input text\", il faut utiliser l'instruction document.getElementById(\"idDuDiv\").value 

 Faire valider votre travail par le professeur. 

","title":"La requête Get"},{"edit":"

Commentez ici.

"},{"htm":"","css":"","js":""}],[{"text":"


Nous avons 2 \"input text\" sur une page html :

<label>Température</label><input type=\"text\" name=\"temp\" id=\"temp\" value=\"19\"><label>°C</label><br/>

<label>humidité</label><input type=\"text\" name=\"humi\" id=\"humi\" value=\"45\"><label>%</label>

Nous souhaitons envoyer leur contenu, au serveur ci-dessous, par la méthode Post.

http://sciencesappliquees.com/templates/php/metPost.php 

Réaliser le programme. 

Aide : 

  • Utiliser la fonction XMLHttpRequest() avec la script ci-dessous pour récupérer la température  1 fois sur le serveur:
<script>

   //déclaration de l'objet contenant les données à envoyer.
   var data = \"parametre1=valeur1&parametre2=valeur2\";

//declaration de l'objet pour la requete   
var maRequete = new XMLHttpRequest();

//url du serveur
var url = \"adresse de la page\";
//gestion de la reponse du serveur
maRequete.onreadystatechange = function(){
if(maRequete.readyState == 4){
//affiche la réponse du serveur
alert(maRequete.responseText);
}
}

    //Choisir le type de requete
maRequete.open(\"POST\", url, true);
    //Entête de la requete pour la méthode POST
maRequete.setRequestHeader(\"Content-Type\", \"application/x-www-form-urlencoded\");
   //envoyer la requete au serveur
maRequete.send(data);

</script>

Faire valider votre travail par le professeur. 

 

","title":"La requête Post"},{"edit":"

Commentez ici.

"},{"htm":"","css":"","js":""}],[{"text":"


Donner une définition du JSON.

Le serveur ci-dessous envoie les datas au format JSON.

http://sciencesappliquees.com/templates/php/json.php

Elles sont sous la forme suivante :

{
  \"temp\":19.07,
  \"humi\":27,
  \"led1\":\"OFF\"
}

Réaliser une page html qui affiche les 3 grandeurs dans 3 div toutes les secondes.

Aide :

  • Pour convertir la \"responseText\" en JSON, il faut utiliser l'instruction suivante : 
var data = JSON.parse(maRequete.responseText);
  • Pour récupérer la valeur d'une grandeur d'un JSON, par exemple \"temp\", il faut utiliser : data.temp  

Faire valider votre travail par le professeur. 

 

","title":"Les datas au format JSON"},{"edit":"

Commentez ici.

"},{"htm":"","css":"","js":""}],[{"text":"

Revenons sur l'adresse qui s'affiche dans la barre d'adresse d'un navigateur web et plus précisément sur le début de cette adresse c'est-à-dire le \"http\"

Selon les cas cette adresse commencera par http ou https (nous verrons ce deuxième cas à la fin de cette activité).

Le protocole (un protocole est ensemble de règles qui permettent à 2 ordinateurs de communiquer ensemble) HTTP (HyperText Transfert Protocol) va permettre au client d'effectuer des requêtes à destination d'un serveur web. En retour, le serveur web va envoyer une réponse.

Voici une version simplifiée de la composition d'une requête HTTP (client vers serveur) :

  • la méthode employée pour effectuer la requête
  • l'URL de la ressource
  • la version du protocole utilisé par le client (souvent HTTP 1.1)
  • le navigateur employé (Firefox, Chrome) et sa version
  • le type du document demandé (par exemple HTML)
  • ...

Certaines de ces lignes sont optionnelles.

","title":"Http"}],[{"text":"

Voici un exemple de requête HTTP :

\nGET /mondossier/monFichier.html HTTP/1.1\nUser-Agent : Mozilla/5.0\nAccept : text/html\n\t\t\t

Nous avons ici plusieurs informations :

  • \"GET\" est la méthode employée (voir ci-dessous)
  • \"/mondossier/monFichier.html\" correspond l'URL de la ressource demandée
  • \"HTTP/1.1\" : la version du protocole est la 1.1
  • \"Mozilla/5.0\" : le navigateur web employé est Firefox de la société Mozilla
  • \"text/html\" : le client s'attend à recevoir du HTML

Revenons sur la méthode employée :

Une requête HTTP  utilise une méthode (c'est une commande qui demande au serveur d'effectuer une certaine action). Voici la liste des méthodes disponibles :

GET, HEAD, POST, OPTIONS, CONNECT, TRACE, PUT, PATCH, DELETE

Détaillons 4 de ces méthodes :

  • GET : C'est la méthode la plus courante pour demander une ressource. Elle est sans effet sur la ressource.
  • POST : Cette méthode est utilisée pour soumettre des données en vue d'un traitement (côté serveur). Typiquement c'est la méthode employée lorsque l'on envoie au serveur les données issues d'un formulaire.
  • DELETE : Cette méthode permet de supprimer une ressource sur le serveur.
  • PUT : Cette méthode permet de modifier une ressource sur le serveur
"}],[{"text":"


Une fois la requête reçue, le serveur va renvoyer une réponse, voici un exemple de réponse du serveur :

\nHTTP/1.1 200 OK\nDate: Thu, 15 feb 2019 12:02:32 GMT\nServer: Apache/2.0.54 (Debian GNU/Linux) DAV/2 SVN/1.1.4\nConnection: close\nTransfer-Encoding: chunked\nContent-Type: text/html; charset=ISO-8859-1\n<!doctype html>\n<html lang=\"fr\">\n<head>\n<meta charset=\"utf-8\">\n<title>Voici mon site</title>\n</head>\n<body>\n <h1>Hello World! Ceci est un titre</h1>\n<p>Ceci est un <strong>paragraphe</strong>. Avez-vous bien compris ?</p>\n</body>\n</html>\n\t\t\t

Nous n'allons pas détailler cette réponse, voici quelques explications sur les éléments qui nous seront indispensables par la suite :

Commençons par la fin : le serveur renvoie du code HTML, une fois ce code reçu par le client, il est interprété par le navigateur qui affiche le résultat à l'écran. Cette partie correspond au corps de la réponse.

La 1re ligne se nomme la ligne de statut :

  • HTTP/1.1 : version de HTTP utilisé par le serveur
  • 200 : code indiquant que le document recherché par le client a bien été trouvé par le serveur. Il existe d'autres codes dont un que vous connaissez peut-être déjà : le code 404 (qui signifie  «Le document recherché n'a pu être trouvé»).

Les 5 lignes suivantes constituent l'en-tête de la réponse, une ligne nous intéresse plus particulièrement :

\nServer: Apache/2.0.54 (Debian GNU/Linux) DAV/2 SVN/1.1.4\n\t\t\t

Le serveur web qui a fourni la réponse http ci-dessus a comme système d'exploitation une distribution GNU/Linux nommée \"Debian\" (pour en savoir plus sur GNU/Linux, n'hésitez pas à faire vos propres recherches). \"Apache\" est le coeur du serveur web puisque c'est ce logiciel qui va gérer les requêtes http (recevoir les requêtes http en provenance des clients et renvoyer les réponses http). Il existe d'autres logiciels capables de gérer les requêtes http (nginx, lighttpd...) mais, aux dernières nouvelles, Apache est toujours le plus populaire puisqu'il est installé sur environ la moitié des serveurs web mondiaux !

","title":"Réponse du serveur à une requête HTTP"}],[{"text":"

Le \"HTTPS\" est la version \"sécurisée\" du protocole HTTP. Par \"sécurisé\" en entend que les données sont chiffrées avant d'être transmises sur le réseau.

Voici les différentes étapes d'une communication client - serveur utilisant le protocole HTTPS :

  • le client demande au serveur une connexion sécurisée (en utilisant \"https\" à la place de \"http\" dans la barre d'adresse du navigateur web)
  • le serveur répond au client qu'il est OK pour l'établissement d'une connexion sécurisée. Afin de prouver au client qu'il est bien celui qu'il prétend être, le serveur fournit au client un certificat prouvant son \"identité\". En effet, il existe des attaques dites \"man in the middle\", où un serveur \"pirate\" essaye de se faire passer, par exemple, pour le serveur d'une banque : le client, pensant être en communication avec le serveur de sa banque, va saisir son identifiant et son mot de passe, identifiant et mot de passe qui seront récupérés par le serveur pirate. Afin d'éviter ce genre d'attaque, des organismes délivrent donc des certificats prouvant l'identité des sites qui proposent des connexions \"https\".
  • à partir de ce moment-là, les échanges entre le client et le serveur seront chiffrés grâce à un système de \"clé publique - clé privée\" (nous n'aborderons pas ici le principe du chiffrement par \"clé publique - clé privée\"). Même si un pirate arrivait à intercepter les données circulant entre le client et le serveur, ces dernières ne lui seraient d'aucune utilité, car totalement incompréhensible à cause du chiffrement (seuls le client et le serveur sont aptes à déchiffrer ces données)

D'un point vu strictement pratique il est nécessaire de bien vérifier que le protocole est bien utilisé (l'adresse commence par \"https\") avant de transmettre des données sensibles (coordonnées bancaires...). Si ce n'est pas le cas, passez votre chemin, car toute personne qui interceptera les paquets de données sera en mesure de lire vos données sensibles.

","title":"HTTPS"}],[{"text":"Sources : 

"}]]
[[{"title":"SQL - Systèmes de Gestion de Bases de Données","posi":0,"tagtitle":"h1"},{"text":"
Après l’étape de modélisation des données, utilisant le modèle relationnel, vient l'étape de la mise en pratique. 

Le système d'information repose sur un programme essentiel, le système de gestion de buses de données relationnel. 
Ce dernier est un logiciel permettant :
  - de créer des bases de données, c’est-à-dire des ensembles de tables ;
  - de créer des tables en spécifiant leurs schémas ;
  - de spécifier des contraintes d'intégrité, telles que les clés primaires et étrangères ou encore des contraintes de domaine ou des contraintes utilisateur ;
  - d'ajouter des données à des tables, mais uniquement si ces entités
respectent les contraintes ;
  - de mettre à jour ou de supprimer des données dans des tables et de supprimer des tables ;
  - d'interroger les données grâce à des programmes écrits dans un langage de requêtes ;
  - d'assurer la sûreté des données, par exemple en garantissant que même en cas de problème matériel (coupure de courant, défaut sur un disque les données sont récupérables.

De plus, le SGBD devant permettre des accès simultanés aux données de la part de plusieurs utilisateurs, il est souvent architecturé sur un modèle client-serveur. 

Le serveur est le programme qui à effectivement accès aux données et les clients sont des programmes émettant des ordres (requête, mise à jour, etc.) et affichant les résultats de ces derniers. 

Dans ce contexte multi-utilisateur, le SGBD permet de plus de définir des droits d'accès différents aux données selon les utilisateurs. 

Ainsi, un SBGD possède des utilisateurs munis d’identifiants et de mots de passes (comme un système d’exploitation).

Les utilisateurs ont des droits différents (consultation simple de tables, mise
à jour de leurs tables ou droits d'administration permettant de configurer
le SGBD).

Un aspect fondamental des SGBD modernes et du langage SQL est que le programmeur de bases de données ne spécifie jamais comment récupérer les données. Il ne programme aucun algorithme, ne spécifie jamais de structure de données. 

Certaines structures de données fixées sont connues
des SGBD : arbres, table de hachage. 
Le programmeur avancé peut guider le SGBD dans le choix initial de représentation, mais il est la plupart du
temps fait automatiquement. 

Au moment d'écrire sa requête, le programmeur n'indiquera jamais qu’il souhaite utiliser un tri fusion par exemple, mais simplement qu'il souhaite obtenir les données dans un certain ordre.

Le système fera alors le meilleur choix possible d'algorithme en fonction des informations à sa disposition (statistiques sur les données des tables, tailles de ces dernières, caractéristiques du système d’exploitation et du matériel sur lequel il s'exécute).

Dans ce contexte, SQL est parfois qualifié de langage déclaratif, c'est-à-dire un langage dans lequel on indique (on « déclare ») les résultats qu’on souhaite obtenir, pas la manière dont on souhaite les calculer.


"},{"text":""}],[{"text":"
Avant les années 1960, le principal moyen de stockage pour les ordinateurs était la bande magnétique. 

Le traitement de données était donc réalisé en lots (batch en anglais), c'est-à-dire qu'une partie des données était rapatriée depuis la bande magnétique jusqu’en mémoire principale, traitée, puis les résultats affichés ou restockés sur bande. Puis le lot suivant de données était lu, traité et affiché, et ainsi de suite. 

L'arrivée des systèmes à accès direct (comme les disquettes et disques durs) a changé la façon d’accéder aux données et les traitements que l’on pouvait espérer en faire.

En premier lieu, le modèle « hiérarchique » est proposé. Il reproduit, sur disque, les structures de données en mémoire. 

Dans ce modèle, les données sont organisées en structures ou enregistrements (qui associent des clés à des données, comme les dictionnaires de Python). 

Une particularité est que les enregistrements sont liés entre eux au moyen de pointeur, de manière à former
des listes chaînées ou des arbres (d’où le nom de système hiérarchique). 

Les «requêtes» de l’époque sont donc semblables aux algorithmes de recherche dans ces structures de données.

Comme nous l'avons vu, Edgar F. Codd introduit en 1970 le modèle relationnel. Apparaissent à partir de cette époque des SGBD relationnels, comme System 
R d'IBM, le premier à proposer une implémentation du langage SQL. 

System R n'est cependant qu’un projet de recherche utilisé chez quelques industriels comme cas d'étude. Le premier SGBD commercial est Oracle, commercialisé par la société Relational Software en 1979 (devenue
depuis Oracle Corporation). 

Les logiciels propriétaires tels qu'Oracle, mais aussi DB/2 d'IBM ou Sybase (maintenant SAP ASE), sont pendant des années la seule alternative viable pour les entreprises.

Avec le développement du Web au milieu des années 1990, le besoin de solutions logicielles moins onéreuses et plus ouvertes augmente. 

En effet, les SGBD propriétaires étaient non seulement coûteux, mais aussi conçus pour fonctionner sur des serveurs aux architectures spécifiques, hors de portée des particuliers, des associations et des petites entreprises. 

C’est dans ce contexte que naissent des alternatives telles que MySQL (maintenant MariaDB) en
1995 puis PostgreSQL en 1996. Ces dernières sont devenues au cours des 25 dernières années des logiciels robustes, capables de concurrencer dans de
nombreux cas les alternatives propriétaires.

En parallèle de l'évolution des systèmes, le langage SQL a lui aussi évolué. Cette évolution s'est faite de manière anarchique, de nombreux éditeurs de logiciels rajoutant leur propres extensions non standardisées. 

Ce phénomène d’«enfermement» (vendor lock-in en anglais) est toujours d’actualité et rend difficile la présentation du langage SQL. Certaines opérations basiques doivent êtres déclinées selon tous les dialectes de SQL utilisés par les différents systèmes.

Une des raisons est le peu d'intérêt qu'ont les éditeurs
de systèmes commerciaux à faciliter la migration de leurs clients chez des systèmes concurrents.

","title":"Historique"},{"edit":"

Mettre ici les résultats.

"}],[{"text":"
Comme expliqué aux séquences précédentes, une action du monde réel (on parle parfois de processus métier) peut être modélisée par des ordres SQL donnés à un SGBD. 

Si Alice (dont la carte a le code barre '19833284474405') emprunte le livre Ravage (dont l'ISBN est '978-2072534911') le 1er février 2020, la borne d'emprunt (qui exécute un programme graphique permettant de scanner les cartes et livres) eflectuera
l’ordre SQL suivant :

INSERT INTO emprunt VALUES
('19833284474405', '978-2072534911', '2020-02-15') ;

On voit ici que l’action d'emprunter se traduit par un seul ordre SQL. 
Nous avons déjà vu qu'il est inutile de vérifier avant l'emprunt que le livre a effectivement été rendu (et pas juste redéposé en rayon sans passer par la borne). 

En effet, si l'ISBN du livre est toujours dans la table emprunt, alors la contrainte d’intégrité faisant de l’attribut isbn une clé primaire sera violée et le SGBD renverra une erreur. 

Le programme s’exécutant sur la borne pourra alors afficher un message d'erreur à l'usager.


","title":"Transactions"},{"edit":"

Mettre le résultat ici.

"}],[{"text":"
Considérons maintenant une action plus complexe, consistant à sortir un livre de l'inventaire, par exemple s'il est en trop mauvais état pour être emprunté. 
Ce processus d'apparence simple cache de nombreuses subtilités. 
En effet, retirer une entrée de la table livre viole la contrainte de clé étrangère sur l’attribut isbn dans la table auteur_de. 

Il faut donc d’abord retirer les lignes correspondantes dans cette table. Il peut y en avoir plusieurs si un livre à plusieurs auteurs. De plus, il peut être souhaitable, si
on à supprimé le dernier livre d’un auteur, de supprimer aussi cet auteur de la base. 
Ce processus peut s'exprimer par plusieurs ordres SQL. 
Supposons que l’on veuille supprimer le livre Les Aventures de Huckieberry Finn
d'ISBN ’978-2081509511?.


DELETE FROM auteur_de WHERE isbn = '7978-2081509511';

DELETE FROM auteur
WHERE NOT (a_id IN (SELECT a_id FROM auteur_de));

DELETE FROM livre WHERE isbn = '978-2081509511' ;


Le premier ordre supprime la référence au livre dans la table auteur_de. 
Le deuxième ordre supprime de la table auteur tous les auteurs dont l’identifant (attribut a_id) n'apparaît pas dans la table auteur_de grâce à une requête imbriquée dans la clause WHERE. 
Enfin, le livre est supprimé de la table livre par le troisième ordre.

Ces trois ordres forment un tout qu’on ne doit pas dissocier. En effet, considérons maintenant la situation suivante : 
      un usager a reposé le livre en rayon sans passer par une borne pour le rendre. Il reste donc dans la table
emprunt une référence vers l’ISBN de ce livre  (contrainte de clé étrangère) et le dernier ordre et seulement celui-ci va échouer. 


","title":""},{"edit":"

Mettre le résultat ici (code et figure).

"}],[{"text":"
Ajoutons une telle entrée dans la table emprunt et regardons ce qui se produit :


INSERT INTO emprunt VALUES ('934701281931682','978-2081509511','2020-02-01');

DELETE FROM auteur_de WHERE isbn = '978-2081509511';

DELETE FROM auteur
WHERE NOT (a_id IN (SELECT a_id FROM auteur_de));

DELETE FROM livre WHERE isbn = '978-2081509511';


ERROR: update or delete on table \"livre\" violates foreignDETAIL: Key (isbn)=(978-2081509511) is still referenced
from table \"emprunt\"

SELECT * FROM auteur WHERE nom = 'Twain';

Nos données sont dans un état incohérent, car les deux premiers ordres DELETE sont exécutés sans problème, retirant de la base l’auteur du livre et la relation entre ce dernier et le livre, alors que livre est toujours présent dans la base (la dernière requête SELECT ne renvoie aucun résultat). On souhaite donc que, si l’un des trois ordres échoue, les trois ordres soient annulés.


","title":""},{"edit":"

Mettre le résultat ici (code et figure).

"}],[{"text":"
Cette notion fondamentale des SGBD s’appelle une transaction. Une transaction est une séquence d'instructions SQL (requêtes, mises à jour) qui
forment un tout et doivent soit toutes réussir, soit toutes être annulées, afin de laisser la base dans un état cohérent. 
Le langage SQL supporte bien évidemment les transactions. Pour déclarer qu’une suite d'ordres est une transaction, il suffit de la faire précéder de START TRANSACTION. On pourra alors la conclure par  l'instruction COMMIT afin de valider la transaction. 

L'instruction ROLLBACK permet de manuellement annuler la transaction. Il est à noter que si une erreur se produit lors d’une transaction, alors toutes les tables
sont remises dans leur état d'avant la transaction au moment du COMMIT ou du ROLLBACK (qui ont alors le même effet).


INSERT INTO emprunt VALUES ('934701281931582', '978-2081509511', '2020-02-01');

START TRANSACTION;

DELETE FROM auteur_de WHERE isbn = '978-2081509511';

DELETE FROM auteur
WHERE NOT (a_id IN (SELECT a_id FROM auteur_de));

DELETE FROM livre WHERE isbn = '978-2081509511';
COMMIT;


ERROR: update or delete on table “Livre” violates foreign
key constraint \"emprunt_isbn_fkey\" on table \"emprunt\"

DETAIL: Key (isbn)=(978-2081509511) is still referenced
from table \"emprunt\"

SELECT * FROM auteur WHERE nom = ’Twain”’;

ERROR: current transaction is aborted, commands ignored
until end of transaction block

ROLLBACK;

SELECT * FROM auteur WHERE nom = ‘Twain’;0 Twain | Mark

Comme on le voit, à l'issue de la transaction, c’est-à-dire après l'exécution de l’ordre ROLLBACK, la table auteur à été restaurée dans son état d'avant la
transaction. 


","title":""},{"edit":"

Mettre le résultat ici (code et figure).

"}],[{"text":"

On peut noter qu'une syntaxe populaire, ne faisant pas partie du standard, mais supportée par tous les SGBD modernes, est celle utilisant le mot clé BEGIN pour START TRANSACTION et END pour ROLLBACK/COMMIT :


BEGIN;

DELETE FROM auteur_de WHERE isbn = '978-2081509511';
DELETE FROM auteur
WHERE NOT (a_id IN (SELECT a_id FROM auteur_de));

DELETE FROM livre WHERE isbn = '978-2081509511';
END;


","title":""},{"edit":"

Mettre le résultat ici (code et figure).

"}],[{"text":"
Mettons en œuvre une transaction plus complexe maintenant, permettant d'ajouter l'auteur Mark Twain s’il n’est pas déjà dans la table auteur !.


START TRANSACTION;
SELECT * INTO mark_present
FROM auteur
WHERE nom = 'Twain' AND prenom = 'Mark';

SELECT MAX(a_id) AS m INTO max_a_id
FROM auteur
WHERE (SELECT COUNT(*) FROM mark_present) = 0;

INSERT INTO auteur
(SELECT m+1, 'Twain', 'Mark'
FROM max_a_id WHERE m IS NOT NULL);

DROP TABLE mark_present;
DROP TABLE max_a_id;
COMMIT ;


La première requête sélectionne toutes les lignes de la table auteur pour lesquelles le nom et le prénom sont ceux de Mark Twain et sauve ce résultat dans la table mark_present. 
Si Mark Twain est bien présent, alors (au moins) une ligne sera copiée dans cette table. 
Si Mark Twain n’est pas présent, alors la table mark_present sera vide.

La deuxième requête est plus subtile. Elle sélectionne les plus grands a_id de la table auteur pour lesquels la table temporaire mark_present est vide (son « COUNT » vaut 0). On peut remarquer que cette condition est indépendante de la ligne que l’on considère. 
Ainsi, si la table mark_present est vide, alors la condition est toujours vraie. 
La requête va donc renvoyer le maximum de fois les a_id de la table, car toutes les lignes sont sélectionnées. 

À l'inverse, si mark_present est non vide, alors la condition est toujours fausse et aucun a_id n’est sélectionné. Dans ce cas, la fonction 
d’agrégation renvoie la valeur spéciale NULL. 

Pour résumer, les deux premiers ordres SELECT ensemble ont pour effet de mettre dans une colonne m
d’une table temporaire max_a_id le plus grand identifiant présent dans la table auteur si Mark Twain en est absent et NULL s’il est présent.

Le dernier ordre utilise enfin un « INSERT avec SELECT ». Le SELECT imbriqué renvoie le triplet (m+1, ‘Twain’, Mark’) si la colonne m de la table max_a_id est non NULL. Comme dans ce cas-ci m contient le plus grand
a_id de la table auteur, m+1 est un nouvel identifiant et est donc bien une clé primaire valide. 
Si m est NULL, aucune insertion n'est faite (car Mark
Twain est déjà présent).

Les deux derniers ordres DROP détruisent les tables temporaires créées dans cette transaction. 

Notons que si un problème survient durant la transaction, l'ordre ROLLBACK aura aussi pour effet de supprimer les tables temporaires créées pendant la transaction.


","title":""},{"edit":"

Mettre le résultat ici (code et figure).

"}],[{"text":"
Les propriétés ACID sont quatre garanties offertes par les SGBD relationnels concernant les transactions. 

L'acronyme ACID est constitué des initiales des quatre propriétés : Atomicité, Isolation, Cohérence, Durabilité.

Atomicité : Par ce terme, on désigne le fait qu’une transaction est «tout ou rien». 
Soit la transaction est arrivée à son terme, et les données sont alors modifiées, soit elle a échoué, et toutes les modifications sont annulées pour restaurer la base de données dans l’état où elle était avant la transaction.

Cohérence : Les transactions doivent faire passer la base d’un état cohérent à un autre état cohérent. 
À l'issue d’une transaction, en particulier, toutes les contraintes d'intégrité doivent être vérifiées.

Isolation : Si deux transactions s’exécutent simultanément, alors leur exécution doit produire le même effet que si on les avait exécutées l’une
après l'autre (une transaction ne peut en particulier pas observer un état intermédiaire où certaines modifications n’ont pas été validées par un COMMIT).

Durabilité : Une transaction validée par un COMMIT est valide « pour de bon ». 
Le système s’assure donc que, quels que soient les problèmes logiciels ou matériels qui pourraient survenir (défaillance de disque dur, panne de courant, etc.), les mises à jour d’une transaction validée ne sont jamais perdu.


","title":"Propriétés ACID"},{"edit":"


"}],[{"text":"
Nous illustrons la propriété d'isolation avec l'exemple suivant. Supposons que l’on tente d'exécuter de manière simultanée deux copies de la transaction
«ajout de Mark Twain si absent» décrite plus haut. 

Une manière simple de procéder consiste à ouvrir deux connexions à la base de données et de rentrer les deux séries d’ordres dans chacune de ces connexions.



START TRANSACTION;
  SELECT * INTO mark_present
  FROM auteur 
  WHERE nom = 'Twain' 
    AND prenom = 'Mark’; 

  SELECT MAX(a.id) AS m 
  INTO max_a_id 
  FROM auteur 
  WHERE (SELECT COUNT (*) 
    FROM mark_present) = 0; 

  INSERT INTO auteur (SELECT m+1, 'Twain', 'Mark' 
  FROM max_a_id
  WHERE m IS NOT NULL);

  DROP TABLE mark_present; 
  
  DROP TABLE max_a_id; 

COMMIT ; 

  
START TRANSACTION;
  SELECT * INTO mark_present
  FROM auteur 
  WHERE nom = 'Twain' 
    AND prenom = 'Mark’; 

  SELECT MAX(a.id) AS m 
  INTO max_a_id 
  FROM auteur 
  WHERE (SELECT COUNT (*) 
    FROM mark_present) = 0; 

  INSERT INTO auteur (SELECT m+1, 'Twain', 'Mark' 
  FROM max_a_id
  WHERE m IS NOT NULL);

  DROP TABLE mark_present; 
  
  DROP TABLE max_a_id; 

COMMIT 
Supposons que ces deux transactions soient envoyées au même moment au SGBD (par exemple parce que deux documentalistes souhaitent ajouter Mark Twain). Si ces deux transactions sont exécutées l’une après l'autre :

  - la première ajoute Mark Twain dans la base;
  - la seconde, trouvant Mark Twain dans la base, ne fait rien.

Si ces deux transactions étaient exécutées en parallèle de façon naïve, leurs ordres pourraient s’entremêler de la façon suivante :

 - la transaction de gauche recherche Mark Twain et ne le trouve pas;
  --la transaction de droite recherche Mark Twain et ne le trouve pas non plus ;
  - la transaction de gauche détermine un certain identifiant et ajoute Mark Twain ;
  - la transaction de gauche est validée par son COMMIT;
  - la transaction de droite détermine le même identifiant (car elle travaille sur la version de la table telle qu’elle était en début de transaction) et tente d'ajouter Mark Twain, mais viole alors la contrainte de clé

Le modèle ACID interdit un tel comportement, car le résultat de l'exécution séquentielle {tout se passe bien car la deuxième transaction ne fait rien) est différent de l'exécution en parallèle des deux transactions. 

Un système dans lequel cela serait possible ne posséderait pas la propriété d'isolation. 
En pratique, les SGBD modernes évitent cette situation en bloquant la deuxième transaction dès qu'elle accède à une table en cours d'utilisation par une autre transaction. 

Dans notre scénario, la transaction de droite serait «bloquée» sur son premier SELECT (qui détermine si Mark Twain est présent), tant que la transaction de gauche n’a pas exécuté son COMMIT. Elle sera alors
débloquée et ne fera rien, car le SELECT trouvera Mark Twain dans la table.

","title":""},{"edit":"

Mettre le résultat ici (code et figure).

"}],[{"text":"
Nous terminons ce tour d'horizon des SGBDSs par une courte introduction à l’utilisation d’un SGBD depuis un langage de programmation. 

Nous utilisons Python, mais les concepts présentés ici sont facilement transposables dans d’autres langages (tels que PHP pour la création d’un site web
riche). 

L'une des difficultés d'une telle présentation repose sur le fait que, pour chaque SGBD existant, certaines lignes spécifiques propres à ce SGBD sont nécessaires. 

Ainsi, ces lignes seront différentes selon que l’on se connecte à PostgreSQL, MariaDB ou encore Oracle.

Un programme (simple) interagissant avec un SGBD effectue généralement les actions suivantes :

1. Connexion au SGBD. C’est lors de cette phase que l’on spécifie où se trouve le SGBD (par exemple en donnant son adresse IP), le nom d'utilisateur et le mot de passe, ainsi que d’autres paramètres système.

2. Envoi d'ordres au SGDB. On crée (le plus souvent dans des chaînes de caractères) des ordres SQL.

3. On récupère les données correspondant aux résultats dans des structures de données du langage (par exemple dans des tableaux Python).

4. On peut ensuite exécuter du code Python sur les données récupérées.


","title":"interaction entre un SGBD et un programme"},{"edit":"

Mettre le résultat ici (code et figure).

"}],[{"text":"
Le programme ci-dessus importe en premier lieu le module mysql.connector, qui permet de se connecter au SGBD MariaDB (mysql). Si l’on souhaite se connecter à un autre SGBD), il faudra changer cette ligne pour charger le bon module. 

Attention, si le module mysql n'est pas présent sur votre ordinateur. Il faut se rendre dans le programme Python avec le terminale de commande (cmd) et exécuter la commande ci-dessous:
C:\\Users\\Your Name\\AppData\\Local\\Programs\\Python\\Python36-32\\Scripts>python -m pip install mysql-connector-python
En cas de problème d'installation de mysql.connector, il faut prevenir le professeu.

Un aspect important du langage Python est que ces concepteurs ont défini une interface unifiée d'accès aux bases de données. 
Ainsi, même si les SGBD visés sont différents, les méthodes Python utilisées seront toujours les mêmes, ce qui rend le code facilement portable d'un SGBD à un autre. 


Programme — SELECT depuis Python

import mysql.connector as sgbd

#Entrer l'adresse IP du serveur ou le nom de domaine
HOST = \"217.182.207.90\" # ou \"domaine.com\"
#Le nom de la base de données
DATABASE = \"DBuser?\" #changer le ? par le numero donnée par le professeur
#Le nom de l'utilisateur de la DB
USER = \"user?\"
# Le mot de passe de l'utilisateur
PASSWORD = \"mot de passe de la base\"
#connexion à la SGDB
cnx = sgbd.connect(host=HOST, database=DATABASE, user=USER, password=PASSWORD)
print(\"Connecté à:\", cnx.get_server_info())

c = cnx.cursor()

c.execute (\"SELECT * FROM livre WHERE annee < 1990\")

for l in c.fetchall():
print(l[0], l[2])

cnx.close()



Attention, vous devez modifier les paramètres : USER, DATABASE et PASSWORD.

Tester le code et mettre les résultats ci-dessous.

Nous avons choisi d'importer le module mariadb sous le nom générique sgbd ce qui évitera de devoir changer de nom dans la suite du programme si on change
de SGBD.

Le programme établit ensuite une connexion vers le SGBD. Il utilise pour cela la fonction connect du module. Cette dernière prend en argument des paramètres nommés. 
Nous en donnons trois ici : 
  le paramètre host permet de spécifier le nom ou l'adresse du serveur et les paramètres user
et password permettent de donner le nom d'utilisateur et le mot de passe à utiliser pour se connecter au SGBD. 
Le résultat de cet appel est un objet représentant la connexion au serveur (une exception est levée si jamais la connexion échoue). 
L'objet cnx est celui qui est utilisé dans toute la suite
pour communiquer avec le SGBD. 
La première chose à faire est la création
d'un curseur (variable c) au moyen de la méthode .cursor() de l’objet de connexion. 
Un curseur représente essentiellement un ordre SQL. 

Les deux principales méthodes que nous présentons sur les curseurs sont les suivantes :

 - execute(s, p) permet d'exécuter un ordre SQL s, Ce dernier est simplement représenté par une chaîne de caractères Python, pouvant contenir une succession d'ordres séparés par des « ; ». Le paramètre p est
optionnel et est un tableau de valeurs Python dont l’utilisation sera détaillée dans la suite. 
Notons que cette méthode ne renvoie aucun résultat. 
Elle transmet juste l’ordre SQL au SGBD, qui va calculer un résultat.

 - fetchall() renvoie tous les résultats du dernier ordre passé, sous la forme d’un tableau de n-uplets de valeurs Python. Chaque n-uplet représente une ligne de résultat de la requête. 
Les valeurs sont ordonnées comme pour le résultat d’un SELECT. Un appel à fetchall() « réinitialise » le curseur. Si on appelle fetchall() deux fois, le deuxième appel renverra un tableau vide. Il faut ré-exécuter une requête pour obtenir de nouveau un résultat.

Dans le programme ci-dessus, on a donc exécuté une requête renvoyant tous les livres dont l’année est inférieure à 1990. 

Comme on le voit, les valeurs ont été automatiquement traduites : les chaînes de caractères SQL (type VARCHAR) sont représentées par des chaînes
de caractères Python. Les entiers (type INTEGER) sont devenus des entiers Python. 
Le programme parcourt cette liste de n-uplets au moyen d’une boucle for et affiche que le titre et l’année. Pour cela, il accède aux éléments d’indices 0 et 2 de chaque n-uplet. 
Enfin, le programme se termine en fermant la connexion vers le SGBD. La méthode .close() est similaire à celle utilisée sur les descripteurs de fichiers et permet de libérer les ressources associées à la connexion (côté Python et côté SGBD).


","title":""},{"edit":"

Mettre le résultat ici (code et figure).

"}],[{"text":"
Une fonctionnalité importante est la possibilité de pouvoir insérer dans des ordres SQL des valeurs venant du monde Python, par exemple saisies par
l'utilisateur. 
Nous illustrons cela avec le programme ci-dessous. Dans ce dernier, on demande à l'utilisateur de saisir une chaîne de caractères. 
On veut ensuite exécuter la requête SELECT * FROM livre WHERE titre LIKE ’%s%' où s est la chaîne saisie par l'utilisateur. Nous utilisons ici la facilité fournie par la méthode .execute()


Programme — Recherche paramétrée
import mysql.connector as sgbd

#Entrer l'adresse IP du serveur ou le nom de domaine
HOST = \"217.182.207.90\" # ou \"domaine.com\"
#Le nom de la base de données
DATABASE = \"DBuser?\" #changer le ? par le numero donnée par le professeur
#Le nom de l'utilisateur de la DB
USER = \"user?\"
# Le mot de passe de l'utilisateur
PASSWORD = \"mot de passe de la base\"
#connexion à la SGDB
cnx = sgbd.connect(host=HOST, database=DATABASE, user=USER, password=PASSWORD)
print(\"Connecté à:\", cnx.get_server_info())

c = cnx.cursor()

texte = input (\"Texte à rechercher dans le titre :\")

c = cnx.cursor()

motif = '%' + texte + '%';

c.execute(\"SELECT * FROM livre WHERE titre LIKE %s\", \\
[ motif ])

for l in c.fetchall():
print(l[0], l[2])

cnx.close()


Il est possible de laisser dans la requête des «trous» dénotés par les caractères « %s ». Ces trous sont ensuite remplacés par les valeurs se trouvant dans le tableau passé en second paramètre à .execute() (le premier trou est remplacé par la première valeur du tableau et ainsi de suite). 

Ainsi, si l'utilisateur saisit la chaîne Ast, alors la variable
motif contiendra la chaîne '%Ast%’. 

La requête envoyée au SGBD sera alors
la suivante :

SELECT * FROM livre WHERE titre LIKE '%Ast%'

Il serait tentant de créer ia requête directement en Python au moyen de concaténations. On pourrait ainsi écrire directement 

c.execute(\"SELECT * FROM livre WHERE titre LIKE '\" + motif + \"'\")

Cette approche est à proscrire et ne doit en aucun cas être utilisée?. En effet, le code ci-dessus est particulièrement fragile et peut être modifié par un utilisateur mal intentionné. 
Ce dernier pourraît par exemple saisir comme texte :

'; DROP TABLE emprunt; SELECT * FROM livre WHERE titre = '

La requête formée et envoyée au SGBD serait alors :

SELECT * FROM livre WHERE titre LIKE '%';
DROP TABLE emprunt ;
SELECT * FROM livre WHERE titre = '%';

Le SGBD exécutera alors les ordres en séquence et en particulier le deuxième lui indiquant de supprimer la table emprunt. 
Une telle subversion s'appelle une injection de code SQL. De nombreuses failles de sécurité » des sites
web sont en fait basées sur des injections de code SQL. Une telle faille n’est pas présente dans le programme ci-dessus. En effet, ce dernier laisse le soin à la méthode execute d'insérer le texte. Cette dernière va donc correctement échapper la chaîne de caractères et le programme effectuera la requête inoffensive

SELECT * FROM livre WHERE titre LIKE '%';DROP TABLE emprunt;SELECT * FROM livre WHERE titre = '%';

où toute la partie soulignée fait partie de la chaîne de caractères recherchée.
Cette requête essaye de trouver un livre dont le titre est littéralement

'; DROP TABLE emprunt; SELECT * FROM livre WHERE titre = '

","title":"Ordres paramétrés"},{"edit":"

Mettre le résultat ici (code et figure).

"}],[{"text":"
Pour chacun des scénarios suivant dire laquelle des quatre propriétés ACID est mise en jeu.

1. Une transaction tente d'insérer 20 lignes dans une table. L'insertion
de la 19° ligne échoue, à cause d’une contrainte de clé primaire. La
transaction est annulée et ancune des lignes ne se retrouve dans la
table.

2. Une table T2 contient des clés étrangères, référençant les clés d’une
table T,. On exécute une transaction arbitraire qui modifie T2. Après
la transaction 72 contient toujours des clés étrangères.

3. On exécute intégralement une transaction, validée par un « COMMIT ».
La machine exécutant le SGBD subit une panne de courant. Au redé-
marrage, l'effet de la transaction à bien été pris en compte.

4. Sur une table T contenant une colonne n de type INTEGER, on exécute
deux transaction, « en même temps ». La première ajoute 1 à toutes
les cases de la colonne n et la seconde retire 1 à ces même cases. Le
contenu de la table T après exécution (sans erreur) est le même.

Solution page 495 0


","title":"Exercice"},{"edit":"

Mettre le résultat ici (code et figure).

"},{"solution":"
1. Atomicité.
2. Cohérence.
3. Durabilité.
4. Isolation.

"}],[{"text":"
On considère la base de données de la médiathèque. On suppose qu'un utilisateur à perdu sa carte, dont le code barre est '11111111111111'. Un employé lui crée une nouvelle carte, dont le code barre est '222222222222222'. 
Donner une transaction permettant de réaliser le processus de « remplacement de carte ».



","title":"Exercice"},{"edit":"

Mettre le résultat ici (code et figure).

"},{"solution":"
On doit modifier deux tables au sein de la même
transaction. Attention, on ne peut pas brutalement mettre à jour la table emprunt pour changer le code barre, ni la table usager, car il y a une contrainte de clé étrangère sur le code_barre. On procède donc de la façon suivante :


START TRANSACTION;
SELECT * INTO tmp FROM emprunt
WHERE code_barre = '111111111111111';

DELETE FROM emprunt WHERE code_barre = '111111111111111';

UPDATE usager SET code_barre = '222222222222222'
WHERE code_barre = '111111111111111';

INSERT INTO emprunt
(SELECT '222222222222222', isbn, retour FROM tmp);

DROP TABLE tmp;

COMMIT;


Le premier ordre sauvegarde dans une table temporaire tous les emprunts.

Ensuite, on modifie la table usager. Comme il n’y a plus d'emprunt correspondant à cet usager,la mise à jour ne viole pas de contrainte. 
On peut ensuite réinsérer les lignes sauvegardées en utilisant la valeur fixe '222222222222222'. On n'oublie pas de détruire la table temporaire en fin de transaction.

"}],[{"text":"
Sur un site web de réservation de billets de trains, un usager peut consulter la liste des billets qui répondent à certains critères (destination, date, prix, etc.). 

Lorsqu'il trouve un billet à sa convenance, il peut le
sélectionner puis l’acheter.

On suppose que la base de données du site stocke tous les billets disponibles dans une unique table billet_a_vendre  où les billets possèdent
un attribut « id INTEGER PRIMARY KEY » et d’autres attributs que l’on ne précise pas. 
Les billets vendus sont stockés dans une table « billet_vendu », ayant le même schéma que «billet_a_vendre». 
On suppose enfin que la recherche se fait par un simple

SELECT id FROM BILLET_A_ VENDRE WHERE ...;

où les critères sont ceux cochés sur le site.

1. Étant donné un identifiant  de billet, donner le code SQL de la transaction.

2 Expliquer pourquoi il est possible que quelqu'un trouve un billet à sa convenance, mais qu’au moment de l'achat le billet ne soit plus disponible.

3. Pour « corriger » le problème précédant, on décide de mettre la recherche et l'achat dans la même transaction. Quel nouveau problème (bien plus grave) est causé par cette approche ?

Solution page 496 D


","title":"Exercice"},{"edit":"

Mettre le résultat ici (code et figure).

"},{"solution":"
1. Voici la transaction :

START TRANSACTION;
INSERT INTO billet_vendu
(SELECT *
FROM billet_a_vendre
WHERE id = 1);

DELETE FROM billet_a_vendre WHERE id = i;
COMMIT ;


2. Le « SELECT ... » permettant de rechercher un billet peut s'exécuter en parallèle avec un achat. Supposons qu’il reste un billet disponible et deux acheteurs. Le premier acheteur trouve ce billet avec un « SELECT ». Le second acheteur trouve aussi ce billet. Les deux entament une transaction d'achat (celle trouvée à la question 1). Si la transaction réussit pour le premier acheteur, alors elle va échouer pour le second acheteur (le « SELECT » imbriqué ne va rien renvoyer).

3. Si on met tout le processus de recherche et d'achat dans une même transaction, alors cela veut dire que deux utilisateurs ne peuvent pas chercher en même temps, car le SGBD va bloquer toutes les transactions, sauf une, pour garantir la propriété d'isolation.

"}],[{"text":"
Considérons une table :


CREATE TABLE T (id INTEGER PRIMARY KEY, jour DATE, heure TIME, tmp DECIMAL(5,2));


Cette table permet d'enregistrer des relevés de température faits par une sonde. Chaque relevé possède un identifiant unique, le jour du relevé, l'heure
du relevé et la température relevée. 

Supposons données trois valeurs j (un
jour),h (une heure) et t une température. 

Écrire une transaction qui ajoute la nouvelle entrée en choisissant automatiquement un nouvel identifiant. 

On pourra, dans un premier temps, considérer qu’il y a des données dans la table T, puis complexifier la transaction pour gérer le cas de la table vide.

","title":"Exercice"},{"edit":"

Mettre le résultat ici (code et figure).

"},{"solution":"

START TRANSACTION;
CREATE TABLE id_max_tmp (id INTEGER) ;

INSERT INTO id_max_tmp VALUES (-1);
INSERT INTO id_max_ tmp (SELECT MAX(id) FROM T);
INSERT INTO T (SELECT 1+MAX(id), j, h, t
FROM id_max_tmp
WHERE NOT (id IS NULL));
DROP TABLE id_max_tmp;

COMMIT;


La transaction crée une table temporaire id_max_tmp. On y insère une valeur par défaut valant -1. On y insère ensuite le plus grand identifiant trouvé dans la table T. Si la table T est vide, cette requête insère NULL dans la table id_max_tmp. Si la table est non vide, elle insère le plus grand identifiant. table id_max_tmp et on lui ajoute 1. 
On l'utilise comme valeur d'insertion avec les constantes j, h et t. 
On détruit ensuite la table temporaire.

"}],[{"text":"
Considérons la table T des relevés de température de l’exercice précédent. On considère deux ordres exécutés en parallèle :


SELECT MIN(jour) FROM T WHERE tmp >= 40;

qui renvoie le jour la plus ancien pour lequel la température a dépassé 40°.


UPDATE T SET tmp = tmp * 1.8 + 32;

qui convertit toutes les températures en degrés Farenheit.

Est-ce que la propriété ACID d'isolation garantit que la requête  SELECT MIN... , renvoie toujours le même résultat quel que soit l’ordre d'exécution
des deux requêtes ? 

","title":"Exercice"},{"edit":"

Mettre le résultat ici (code et figure).

"},{"solution":"
Exercice 164, page 343 Non, la propriété d'isolation n'offre pas cette ga-
rantie. Elle permet juste de s’assurer que la requête « SELECT MIN... »
donnera un résultat qui correspond soit à une exécution où elle précède en-
tièrement la mise à jour, soit à une exécution où elle suit entièrement la mise
à jour. En d’autres termes, la requête ne peut pas observer une table T où
seulement une partie des lignes ont été mises à jour.

"}],[{"text":"
En s'inspirant du programme python de connexion à une SGBD, écrire un programme Python qui sauvegarde l’intégralité de la table usager dans un fichier CSV nommé usager.csv. 

On pourra utiliser le module Python csv 
","title":"Exercice"},{"edit":"

Mettre le résultat ici (code et figure).

"},{"solution":"

import csv
import mysql.connector as sgbd

#Entrer l'adresse IP du serveur ou le nom de domaine
HOST = \"217.182.207.90\" # ou \"domaine.com\"
#Le nom de la base de données
DATABASE = \"DBuser?\" #changer le ? par le numero donnée par le professeur
#Le nom de l'utilisateur de la DB
USER = \"user?\"
# Le mot de passe de l'utilisateur
PASSWORD = \"mot de passe de la base\"
#connexion à la SGDB
cnx = sgbd.connect(host=HOST, database=DATABASE, user=USER, password=PASSWORD)
print(\"Connecté à:\", cnx.get_server_info())

with open(\"usager.csv\", \"w\") as fichier:
csvf = csv.writer(fichier)
#on écrit l'en-tête
csvf.writerow([\"nom\", \"prenom\", “adresse\" ,\\
“cp\", \"ville\", \"email\", \"code _barre\"])
#on se connecte à la base
c = cnx.cursor()
#on exécute la requête renvoyant tous les livres
c.execute(\"SELECT * FROM livre\")
#on écrit chaque ligne dans Le fichier
for l in c.fetchall(0):
csvf.writerow(l)
cnx.close()


"}],[{"text":"
En s'inspirant du programme python sur les SGBD, écrire un programme Python qui demande à l'utilisateur de saisir deux années, recherche tous les livres publiés entre ces deux années et crée un fichier HTML contenant une table présentant les résultats 
","title":"Exercice"},{"edit":"

Mettre le résultat ici (code et figure).

"},{"solution":"

import mysql.connector as sgbd

#Entrer l'adresse IP du serveur ou le nom de domaine
HOST = \"217.182.207.90\" # ou \"domaine.com\"
#Le nom de la base de données
DATABASE = \"DBuser?\" #changer le ? par le numero donnée par le professeur
#Le nom de l'utilisateur de la DB
USER = \"user?\"
# Le mot de passe de l'utilisateur
PASSWORD = \"mot de passe de la base\"
#connexion à la SGDB
cnx = sgbd.connect(host=HOST, database=DATABASE, user=USER, password=PASSWORD)
print(\"Connecté à:\", cnx.get_server_info())


a1 = int(input(\"Saisir la première année : \"))
a2 = int(input(\"Saisir la deuxième année : \"))
with open(\"res.html\", \"w\") as fichier:
fichier.write(\"\"\"</DOCTYPE html>
<html>
<head><title></title></head>
<body><table>\"\"\")
c = cnx.cursor()
#on exécute la requête renvoyant tous les livres
c.execute(\"\"\"SELECT * FROM livre
WHERE annee >= %s AND annee <= %s\"\"\", \\
[a1, a2])
for lig in in c.fetchall():
fichier.write(\"<tr>\")
for col in lig:
fichier.write(\"<td>\")
fichier.write(str(col)
fichier.write(\"</td>\")
fichier.write(\"</tr>\\n\")
fichier.write(\"</table></body></html>\")
cnx.close()


"}]]
[[{"visi":false,"text":"Vous allez répondre à un QCM sur le web du programme de Snt.

Consignes : 
  - 1 seul onglet ouvert sur sciencesappliquees.com dans le navigateur chrome;
  - Téléphone portable ramasser dans le sac.
  - Aucun autre logiciel doit être exécuté pendant le test.
Si vous enfreignez une de ces consignes, vous aurez 0 avec 2 heures de colles pour tentative de triche!
","posi":1}],[{"text":"
Sur un Arduino, les informations entrent et sortent par des …
"},{"radio":[{"label":"
liens
","sol":false},{"label":"
portes
","sol":false},{"label":"
 fils
","sol":false},{"label":"
ports
","sol":true}]}],[{"text":"
Que signifie le sigle GND sur les platines Arduino ?
"},{"radio":[{"label":"
Port digital (Gate Numerical Dot)
","sol":false},{"label":"
Non utilisé (Get No Data)
","sol":false},{"label":"
LED verte (GreeN Diode)
","sol":false},{"label":"
Masse électrique (GrouND)
","sol":true}]}],[{"text":"
Que signifie l’acronyme IDE (EDI en Français) ?
"},{"radio":[{"label":"
Étude et Développement d'Interface
","sol":false},{"label":"
Environnement Durable Informatique
","sol":false},{"label":"
Environnement de Développement Intégré
","sol":true},{"label":"
Espace de Données Interactif
","sol":false}]}],[{"text":"
Quel nom porte la fonction qui n’est exécutée qu’à la mise sous tension de l’Arduino ?
"},{"radio":[{"label":"
demarre
","sol":false},{"label":"
start
","sol":false},{"label":"
loop
","sol":false},{"label":"
setup
","sol":true}]}],[{"text":"
Pourquoi le programme suivant provoquera une erreur à la compilation ?

int led = 9;
int brightness = 0;
int fadeAmount = 5;

void setup() {
  pinMode(led, OUTPUT);
}

void loop() {
  analogWrite(led, brightness);
  brightness = brightness + fadeAmount;
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  delay(30);
}

void setup() { 
  Serial.begin(9600); 
}
"},{"radio":[{"label":"
 car il ne commence pas par la déclaration de la fonction
setup
","sol":false},{"label":"
car il manque un point-virgule <pre>;</pre> en fin d'instruction
","sol":false},{"label":"
car il comporte 2 déclarations de fonction
setup
","sol":true},{"label":"
car il manque une accolade
","sol":false}]}],[{"text":"
On doit mémoriser la valeur d'un capteur de température précis à 0,1°C près. Sa plage de valeur est -40/+250°C.

Quelle type de variable doit-on choisir?
"},{"radio":[{"label":"int","sol":false},{"label":"float","sol":true},{"label":"char","sol":false},{"label":"long","sol":false},{"label":"boolean","sol":false}]}],[{"text":"
On doit compter le nombre de personnes rentrant dans une salle de cours du lycée.

Quelle type de variable doit-on choisir?
"},{"radio":[{"label":"int","sol":true},{"label":"float","sol":false},{"label":"char","sol":false},{"label":"long","sol":false},{"label":"boolean","sol":false}]}],[{"text":"
On utilise un capteur de présence qui renvoie une information binaire TOR (0 ou 1).

Quelle type de variable doit-on choisir?
"},{"radio":[{"label":"int","sol":false},{"label":"float","sol":false},{"label":"char","sol":false},{"label":"long","sol":false},{"label":"boolean","sol":true}]}],[{"text":"
On utilise un clavier 12 touches qui renvoie le code ASCII du caractère correspondant à la touche appuyée

Quelle type de variable doit-on choisir?
"},{"radio":[{"label":"int","sol":false},{"label":"float","sol":false},{"label":"char","sol":true},{"label":"long","sol":false},{"label":"boolean","sol":false}]}],[{"text":"
La carte Arduino Uno possède des entrées analogiques (A0, A1, ...)

Pour quel type de signal ces entrées sont-elles prévues?
"},{"radio":[{"label":"
Une tension variable dont la valeur peut être comprise entre 0 et 5V
","sol":true},{"label":"
Un courant variable dont la valeur peut être comprise entre 0 et 5A
","sol":false},{"label":"
Un signal logique TOR qui peut valoir soit 0V soit 5V
","sol":false},{"label":"Une tension sinusoïdale","sol":false}]}],[{"text":"
La carte Arduino Uno possède des entrées numériques (\"digital\" en anglais)

Pour quel type de signal ces entrées sont-elles prévues?
"},{"radio":[{"label":"
Une tension variable dont la valeur peut être comprise entre 0 et 5V
","sol":false},{"label":"
Un courant variable dont la valeur peut être comprise entre 0 et 5A
","sol":false},{"label":"
Un signal logique TOR qui peut valoir soit 0V soit 5V
","sol":true},{"label":"Une tension sinusoïdale","sol":false}]}],[{"text":"
Sur la carte Arduino, les entrées numériques (digital) peuvent aussi être utilisées en sorties numériques (TOR).

Cela se paramètre à l'aide d'un instruction placée dans le programme.
"},{"radio":[{"label":"
 Vrai
","sol":true},{"label":"
 Faux

"}]}],[{"text":"
On a programmé l'instruction suivante:

for (int i=0 ; i<10 ; i=i+2)  {
   .......

}

Elle permet:
"},{"radio":[{"label":"
de faire une boucle qui va s'effectuer 9 fois
","sol":false},{"label":"
de faire une boucle qui va s'effectuer 10 fois
","sol":false},{"label":"
de faire une boucle qui va s'effectuer 11 fois
","sol":false},{"label":"
de faire une boucle qui va s'effectuer 4 fois
","sol":true},{"label":"
de faire une boucle qui va s'effectuer 5 fois
","sol":false}]}],[{"text":"
Nous allons utiliser la fonction suivante:

float perimetre_cercle (float ray)
{
    float per;
    per= 2*pi*ray;           
    return per;       
}

Que renvoie cette fonction?
"},{"radio":[{"label":"
Cette fonction ne renvoie rien.
","sol":false},{"label":"
Cette fonction renvoie le contenu de per (de type \"float\")
","sol":true},{"label":"Cette fonction renvoie le contenu de per (de type \"int\")
","sol":false},{"label":"Cette fonction renvoie le contenu de ray (de type \"float\")
","sol":false}]}],[{"chrono":90},{"text":"
Nous avons le programme suivant:

#define capt_diam_pin A3

float diametre;

float perimetre;

float pi = 3.141592654;

int capteur_diam;

float perimetre_cercle (float ray)
{

   float per;

   per= 2*pi*ray;

   return per;

}


void setup() {

}

void loop()
{

   capteur_diam=analogRead(capt_diam_pin);

   diametre = (((capteur_diam)*5)/1024)*0,1256;

   perimetre=perimetre_cercle(diametre/2);

} // fin du loop

Les variables ci-dessus, sont elles locales ou globales?
Cochez la ou les bonnes réponses?

"},{"chekbox":[{"label":"
La variable \"pi\" est une variable globale
","sol":true},{"label":"La variable \"pi\" est une variable locale","sol":false},{"label":"
la variable \"perimetre\" est une variable globale
","sol":true},{"label":"la variable \"perimetre\" est une variable locale","sol":false},{"label":"
La variable \"per\" est une variable globale
","sol":false},{"label":"La variable \"per\" est une variable locale","sol":true},{"label":"
La variable \"ray\" est une variable globale
","sol":false},{"label":"La variable \"ray\" est une variable locale","sol":true}]}],[{"text":"
Quel nom porte la fonction qui est exécutée en boucle dans un programme Arduino ?
"},{"radio":[{"label":"
demarre
","sol":false},{"label":"
start
","sol":false},{"label":"
loop
","sol":true},{"label":"
setup
","sol":false}]}],[{"text":"Dans les éléments ci-dessous, lequel ou lesquels sont des actionneurs?"},{"chekbox":[{"label":"Une led","sol":true},{"label":"Un moteur électrique","sol":true},{"label":"un écran lcd","sol":true},{"label":"un thermomètre","sol":false},{"label":"un bouton poussoir","sol":false},{"label":"un baromètre ","sol":false}]}],[{"text":"Dans les éléments ci-dessous, lequel ou lesquels sont des capteurs?"},{"chekbox":[{"label":"Une led","sol":false},{"label":"Un moteur électrique","sol":false},{"label":"un écran lcd","sol":false},{"label":"un thermomètre","sol":true},{"label":"un bouton poussoir","sol":true},{"label":"un baromètre ","sol":true}]}],[{"text":"
Dans le programme ci-dessous quelle led va être allumée? 

int led1 = 2;
int led2 = 3;
int led3 = 4;
int x = 512;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
}

void loop() {
  if (x<256) {
    digitalWrite(led1, HIGH);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
  }
  else if (x<512) {
    digitalWrite(led1, LOW);
    digitalWrite(led2, HIGH);
    digitalWrite(led3, LOW);
  }
  else if (x<768) {
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, HIGH);
  } 
  else {
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
  } 
}

"},{"radio":[{"label":"led1","sol":false},{"label":"led2","sol":false},{"label":"led3","sol":true},{"label":"Aucune","sol":false}]}],[{"text":"Quelle est le rôle des entrées analogiques de l'arduino?"},{"radio":[{"label":"De convertir une tension analogique (entre 0 et 5v) en numérique (entre 0 et 1023)","sol":true},{"label":"De convertir une tension analogique (entre 0 et 5V) en numérique (0 ou 1)"},{"label":"De mesurer directement la tension analogique ","sol":false},{"label":"De mesurer directement une tension numérique","sol":false}]}],[{"text":"
On a programmé l'instruction suivante:

int i = 0;
while ( i<10)  {
   .......
   i ++; 

}

Elle permet:
"},{"radio":[{"label":"
de faire une boucle qui va s'effectuer 9 fois
","sol":false},{"label":"
de faire une boucle qui va s'effectuer 10 fois
","sol":true},{"label":"
de faire une boucle qui va s'effectuer 11 fois
","sol":false},{"label":"
de faire une boucle qui va s'effectuer 4 fois
","sol":false},{"label":"
de faire une boucle qui va s'effectuer 5 fois
","sol":false}]}]]

Cliquer ici pour commencer la séquence 10

[[{"quiz":1072}]]


Logo Lycée Paul Sérusier

J'enseigne au
Lycée Paul SERUSIER
Avenue de Waldkappel
29270 CARHAIX PLOUGUER
Tél : 02 98 99 29 29
Site : www.lycee-serusier.fr

footer2

Richard GAUTHIER
Professeur de Physique Appliquée
Certification ISN
Cette adresse e-mail est protégée contre les robots spammeurs. Vous devez activer le JavaScript pour la visualiser.

www.carhaix2020.bzh