Benchmark PDO

Bind est plus rapide que l'utilisation d'un array()

PDO::query reste plus rapide est plus simple qu'un Statement dans le cas d'une requête statique.

Difficultés rencontrés à l'utilisation de PDO

num_rows et num_fields

num_rows : le nombre de lignes (affectés) d'un résultat

  • MySQL
    • mysql_num_rows — Retourne le nombre de lignes d'un résultat MySQL
    • mysql_affected_rows — Retourne le nombre de lignes affectées lors de la dernière opération MySQL
  • Oracle
    • oci_num_rows — Retourne le nombre de lignes affectées durant la dernière commande Oracle

Pour compter le nombre d'enregistrements contenus dans votre SELECT, il ne semble exister d'équivalence PDO à la fonction mysql_num_rows qui n'as d'ailleurs pas d'équivalent sous Oracle. A vous de vous organiser avec des count(fetchAll()) ou bien des requêtes COUNT(*) au préalable...

Pour connaître le nombre d'enregistrements affectés avec votre UPDATE, vous pouvez utiliser PDOStatement->rowCount — Retourne le nombre de lignes affectées par le dernier appel à la fonction PDOStatement::execute()

num_fields : le nombre de champs (colonnes) d'un résultat

  • MySQL
  • Oracle
    • oci_num_fields — Retourne le nombre de colonnes dans un résultat Oracle

PDOStatement->columnCount — Retourne le nombre de colonnes dans le jeu de résultats

Par exemple pour mettre des en-têtes avant d'afficher vos données :

$sql = "SELECT * FROM MyTable";
$result = $DbToQuery->query($sql);
// Get the number of columns
$Cols = $result->columnCount();
// Loop through the results
$countrows = 1;
while($row = $result->fetch(PDO::FETCH_ASSOC)) {
   if($countrows == 1) {
      // Print column names
      print join(",", array_keys($row));
   }
   $countrows++;
   // handle the row data
   // ...
}

IN()

DATES

NULL

Problème pour un SELECT : IS NULL, pas = NULL

On peut le typer avec les constantes PDO pré-définies

  • PDO::PARAM_NULL

Oracle FAQ : NULL est un marqueur qui represente des données manquantes, inconnue ou inapplicables.

Les tris ASC et DESC sur les NULL avec Oracle : Dans l'ordre ASCendant, les valeurs NULL apparaissent toujours à la fin.

SELECT * FROM emp ORDER BY sal DESC NULLS FIRST;
 
SELECT * FROM emp ORDER BY sal DESC NULLS LAST;

Avec MySQL, il n'y pas d'option de tri des NULL. Les NULL sont placés en premier pour un tri ASC.

Et les exemples valides et invalides :

Exemples invalides

Un NULL n'est pas égal à NULL:
SELECT * FROM emp WHERE NULL = NULL;
Un NULL ne peut pas être égal à un NULL:
SELECT * FROM emp WHERE NULL <> NULL;
Un NULL n'est pas égal à une chaine vide:
SELECT * FROM emp WHERE NULL = '';

Examples valides

Selection des valeurs nulles NULL d'une colonne:
SELECT * FROM emp WHERE comm IS NULL;
Selection des valeurs non nulles NOT NULL d'un colonne:
SELECT * FROM emp WHERE comm IS NOT NULL;
Changer la valeur d'une colonne en NULL:
UPDATE emp SET comm = NULL WHERE deptno = 20;

Les fetch modes de PDO

Vous aurez surement besoin d'avoir les un fetch mode numérique (PDO::FETCH_NUM) ou litteral (PDO::FETCH_NAMED), mais pas les 2 cumulés (PDO_FETCH_BOTH par défaut)

$stmt = $conPDO->query($query);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
 
// Le code ci dessous est identique mais nécessite une ligne de plus 
$stmt = $conPDO->query($query);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$row = $stmt->fetch();

Consulter les constantes pré-définies de PDO pour connaitre les modes de fetch (PDO::FETCH_*) possibles.

