web-dev-qa-db-fra.com

Comment insérer des valeurs NULL à l'aide de PDO?

J'utilise ce code et je suis au-delà de la frustration:

try {
    $dbh = new PDO('mysql:dbname=' . DB . ';Host=' . Host, USER, PASS);
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $dbh->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
}
catch(PDOException $e)
{
    ...
}
$stmt = $dbh->prepare('INSERT INTO table(v1, v2, ...) VALUES(:v1, :v2, ...)');
$stmt->bindParam(':v1', PDO::PARAM_NULL); // --> Here's the problem

PDO::PARAM_NULL, null, '', tous échouent et jettent cette erreur:

Erreur fatale : Impossible de transmettre le paramètre 2 par référence dans/opt/...

97
Nacho

J'apprends juste le PDO, mais je pense que vous devez utiliser bindValue, pas bindParam

bindParam prend une variable, à référencer, et n'extrait pas de valeur au moment de l'appel bindParam. J'ai trouvé cela dans un commentaire sur la documentation php:

bindValue(':param', null, PDO::PARAM_INT);

EDIT: P.S. Vous pourriez être tenté de faire cette bindValue(':param', null, PDO::PARAM_NULL); mais cela n’a pas fonctionné pour tout le monde (merci Will Shaver pour le compte rendu.)

127
JasonWoof

Lorsque vous utilisez bindParam(), vous devez transmettre une variable et non une constante. Donc, avant cette ligne, vous devez créer une variable et la définir sur null

$myNull = null;
$stmt->bindParam(':v1', $myNull, PDO::PARAM_NULL);

Vous obtiendrez le même message d'erreur si vous essayiez:

$stmt->bindParam(':v1', 5, PDO::PARAM_NULL);
45
Joe Phillips

Lors de l'utilisation de INTEGER colonnes (pouvant être NULL) dans MySQL, PDO a un comportement inattendu (pour moi).

Si vous utilisez $stmt->execute(Array), vous devez spécifier le littéral NULL et vous ne pouvez pas donner NULL par la référence de variable . Cela ne fonctionnera donc pas:

// $val is sometimes null, but sometimes an integer
$stmt->execute(array(
    ':param' => $val
));
// will cause the error 'incorrect integer value' when $val == null

Mais cela fonctionnera:

// $val again is sometimes null, but sometimes an integer
$stmt->execute(array(
    ':param' => isset($val) ? $val : null
));
// no errors, inserts NULL when $val == null, inserts the integer otherwise

J'ai essayé sur MySQL 5.5.15 avec PHP 5.4.1

26
ChrisF

J'ai eu le même problème et j'ai trouvé cette solution fonctionnant avec bindParam:

    bindParam(':param', $myvar = NULL, PDO::PARAM_INT);
6
user1719210

Pour ceux qui ont encore des problèmes (Ne peut pas passer le paramètre 2 par référence), définissez une variable avec une valeur null, pas seulement passez null à PDO:

bindValue(':param', $n = null, PDO::PARAM_INT);

J'espère que cela t'aides.

5
Pedro Guglielmo

Si vous souhaitez insérer NULL uniquement lorsque value est empty ou '', mais insérez la value lorsqu'elle est disponible.

A) Reçoit les données du formulaire à l’aide de la méthode POST, et appelle la fonction insérer avec ces valeurs.

insert( $_POST['productId'], // Will be set to NULL if empty    
        $_POST['productName'] ); // Will be to NULL if empty                                

B) Evalue si un champ n'a pas été rempli par l'utilisateur et insère NULL si c'est le cas.

public function insert( $productId, $productName )
{ 
    $sql = "INSERT INTO products (  productId, productName ) 
                VALUES ( :productId, :productName )";

    //IMPORTANT: Repace $db with your PDO instance
    $query = $db->prepare($sql); 

    //Works with INT, FLOAT, ETC.
    $query->bindValue(':productId',  !empty($productId)   ? $productId   : NULL, PDO::PARAM_INT); 

    //Works with strings.
    $query->bindValue(':productName',!empty($productName) ? $productName : NULL, PDO::PARAM_STR);   

    $query->execute();      
}

Par exemple, si l'utilisateur n'entre rien dans le champ productName du formulaire, alors $productName sera SET mais EMPTY. Donc, vous devez vérifier si c'est empty(), et si c'est le cas, alors insérez NULL.

Testé sur PHP 5.5.17

Bonne chance,

3
Arian Acosta

Dans mon cas, j'utilise:

  • SQLite,

  • instructions préparées avec des espaces réservés pour traiter un nombre inconnu de champs,

  • Demande AJAX envoyée par l'utilisateur où tout est une chaîne et qu'il n'existe pas de valeur telle que NULL value et

  • J'ai désespérément besoin d'insérer NULLs car cela ne viole pas la clé étrangère contraint (valeur acceptable).

Supposons maintenant que l’utilisateur envoie avec post: $_POST[field1] avec la valeur value1 qui peut être la chaîne vide "" ou "null" ou "NULL".

D'abord je fais la déclaration:

$stmt = $this->dbh->prepare("INSERT INTO $table ({$sColumns}) VALUES ({$sValues})");

{$sColumns} est sth comme field1, field2, ... et {$sValues} sont mes espaces réservés ?, ?, ....

Ensuite, je collecte mes données $_POST associées aux noms de colonne dans un tableau $values et remplace par NULLs:

  for($i = 0; $i < \count($values); $i++)
     if((\strtolower($values[$i]) == 'null') || ($values[$i] == ''))
        $values[$i] = null;

Maintenant, je peux exécuter:

$stmt->execute($values);

et entre autres contourner les contraintes de clé étrangère.

Si par contre une chaîne vide a plus de sens, vous devez vérifier si ce champ fait partie d'une clé étrangère ou non (plus compliqué).

0
centurian

Essaye ça.

$stmt->bindValue(':v1', null, PDO::PARAM_NULL); // --> insert null
0
hector teran