2009-09-08 15 views
90

Estoy usando este código y estoy más allá de la frustración:¿Cómo inserto valores NULL usando PDO?

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, '', todas ellas fallar y tirar este error:

Fatal error: Cannot pass parameter 2 by reference in /opt/...

Respuesta

116

estoy aprendiendo DOP, pero creo es necesario utilizar bindValue, no bindParam

bindParam toma una variable, para hacer referencia, y no se tire en un valor en el momento de llamar a bindParam. Encontré esto en un comentario sobre los documentos php:

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

EDIT: P.S. Usted puede tener la tentación de hacer esto bindValue(':param', null, PDO::PARAM_NULL); pero no funcionó para todo el mundo (gracias Va máquina de afeitar para los informes.)

+0

No estoy seguro de la diferencia entre esos dos, pero investigaré algunos. Gracias, tu respuesta también fue genial. – Nacho

+3

Creo que esta podría ser una mejor respuesta que la mía (si de hecho funciona) –

+0

mis pruebas en PHP 5.3.8 + Mysql muestran que no hay diferencia en la consulta generada entre los dos. La parte importante parece ser que el valor pasado es NULL y no '' o '0' – Odin

42

Al utilizar bindParam() debe pasar una variable, no una constante. Así que antes de que la línea de lo necesario para crear una variable y la puso a null

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

que se obtendría el mismo mensaje de error si se trató de:

$stmt->bindParam(':v1', 5, PDO::PARAM_NULL); 
+0

Tienes razón, me acabo de dar cuenta de que lo había hecho antes en mi código, $ null = PDO :: PARAM_NULL; Gracias. – Nacho

+1

Es mejor utilizar bindValue() en este caso, si va a hacer marcadores de posición de todos modos. bindParam() está originalmente destinado a ejecutar una consulta, y luego cambiar las variables y volver a ejecutar sin volver a unir los parámetros. bindValue() se vincula inmediatamente, bindParam() solo en execute. –

+0

Encontré que null debe estar en minúscula en la línea $ myNull = null. $ myNull = NULL NO funcionó. – raphael75

24

Al utilizar INTEGER columnas (que puede ser NULL) en MySQL, DOP tiene algunos (me) un comportamiento inesperado .

Si utiliza $stmt->execute(Array), tiene que especificar el literal NULL y no pueden dar NULL por referencia variable. Así que esto no funcionará:

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

Pero esto va a funcionar:

// $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 

intentado esto en MySQL 5.5.15 con PHP 5.4.1

+0

$ stmt-> execute (array ( ': param' =>! Empty ($ val)? $ Val: null )); Uso! Vacío porque para cadena vacía también desea establecer nulo en la base de datos –

+0

@ShehzadNizamani Solo si el tipo de columna es entero, como en su ejemplo, sí. Pero de lo contrario 'isset()' se correlaciona mejor con 'NULL'. Una cadena vacía también es un valor. – StanE

5

Para aquellos que todavía tienen problemas (no se puede pasar el parámetro 2 por referencia), definir una variable con valor nulo, no sólo pasar null a PDO:

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

Espero que esto ayude.

3

Si desea insertar NULL sólo cuando el value es empty o '', pero insertar el value cuando está disponible.

A) Recibe los datos del formulario utilizando el método POST, y la función de llamadas inserta con esos valores.

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

B) evalúa si un campo no fue llenado por el usuario, e inserta NULL si ese es el caso.

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();  
} 

Por ejemplo, si el usuario hace algo no entrada en el campo de la forma productName, entonces $productName habrá SET pero EMPTY. Entonces, necesita verificar si es empty(), y si lo está, entonces inserte NULL.

Probado en PHP 5.5.17

Buena suerte,

+1

O bien, puede utilizar la función 'IFNULL()' de MySQL en la cadena de consulta. De esta manera: '$ sql =" INSERT INTO products (productId, productName), VALUES (IFNULL (: productId, NULL), IFNULL (: productName, NULL)) ";' – starleaf1

+0

Me gusta la limpieza de su solución. Acabo de probarlo, pero desafortunadamente inserta cadenas vacías en lugar de NULL cuando el usuario no escribe nada en la entrada. Es solo cuestión de preferencia, pero prefiero tener NULL en lugar de cadenas vacías. –

6

que tenían el mismo problema y me encontré con esta solución de trabajo con bindParam:

bindParam(':param', $myvar = NULL, PDO::PARAM_INT); 
-1

probar esto.

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

Antes de intentar responder una pregunta tan antigua, primero debe leer otras respuestas. Puede ser que ya ha sido respondida. –

Cuestiones relacionadas