Travail avec la base de données dans Drupal 7 - leçon 8 - Requêtes d’insertion (INSERT INTO)
Les requêtes d'insertion doivent toujours utiliser le constructeur de requêtes. Certaines bases de données nécessitent des gestionnaires spécifiques pour les champs LOB (Large OBject, comme le texte dans MySQL) et BLOB (Binary Large OBject), d'où l'importance du niveau d'abstraction pour que les pilotes DB implémentent ces gestionnaires.
Les requêtes d'insertion commencent par l'utilisation de la fonction db_insert()
:
<?php $query = db_insert('node', $options); ?>
La requête d'insertion crée un objet requête qui insère une ou plusieurs entrées dans la table node
. Notez que l'utilisation d'accolades n'est pas nécessaire, le constructeur de requêtes gère lui-même les noms de table.
La requête d'insertion utilise une API fluide (fluent API), ce qui signifie que tous les appels de méthode (y compris execute()
) retournent l'objet lui-même, permettant l'enchaînement des méthodes.
Les requêtes d'insertion supportent plusieurs modèles d'utilisation. Le flux principal consiste à définir les champs où insérer les données, puis les valeurs à insérer. Les formes les plus courantes sont décrites ci-dessous.
Forme compacte (Compact form)
Forme préférée pour la majorité des requêtes :
<?php $nid = db_insert('node') ->fields(array( 'title' => 'Example', 'uid' => 1, 'created' => REQUEST_TIME, )) ->execute(); ?>
Cette requête équivaut à :
INSERT INTO {node} (title, uid, created) VALUES ('Example', 1, 1221717405);
Le snippet associe clés et données à insérer.
db_insert('node')
crée un nouvel objet requête pour la table node
.
fields()
accepte généralement un tableau associatif avec les colonnes comme clés et les valeurs à insérer.
execute()
exécute la requête et retourne la valeur du champ auto-increment utilisé (par exemple nid
pour la table node
). Si aucun champ auto-increment n'existe, la valeur retournée est indéfinie.
Forme simplifiée (Degenerate form)
<?php $nid = db_insert('node') ->fields(array('title', 'uid', 'created')) ->values(array( 'title' => 'Example', 'uid' => 1, 'created' => REQUEST_TIME, )) ->execute(); ?>
Cette requête est équivalente et donne le même résultat.
Appeler fields()
avec un tableau indexé définit les colonnes sans valeurs, ce qui est utile pour les insertions multiples.
values()
accepte un tableau associatif ou indexé des valeurs. En cas de tableau indexé, l’ordre doit correspondre à celui des champs définis par fields()
. Pour les tableaux associatifs, l’ordre n’a pas d’importance. La forme compacte est préférable, les formes séparées sont surtout utilisées pour les insertions multiples.
Insertion multiple (Multi-insert form)
L'objet requête supporte l'insertion de plusieurs valeurs. values()
peut être appelé plusieurs fois pour insérer plusieurs enregistrements en une seule requête. Cette opération est optimisée par le pilote DB, exécutant les insertions dans une transaction unique. Par exemple en MySQL :
<?php $values = array( array( 'title' => 'Example', 'uid' => 1, 'created' => REQUEST_TIME, ), array( 'title' => 'Example 2', 'uid' => 1, 'created' => REQUEST_TIME, ), array( 'title' => 'Example 3', 'uid' => 2, 'created' => REQUEST_TIME, ), ); $query = db_insert('node')->fields(array('title', 'uid', 'created')); foreach ($values as $record) { $query->values($record); } $query->execute(); ?>
Ce code exécute trois insertions dans un seul bloc optimisé, en appelant values()
plusieurs fois.
En cas de séparation des appels values()
et fields()
, cela revient à faire trois requêtes :
INSERT INTO {node} (title, uid, created) VALUES ('Example', 1, 1221717405); INSERT INTO {node} (title, uid, created) VALUES ('Example 2', 1, 1221717405); INSERT INTO {node} (title, uid, created) VALUES ('Example 3', 2, 1221717405);
Notez que dans une insertion multiple, la valeur retournée par execute()
est indéfinie et ne doit pas être utilisée car elle dépend du pilote.
Insertion basée sur le résultat d’une requête (table de synthèse)
Pour remplir une table à partir d’autres tables, vous pouvez soit traiter les données via PHP et insérer dans la nouvelle table, soit utiliser une requête INSERT INTO ... SELECT FROM
pour insérer directement.
Exemple : créer la table "mytable" avec tous les nid
et noms d’utilisateurs :
Drupal 6 :
<?php db_query('INSERT INTO {mytable} (nid, name) SELECT n.nid, u.name FROM {node} n LEFT JOIN {users} u on n.uid = u.uid WHERE n.type = "%s"', array ('page')); ?>
Drupal 7 :
<?php // Construire la requête SELECT. $query = db_select('node', 'n'); // Joindre la table users. $query->join('users', 'u', 'n.uid = u.uid'); // Ajouter les champs. $query->addField('n','nid'); $query->addField('u','name'); // Condition pour récupérer uniquement les nœuds de type 'page'. $query->condition('type', 'page'); // Effectuer l'insertion. db_insert('mytable') ->from($query) ->execute(); ?>
Valeurs par défaut (Default values)
Normalement, si aucune valeur n’est définie pour un champ et que la table définit une valeur par défaut, la DB insère cette valeur par défaut automatiquement. Parfois, il faut forcer l’utilisation de ces valeurs par défaut explicitement, par exemple pour toutes les lignes insérées. Cela se fait avec la méthode useDefaults()
.
<?php $query->useDefaults(array('field1', 'field2')); ?>
Ce code indique d’utiliser la valeur par défaut pour les champs field1
et field2
. Attention, déclarer les mêmes champs dans useDefaults()
et fields()
ou values()
provoque une erreur.