8768 sujets

Développement web côté serveur, CMS

Bonsoir à tous
Petit problème dont tout utilisateur de PDO doit connaître la solution:
J'ai défini un champ "lastUsed" de la façon suivante:

ALTER TABLE `Locations`  ADD `lastUsed` DATE NULL DEFAULT NULL  AFTER `type`;

Je crée une requête préparée contenant un paramètre ':lastUsed'.

$sql = 'INSERT INTO Locations(locationID, type, lastUsed) VALUES(:locationID, :type, :lastUsed)';

je ne parviens pas à faire une commande bindValue correcte pour mettre la valeur de ce paramètre à NULL
J'ai essayé

$sql = 'INSERT INTO Locations(locationID, type, lastUsed) VALUES(:locationID, :type, :lastUsed)';
$stmt = $pdo -> prepare($sql);
$stmt -> bindValue(':locationID', 'toto');
$stmt -> bindValue(':type', '');
$value = NULL;
$stmt -> bindValue(':lastUsed', $value, PDO::PARAM_NULL);

Je récupère toujours une erreur HY093 (sans autre information dans $stmt -> errorInfo()),
que je mette NULL dans une variable intermédiaire ou directement dans bindValue, que je mette ou non PDO::PARAM_NULL

J'ai testé sur phpMySQL que la commande

INSERT INTO Locations(locationID, type, lastUsed) VALUES('toto', '', null)

fonctionne correctement

Quelle est l'énormité que j'ai commise ?
Modifié par PapyJP (25 Jan 2019 - 21:41)
IL semble que ce soit une faute de frappe dans mon code, je vais regarder ça lundi en rentrant de week end, je laisse tomber pour le moment.
Le debugging des requêtes préparées est une plaie, la fonction $stmt -> debugDumpParams() ne donne pas les valeurs affectées aux paramètres, contrairement à ce que dit la doc. Il y a un bug signalée en 2010 à ce sujet, je pense que c'est sans espoir.
Un peu marre de revenir aux essais-erreurs....
Modifié par PapyJP (25 Jan 2019 - 22:05)
Salut,

De tête, comme ça, il faut utiliser la chaîne 'NULL' au lieu du type null de PHP pour insérer la valeur dans une base de données MySQL.
Meilleure solution
Merci Kach
Apparemment cela semble fonctionner, je dis "semble" par ce que je n'ai fait qu'un seul essai.
Premier point, au lieu d'aligner des lignes de code
$stmt -> bindValue(':param', $value)

j'ai constitué un tableau que je passe en paramètre à exec(), ce qui donne:

$params = [':param1' => $value1, ':param2' => $value2,... ];
$stmt -> exec($params);

Avec la commande SQL

INSERT INTO Locations (locationID, type) 
VALUES (:locationID, :type)

tout fonctionne correctement, que l'on ait ":type" => NULL ou ":type" => "NULL"

Par contre avec la commande SQL

INSERT INTO Locations (locationID, type) 
VALUES (:locationID, :type) 
ON DUPLICATE KEY UPDATE type= :type2

ça ne fonctionne que si ":type2" => "NULL" et pas si ":type2" => NULL

Pour arriver à tester ce point, j'ai réduit ma table Locations à deux colonnes
J'espère que cela va fonctionner aussi bien avec la table complète à 12 colonnes.
Modifié par PapyJP (29 Jan 2019 - 12:07)
Je viens de réaliser quelques essais supplémentaires.
J'ai défini un champ supplémentaire "lastUsed"
Si je le définis comme

ALTER TABLE `Locations` CHANGE `lastUsed` `lastUsed` VARCHAR(32) NULL DEFAULT NULL;

je n'ai aucun problème à le mettre à NULL par le mécanisme décrit dans mon précédent message.
Par contre si le définis comme

ALTER TABLE `Locations` CHANGE `lastUsed` `lastUsed` DATE NULL DEFAULT NULL;

je ne parviens pas à mettre ce champ à NULL
La structure errorInfo est

Array
(
    [0] => 22007
    [1] => 1292
    [2] => Incorrect date value: 'NULL' for column 'lastUsed' at row 1
)

En d'autres termes, il semble qu'on peut définir un champ comme "DATE NULL" mais qu'on ne peut pas lui donner la valeur 'NULL' parce que ce n'est pas une valeur de date correcte.
Il s'agit apparemment d'une incohérence.
Votre opinion?
Pour éviter le problème, j'ai défini une valeur par défaut de cette date, et le code est écrit de telle façon que si on veut la mettre à "NULL" je la mets à cette valeur par défaut.
Ça me permet de continuer, mais j'aimerais bien avoir le cœur net sur ce problème.