Memo PHP et SQLite

Cette page regroupe quelques lignes de code PHP pour utiliser SQLite. Il s’agit plus d’un mémo personnel que d’un véritable tutoriel.

SQLite est un système de gestion de bases de données léger intégré directement dans PHP5, au moyen d’un simple module.

L’avantage de SQLite est sa simplicité et sa légèreté. La base de données est un simple fichier binaire « .sqlite » rendant la sauvegarde d’un coup beaucoup plus simple.

SQLite peut-être utilisé avec PHP, mais également avec d’autres langages (Java, C/C++, Python…) et il est ainsi utilisé massivement dans de nombreux logiciels (Firefox, LibreOffice…) ou systèmes d’exploitations, y compris les Smartphones (iOS, Android…).

Ci-dessous j’ai noté les moyens d’utiliser SQLite avec PHP. Il n’y a souvent pas d’explications, et je donne la ligne de code à titre d’exemple.

En PHP Procédural

Ouvrir / créer une base

Ceci ouvre la base. Le fichier .sqlite est créé s’il n’existe pas.

$db_handle = sqlite_open('fichier.sqlite', 0666, $error);

// gestion des erreurs
if (!empty($error)) {
    die('Erreur SQLite : '.$error);
}

À la fin, on referme la base de données. C’est plus propre même si SQLite ne peut normalement pas s’altérer.

sqlite_close($db_handle);

Créer une table

C’est comme dans les autres SGBD :

// Ouverture de la base
$db_handle = sqlite_open('fichier.sqlite', 0666, $error);

// requête SQL
sqlite_query($db_handle, "CREATE TABLE matable ( ID INTEGER PRIMARY KEY, champ TEXT, autrechamp INTEGER );", NULL, $error);

// Gestion des erreurs éventuelles
if (!empty($error)) { 
    die('Erreur SQLite : '.$error);
}

Supprimer une table

sqlite_query($db_handle, "DROP TABLE matable", NULL, $error);

Lister les tables dans une base

Il s’agit de lister les éléments de type « table » de la base elle même (et non dans une table). Ici, le résultat est un tableau php (array()) car j’ai utilisé la fonction sqlite_single_query() :

// listage des tables dans un array() :
$tables = sqlite_single_query($db_handle, "SELECT name FROM sqlite_master WHERE type='table'");

$tables contient quelque chose comme ça : array(1 => 'table1', 2 => 'table2', …);

Ceci peut-être utile si vous devez vérifier la présence d’une table dans la base, vu que l’option « IF NOT EXISTS » n’exste pas en SQLite pour la création des tables. On contourne ça en listant les bases présentes et en ajoutant seulement celles qui manquent.

Ajouter une entrée

Basique là aussi, avec INSERT INTO :

INSERT INTO table ( champ, autrechamp ) VALUES ( 'text', 42 )

Ajouter plusieurs entrées « à la volée »

Pour ajouter plusieurs lignes à la table, on peut faire ça :
INSERT INTO table ( one, two ) VALUES ( 'bla', 'bli' )
INSERT INTO table ( one, two ) VALUES ( 'blo', 'blu' )
INSERT INTO table ( one, two ) VALUES ( 'bly', 'ble' )

Mais SQLite est lent à l’accès. Aussi, plutôt que de faire 3 requêtes séparées avec chacun un sqlite_query(), il est largement mieux de regrouper les requêtes en une seule :

Contrairement à MySQL, qui utilise cette syntaxe :

# MYSQL:
INSERT INTO tbl ( one, two) VALUES (
   ('bla', 'bli'),
   ('blo', 'blu'),
   ('bly', 'ble'),
   ...
);

SQLite utilise une syntaxe un peu particulière, peu intuitive (qui marche aussi avec MySQL en fait) :

# SQLite:
INSERT INTO tbl ( one, two)
             SELECT 'bla', 'bli'
   UNION ALL SELECT 'blo', 'blu'
   UNION ALL SELECT 'bly', 'ble'
   ...
;

Modifier plusieurs entrées « à la volée »

Cette méthode, que j’ai élaborée moi même après quelques bidouillages, n’ayant pas vraiment trouvé de solutions sur le net, fonctionne.

Au lieu de faire :

UPDATE tbl SET two='bli' WHERE one='bla';
UPDATE tbl SET two='blu' WHERE one='blo';
UPDATE tbl SET two='ble' WHERE one='bly';