Comment remplacer les différents fetch :

  • MySQL
    • mysql_fetch_array — Retourne une ligne de résultat MySQL sous la forme d'un tableau associatif, d'un tableau indexé, ou les deux
    • mysql_fetch_assoc — Lit une ligne de résultat MySQL dans un tableau associatif
    • mysql_fetch_field — Retourne les données enregistrées dans une colonne MySQL sous forme d'objet
    • mysql_fetch_lengths — Retourne la taille de chaque colonne d'une ligne de résultat MySQL
    • mysql_fetch_object — Retourne une ligne de résultat MySQL sous la forme d'un objet
    • mysql_fetch_row — Retourne une ligne de résultat MySQL sous la forme d'un tableau
  • Oracle
    • oci_fetch_all — Lit toutes les lignes d'un résultat Oracle
    • oci_fetch_array — Lit une ligne d'un résultat Oracle sous forme de tableau
    • oci_fetch_assoc — Lit une ligne d'un résultat Oracle sous forme de tableau associatif
    • oci_fetch_object — Lit une ligne d'un résultat Oracle sous forme d'objet
    • oci_fetch_row — Lit une ligne d'un résultat Oracle sous forme de tableau numérique
    • oci_fetch — Lit la prochaine ligne dans le résultat Oracle

De bonnes explications sont données sur le blog de BSO HQ :

  1. Les fetch modes de PDO
  2. Les fetch modes de PDO : les modes orientés objet
  3. Les fetch modes de PDO : les modes spéciaux
  4. Les fetch modes de PDO : les modes modificateurs

Également des notes utiles :

Ressources

Se connecter à une source de données (datasource) avec PDO

Erreurs

Oracle

Des erreurs Oracle avec PHP (et PDO)

Tous avec en complément de l'erreur : (/usr/src/php5-5.3.2/ext/pdo_oci/php-pdo-oci-1.0.1/PDO_OCI-1.0.1/oci_driver.c:579)

Mauvaise URI de connexion à la base et son serveur hôte
SQLSTATE[42S02]: pdo_oci_handle_factory: ORA-12154: TNS:could not resolve the connect identifier specified
Mauvais user/pass
SQLSTATE[HY000]: OCISessionBegin: ORA-01017: nom utilisateur/mot de passe non valide ; connexion refusee (/usr/src/php5-5.3.2/ext/pdo_oci/php-pdo-oci-1.0.1/PDO_OCI-1.0.1/oci_driver.c:630)
SELECT * WHERE 1 AND id = 3
SQLSTATE[HY000]: General error: 920 OCIStmtExecute: ORA-00920: operateur relationnel non valide
SELECT * FROM maTable LIMIT 5
SQLSTATE[HY000]: General error: 933 OCIStmtExecute: ORA-00933: la commande SQL ne se termine pas correctement
SELECT * FROM maTable where rownum <= 5;
SQLSTATE[HY000]: General error: 911 OCIStmtExecute: ORA-00911: caractere non valide
SELECT "id" FROM maTable
SQLSTATE[HY000]: General error: 904 OCIStmtExecute: ORA-00904: "id" : identificateur non valide
SELECT * , id FROM maTable
SQLSTATE[HY000]: General error: 923 OCIStmtExecute: ORA-00923: mot-cle FROM absent a l'emplacement prevu
SELECT * FROM maTable;
SQLSTATE[HY000]: General error: 942 OCIStmtExecute: ORA-00942: Table ou vue inexistante

Car la table a été crée en spécifiant les doubles quotes " sur son nom, il faut y accéder avec les mêmes doubles quotes :

SELECT * FROM "maTable"

Que ce soit pour le nom des tables ou des champs, pour permettre à Oracle d'utiliser à la fois les minuscules et majuscules dans le nom, il faut l'encapsuler (aussi bien à la création CREATE qu'à la lecture avec un SELECT) avec des doubles quotes ".

Sinon par défaut il vous retourne, sa case : UPPER_CASE

Bien que modifiable avec PDO::setAttribute et l'attibut PDO::ATTR_CASE qui force les noms de colonnes à une casse particulière, on ne peut pas mixer du upper et lower case sans double quoter les noms des tables ou des colonnes.

$conPDO->setAttribute (PDO::ATTR_CASE, PDO::CASE_NATURAL); // laisse les noms des colonnes inchangées. Laisse les noms des colonnes comme retournés par le driver de base de données.
$conPDO->setAttribute (PDO::ATTR_CASE, PDO::CASE_LOWER); // force les noms des colonnes à être en minuscules.
$conPDO->setAttribute (PDO::ATTR_CASE, PDO::CASE_UPPER); // force les noms de colonnes à être en majuscules.

Voir :

Règles de standardisation SQL et conventions de nommage des objets SQL