php - una - PDOstatement(MySQL): insertar el valor 0 en un campo de bit(1) da como resultado 1 escrito en la tabla
que significa not null en mysql (4)
Estoy usando un campo de bit (1) para almacenar valores booleanos y escribir en la tabla usando declaraciones preparadas con PDO.
Esta es la tabla de prueba:
CREATE TABLE IF NOT EXISTS `test` (
`SomeText` varchar(255) NOT NULL,
`TestBool` bit(1) NOT NULL DEFAULT b''0''
) ENGINE=MEMORY DEFAULT CHARSET=latin1;
Este es el código de prueba:
$pdo = new PDO("connection string etc") ;
$statement = $pdo->prepare(''INSERT INTO `test` (SomeText,TestBool) VALUES (?,?)'') ;
$statement->execute(array("TEST",0)) ;
Ejecutar ese código me da una fila con el valor 1 en TestBool. Y lo mismo con bindValue () y bindParm (). También probé marcadores de posición con nombre (en lugar de?) Con el mismo resultado.
Entonces probé:
$statement = $pdo->prepare(''INSERT INTO `test` (SomeText,TestBool) VALUES ("TEST",0)'') ;
$statement->execute() ;
Lo cual funcionó correctamente (TestBool tiene valor 0). Perforar el SQL directamente en MySQL también funciona.
Tenga en cuenta que insertar 1 siempre funciona.
Entonces, ¿por qué los marcadores de posición no pueden insertar el valor 0? (¿y cómo lo hago realmente?)
Como prepare
agrega a su parámetro, solo debe agregar b
antes del nombre del parámetro
$statement = $pdo->prepare(''INSERT INTO `test` (SomeText,TestBool) VALUES (?, b?)'');
$statement->execute(array("TEST", 1 /* or TRUE */));
Nota : puede usar 1, 0
o TRUE, FALSE
.
La columna BIT es un tipo binario en mysql (aunque está documentado como tipo numérico, eso no es precisamente cierto) y aconsejo evitarlo debido a problemas con las bibliotecas cliente (lo que prueba el problema PDO). Se ahorrará muchos problemas si modifica el tipo de columna en TINYINT (1)
TINYINT (1) consumirá, por supuesto, un byte de almacenamiento completo para cada fila, pero de acuerdo con los documentos de mysql, BIT (1) también lo hará.
desde: http://dev.mysql.com/doc/refman/5.1/en/storage-requirements.html
El requisito de almacenamiento de bits es: aproximadamente (M + 7) / 8 bytes, lo que sugiere que la columna BIT (M) también está alineada por byte.
También encontré esto: https://bugs.php.net/bug.php?id=50757
Para que pueda verificar si el siguiente código funciona como espera:
$pdo = new PDO("connection string etc") ;
$statement = $pdo->prepare(''INSERT INTO `test` (SomeText,TestBool) VALUES (:someText,:testBool)'') ;
$statement->bindValue('':someText'', "TEST");
$statement->bindValue('':testBool'', 0, PDO::PARAM_INT);
$statement->execute();
También puedes probar con diferentes sugerencias de tipo que PARAM_INT, incluso si lo haces funcionar, te aconsejo cambiar a TINYINT.
pdo por defecto no usa declaraciones preparadas para el controlador mysql, sino que las emula creando sql dinámico detrás de las escenas para usted. El sql enviado a mysql termina siendo un solo 0 citado como ''0'', que mysql interpreta como una cadena, no como un número.
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Debería funcionar ahora, y también usará declaraciones realmente preparadas.
puedes probar esto sin ningún parámetro
if($_POST[''bool''] == 1)
{
$bool = "b''1''";
}
else
{
$bool = "b''0''";
}
$statement = $pdo->prepare("INSERT INTO `test` (SomeText,TestBool) VALUES (?,$bool)") ;
$statement->execute(array("TEST")) ;
y no hay problema de seguridad