faites, en une seule commande :

UPDATE tbl SET two = (CASE
   WHEN one='bla' THEN 'bli'
   WHEN one='blo' THEN 'blu'
   WHEN one='bly' THEN 'ble'
ELSE two END) 

ATTENTION : n’oubliez pas le ELSE two END à la fin ! Si tous les cas précédent avec WHEN ne sont pas trouvés, il mettra dans two la précédente valeur de two. Si vous ne le mettez pas, alors il met une chaîne vide à la place !

ATTENTION : Remarquez qu’entre les deux solutions (commande unique ou commande multiple), l’ordre des colonnes à changé ! Dans l’écriture de la requête, sur la première on a « bli » puis « bla », alors qu’après on a « bla » puis « bli ».

Supprimer une entrée selon un critère

Facile :

DELETE FROM table WHERE champ='$var'

Et selon deux critères simples :

DELETE FROM table WHERE champ='$var' AND autrechamp='$autrevar'

Supprimer plusieurs entrées « à la volée »

Attention à toujours spécifier un WHERE avec un DELETE, sinon ce sont toutes les lignes de la table que vous supprimez…
Pour supprimer plusieurs lignes, c’est plutôt simple : il suffit d’utiliser OR.

DELETE FROM table WHERE champ='$var' OR champ='$var2' OR champ='$var3' OR ...'

Lire une entrée

Très classique, on utilise SELECT :

Sélectionne toute la ligne (chaque colonne de la ligne) :

SELECT * FROM table WHERE colonne='valeur'

Sélectionne une case « case » de la ligne :

SELECT case FROM table WHERE colonne='valeur'

Lire toute la base et obtenir un tableau « array »

Ceci est pratique si on ne veut pas utiliser des boucles WHILE et le fetch(). Il permet de tout mettre dans un tableau directement, avec la fonction SQLite  :

$query = "SELECT * FROM 'tableau' WHERE id < 3 ORDER BY id"; 
$result = sqlite_array_query($db_handle, $query, SQLITE_ASSOC);

$result contient un tableau. Un print_r($result) donne :

Array
(
  [0] => Array
      (
        [id] => 1
        [one] => bla
        [two] => bli
      )

  [1] => Array
      (
        [id] => 2
        [one] => blo
        [two] => blu
      )

  [2] => Array
      (
        [id] => 3
        [one] => bly
        [two] => ble
      )

  [3] ...
  [4] ...
  ...

)

Recherche par comparaison

Le signe % indique qu’il peut y avoir autre chose :

SELECT * FROM 'table' WHERE champ LIKE '%$recherche%'

Rechercher « bon » dans un champ contenant « bonjour » se fera avec "bon%".
Rechercher « jour » dans un champ contenant « bonjour » se fera avec "%jour".
Rechercher « onjou » dans un champ contenant « bonjour » se fera avec "%onjou%".

Recherche booleenne « non » : le premier champ doit contenur $recherche, mais le seconde champ ne doit pas le contenir

SELECT * FROM 'table' WHERE champ LIKE '%$recherche%' AND NOT autrechamp LIKE '%$recherche%'

En PHP Objet « PDO »

PDO est un moyen d’accéder au bases de données en PHP Objet. Son avantage en pratique, c’est qu’il permet de traiter plusieurs langages SQL avec les memes lignes de code.
Ainsi, il suffira juste de dire qu’on travail avec MySQL au lieu de SQLite par exemple, et ça marchera. Il y a une seule ligne à changer dan toute l’application, et on a plus à changer toutes les requêtes. Mais ça c’est la théorie, car en pratique, il reste quelques différences.

Néanmoins, une grande partie des requêtes PDO que j’ai eu à écrire pour SQLite fonctionnaient directement également avec MySQL.

Notez qu’ici j’utiliserai les requêtes préparées. C’est une façon de procéder qui sécurise automatiquement les requêtes : il n’y a pas besoin d’utiliser les fonctions d’échapement des données saisies par l’utilisateur, PDO le fait lui même.

Notez également la simplicité du code : pas de guillements à outrance, ni rien. C’est beaucoup plus simple.

Ouvrir / créer une base

En PHP-Objet, j’utilise là les gestion d’erreur try/catch.

