参数为false时插入的空值


empty value inserted when parameter is false

我试图在数据库中插入FALSE值,但没有任何运气——它插入了一个空字符串。该列为varchar。如果我插入TRUE值,它将插入1。

我使用的是mysql、PDO和php。

我还使用了一个DB类,它只处理查询,只使用PDO准备的语句来准备和执行查询。

脑海中的问题是一个非常基本的问题:

$sql = 'INSERT INTO api_logs_values (value) VALUES (?)';

然后:

$this->_db->query($sql, array(FALSE));

知道发生了什么吗?

编辑:

增加了表格结构:

api_logs_values | CREATE TABLE `api_logs_values` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`log_id` int(10) unsigned NOT NULL,
`name` varchar(255) DEFAULT NULL,
`value` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `log_id` (`log_id`,`name`)
ENGINE=MyISAM AUTO_INCREMENT=26 DEFAULT CHARSET=utf8

第2版:

我在这里找到了一份关于这方面的错误报告https://bugs.php.net/bug.php?id=33876,但似乎没有一个合适的、好的解决方案。除了设置PDO_PARAM_BOOL属性。

第3版:

我发现我使用的DB类并没有单独绑定params,而是执行($param)http://php.net/manual/en/pdostatement.execute.php,它将所有参数视为PDO::PARAM_STR,这是不正确的。

如果要插入字符串"false",则$this->_db->query($sql, array("FALSE"));

对于数据类型varchar,php值false被视为空字符串。

如果希望TRUE1FALSE0,请将列的数据类型设置为tinyint

MySQL将在列中插入求值为false的值。根据数据类型的不同,实际值会有所不同。对于基于字符的数据类型,将插入一个空字符串。对于数字类型,它将插入0。您应该使用适当的数据类型。(仅供参考,虽然MySQL识别数据类型定义的关键字BOOL,但该列实际上将创建为TINYINT。在这种情况下,它将存储1表示true,0表示false)

如果你想直接存储字符串"false",那么你需要使用字符串文本而不是布尔值false。

MySQL实现如下布尔值:

布尔,布尔这些类型是TINYINT(1)的同义词。零值被认为是错误的。非零值被认为是真的。

(发件人:http://dev.mysql.com/doc/refman/5.0/en/numeric-type-overview.html)

这可能是mysql的"严格模式"问题。我知道命令行客户端会很好地帮助将字符串'false'"转换"为数据类型TINYINT(1)的0。它会产生一个警告,但它会进入。JDBC不会这样做。PDO可能表现得很古怪。。

请参阅JDBC错误报告:http://bugs.mysql.com/bug.php?id=24526

请参阅MySQL SQLMode Strict:http://dev.mysql.com/doc/refman/5.1/en/server-sql-mode.html#sqlmode_strict_all_tables

所以我找到了解决方案。问题在于在我使用的数据库类中绑定值的方式。它在做这样的事情:

$stmt = $this->pdo->prepare($query);
$stmt->execute($param);

但从http://lt.php.net/manual/en/pdostatement.execute.php:它需要一个参数:

input_parameters一个值数组,其元素数与正在执行的SQL语句中的绑定参数数相同。全部的值被视为PDO::PARAM_STR。

数据库类所要做的是首先使用适当的data_type参数(PDO常量)调用bindValue()。这条评论很好地总结了这一点:http://lt.php.net/manual/en/pdostatement.bindvalue.php#104939

您真的应该尝试匹配数据类型。一个简单的if就足以实现这一点。代码将如下所示:

$sql = 'INSERT INTO api_logs_values (value) VALUES (?)';
$value = false;
$value = ($value === false? '0':'1');
$this->_db->query($sql, array($value));