PDOstatement(MySQL):将值0插入位(1)字段会导致1写入表中

Pet*_*ter 22 php mysql pdo prepared-statement

我正在使用bit(1)字段来存储布尔值并使用PDO预处理语句写入表中.

这是测试表:

CREATE TABLE IF NOT EXISTS `test` (
  `SomeText` varchar(255) NOT NULL,
  `TestBool` bit(1) NOT NULL DEFAULT b'0'
) ENGINE=MEMORY DEFAULT CHARSET=latin1;
Run Code Online (Sandbox Code Playgroud)

这是测试代码:

$pdo = new PDO("connection string etc") ;
$statement = $pdo->prepare('INSERT INTO `test` (SomeText,TestBool) VALUES (?,?)') ;
$statement->execute(array("TEST",0)) ;
Run Code Online (Sandbox Code Playgroud)

运行该代码在TestBool下给我一行值为1的行.使用bindValue()和bindParm()也是一样的.我也尝试过具有相同结果的命名占位符(而不是?).

然后我尝试了:

$statement = $pdo->prepare('INSERT INTO `test` (SomeText,TestBool) VALUES ("TEST",0)') ;
$statement->execute() ;
Run Code Online (Sandbox Code Playgroud)

哪个工作正常(TestBool的值为0).将SQL直接打入MySQL也行之有效.

请注意,插入1始终有效.

那么为什么占位符无法插入值0?(我怎么做呢?)

Mar*_*ski 31

BIT列是mysql中的二进制类型(虽然它被记录为数字类型 - 这并不完全正确)我建议避免它由于客户端库(PDO问题证明)的问题.如果将列类型修改为TINYINT(1),则会给自己省去很多麻烦

TINYINT(1)当然会为每一行消耗完整的存储字节,但根据mysql docs,BIT(1)也会这样做.

来自:http: //dev.mysql.com/doc/refman/5.1/en/storage-requirements.html

位存储要求是:大约(M + 7)/ 8字节,这表明BIT(M)列也是字节对齐的.

我也发现了这个:https://bugs.php.net/bug.php?id = 50757

因此,您可以检查以下代码是否按预期工作:

$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();
Run Code Online (Sandbox Code Playgroud)

您也可以使用不同于PARAM_INT的类型提示尝试,即使您使其工作,我建议更改为TINYINT.

  • 那很有效.顺便说一下,我刚刚发现使用true/false(而不是1/0)似乎也适用于我的情况. (3认同)

goa*_*oat 5

默认情况下,pdo不使用mysql驱动程序的预处理语句,它通过在幕后为您创建动态sql来模拟它们.发送到mysql的sql最终是一个单引号0,如'0',mysql将其解释为字符串,而不是数字.

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Run Code Online (Sandbox Code Playgroud)

它现在应该工作,你也将实际使用真正准备好的语句.

  • 我尝试过,但仍然无法正常工作。mysql驱动程序是否可能根本不支持本机准备语句?我正在使用php 5.4.0,如果有所作为。 (2认同)