try {
// Nouvel objet de base SQLite 
   $db_handle = new PDO('sqlite:db.sqlite');
// Quelques options
   $db_handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (Exception $e) {
   die('Erreur : '.$e->getMessage());
}

Créer une table

Ceci se passe évidemment après qu’on ait ouvert la table. Je ne met plus les try/catch, mais ce code est évidemment à placer dans le try{}

$results = $db_handle->exec("CREATE TABLE matable (ID INTEGER PRIMARY KEY, champ1 INTEGER, champ2 TEXT);");

Supprimer une table

C’est la même chose que juste au dessus, la requête étant la même que SQLite en mode procédural :

$results = $db_handle->exec("DROP TABLE matable");

Ajouter une entrée

Même chose, allons au plus simple avec les requêtes préparées :

// On prépare la requête
$req = $db_handle->prepare('INSERT INTO table ( champ1, champ2 ) VALUES (?, ?)');

// On l’éxécute.
$req->execute(array($variable1, $variable2));

Avec les requêtes préparées, faites gaffe par contre : le nombre de variables (le nombre de « ? ») est limité à 999 dans PDO. Je n’ai jamais trouvé comment augmenter cette limite. Il m’est arrivé déjà à devoir insérer 100 lignes de 10 variables et là ça plante. L’astuce conciste à faire par exemple deux requêtes de 50 lignes de 10 variables.

Notez que je n’ai nullement échapé les variables lors de l’éxécution. PDO le fait tout seul. C’est l’énorme avantage des requêtes préparées !
Il est possible d’utiliser les requêtes normale, mais c’est à bannir car moins sécurisé :

$results = $db_handle->exec("INSERT INTO table ( champ1, champ2 ) VALUES ($variable1, $variable2)");

Enfin, il existe une autre forme pour ajouter des éléments à la base, avec les requêtes préparées également mais en remplaçant les « ? » par des noms. C’est plus simple pour s’y retrouver, mais il se trouve que SQLite et PDO ont un bug de longue date qui n’a jamais été corrigé… Je préfère donc conseiller la première méthode. Je vous la donne quand même :

$req = $db_handle->prepare('INSERT INTO table ( champ1, champ2 ) VALUES (:var1, :var2)');
$req->execute(array( 'var1'=> $variable1, 'var2'=> $variable2));

Cette méthode est plus précise car les points d’intérrogations sont nommées et chaque nom renvoie vers une race du tableau, donc on s’embrouille moins. Mais elle bug… (voir là).

Ajouter plusieurs entrées « à la volée »

Là encore, le problème de la lenteur se fait sentir si on veut ajouter plusieurs données : soit on fait plusieurs petites requêtes (lent) soit une grosse requête (rapide). C’est là aussi du UNION SELECT, et qui marche aussi avec MySQL en PDO (c’est-y pas bô ?)

Faisons un exemple où j’ajoute 3 lignes de 2 variables (donc 6 variables en tout) :

$req = $db_handle->prepare("INSERT INTO table ( one, two) SELECT ?, ? UNION ALL SELECT ?, ? UNION ALL SELECT ?, ? ");
$req->execute(array($l1c1, $l1c2, $l2c1, $l2c2, $l3c1, $l3c2));

Modifier plusieurs entrées « à la volée »

Supprimer une entrée selon un critère

Supprimer plusieurs entrées « à la volée »

Lire toute la base et obtenir un tableau « array »

// On prépare et éxécute la requête
$req = $handle->prepare("SELECT champ1, champ2 FROM table WHERE champ=?");
$req->execute(array($variable));

// On change la réponse SQL en réponse PHP.
// Ici, on transforme toute la réponse en un gros tableau
// (au lieu de faire ligne par ligne dans une boucle while() par exemple)
$result = $req->fetchAll();

$result sera un tableau contenant ce genre de choses :

Array
(
  [0] => Array
      (
        [champ1] => valeur01
        [champ2] => valeur02
      )

  [1] => Array
      (
        [champ1] => valeur11
        [champ2] => valeur12
      )

  [2] => Array
      (
        [champ1] => valeur21
        [champ2] => valeur22
      )

  [3] ...
  [4] ...

Recherche par comparaison

Ressources…

Sommaire

Page créée en avril 2012. Dernière mise à jour le vendredi 02 novembre 2012.
Adresse de la page : http://lehollandaisvolant.net/tuto/sqlite/