我在安装新的 MariaDB 10.5.8 时遇到问题。
STRICT_TRANS_TABLES
已设置,当我尝试使用$sql
时:
'INSERT INTO test (flag) VALUES (?)'
(其中
flag
定义为 tinyint(1)
),var_dump($params)
显示为:
array(1) {
[0]=>
bool(false)
}
我收到这条消息:
Incorrect integer value: '' for column `mydb`.`test`.`flag` at row 1
如果我这样做:
'INSERT INTO test (flag) VALUES (false)'
没有参数,它按预期工作。
这就是我连接数据库的方式:
$this->PDO = new PDO('mysql:host=' . DB_SERVER . ';dbname=' . DB_NAME . ';charset=utf8mb4', DB_USER, DB_PASSWORD, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_STRINGIFY_FETCHES => false,
]);
$this->PDO->query("SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'");
这就是我将查询/参数发送到 MariaDB 的方式:
$stmt = self::$_instance->PDO->prepare($sql);
$stmt->execute($params);
如果我尝试插入
true
而不是 false
,一切正常。 true
正在沿线某处转换为 1
,并且 false
转换为 ''
。我做错了什么?
所有值都被视为 PDO::PARAM_STR。
https://www.php.net/manual/en/pdostatement.execute.php
execute()
方法不允许您指定变量的类型。它总是转换为字符串,这就是为什么你会得到奇怪的结果:
php > var_dump((string) true);
string(1) "1"
php > var_dump((string) false);
string(0) ""
您可以使用 PDOStatement::bindValue() 指定值的类型:
$statement->bindValue('some_bool', true, PDO::PARAM_INT);
请注意,MySQL 缺少“真正的”布尔类型,这就是为什么我推荐
PDO::PARAM_INT
而不是 PDO::PARAM_BOOL
。
一个更简单的解决方案就是预先将布尔值转换为 int
$stmt = $PDO->prepare('INSERT INTO test (flag) VALUES (?)');
$stmt->execute([(int)$flag]);
这是一个快速片段,可以解决 pdo 参数中布尔值转换为空字符串的问题
$params = array_map(fn($param) => is_bool($param) ? intval($param) : $param, $params);
当我在数据库中关闭@@mode STRICT_TRANS_TABLES时,这些值(1或空字符串)起作用 - 它们作为1或0插入到tinyint(1)类型的mysql列中。