PHP mysql PDO在不可为null的列中设置0,而不是在输入为null时引发异常
使用PHP PDO for mysql更新具有空值的不可空字段时,我无法生成错误或异常。直接执行sql会产生预期的错误 PDO中的所有内容都会导致status_id字段的值设置为0,而不是异常或错误,表明该字段不允许空值PHP mysql PDO在不可为null的列中设置0,而不是在输入为null时引发异常,php,mysql,pdo,Php,Mysql,Pdo,使用PHP PDO for mysql更新具有空值的不可空字段时,我无法生成错误或异常。直接执行sql会产生预期的错误 PDO中的所有内容都会导致status_id字段的值设置为0,而不是异常或错误,表明该字段不允许空值 $stmt_handler = $this->db_handler->prepare( "UPDATE faxes SET metadata = :metadata, status_id = :status_id, created = :created,
$stmt_handler = $this->db_handler->prepare(
"UPDATE faxes SET metadata = :metadata, status_id = :status_id,
created = :created, updated = :updated, content = :content,
vendor_fax_id = :vendor_fax_id WHERE id = :id");
$stmt_handler->bindParam(':id', $fax->id);
$stmt_handler->bindParam(':metadata', $fax->metadata);
$stmt_handler->bindParam(':status_id', $fax->status_id); // tried different combinations
$stmt_handler->bindParam(':created', $fax->created);
$stmt_handler->bindParam(':updated', $fax->updated);
$stmt_handler->bindParam(':content', $fax->content);
$stmt_handler->bindParam(':vendor_fax_id', $fax->vendor_fax_id);
$stmt_handler->execute();
我尝试了不同的组合,并将PDO::ATTR_EMULATE_设置为false(如本问题所建议的)
我的原始装订:
bindParam(':status_id', $fax->status_id);
试用
bindValue(':status_id', null, PDO::PARAM_INT);
bindValue(':status_id', null, PDO::PARAM_NULL);
bindValue(':status_id', 'NULL', PDO::PARAM_INT);
bindValue(':status_id', 'NULL', PDO::PARAM_NULL);
bindValue(':status_id', null);
bindValue(':status_id', 'NULL');
PHP版本:PHP 5.3.10-1ubuntu3
MYSQL服务器版本:5.5.28-0ubuntu0.12.10.1
按评论编辑
mysql> show columns from faxes;
+---------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+-------------------+-----------------------------+
| id | char(36) | NO | PRI | NULL | |
| vendor_fax_id | char(36) | YES | UNI | NULL | |
| metadata | varchar(255) | NO | | NULL | |
| status_id | int(10) | NO | MUL | NULL | |
| created | datetime | NO | | NULL | |
| updated | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| content | mediumblob | NO | | NULL | |
+---------------+--------------+------+-----+-------------------+-----------------------------+
7 rows in set (0.00 sec)
我试过这个小例子
$host = 'localhost';
$database = 'test';
$dbuser = 'USER';
$dbpasswd = '****';
$dsn = "mysql:host=$host;dbname=$database";
$pdo = new PDO($dsn, $dbuser, $dbpasswd);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sth = $pdo->prepare('insert into test values(?, ?)');
$id = 2;
$name = null;
$sth->bindParam(1, $id);
$sth->bindParam(2, $name);
$sth->execute() or die(implode(';', $sth->errorInfo()));
这个试验台
create table test (
id int not null,
name text not null);
它给了我
PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'name' cannot be null' in /tmp/a.php:15
Stack trace:
#0 /tmp/a.php(15): PDOStatement->execute()
#1 {main}
thrown in /tmp/a.php on line 15
在命令行上
更新:
将语句更改为
update test set name = ? where id = ?
与
执行时无错误,并将name
设置为空字符串
更新2:
我终于明白了。这与PDO无关,而是特定于MySQL的
请参阅,向下搜索“非空”
如果通过设置为NULL来更新已声明为非NULL的列,则如果启用了严格SQL模式,则会发生错误;否则,列将被设置为列数据类型的隐式默认值,并且警告计数将递增。对于数字类型,隐式默认值为0,对于字符串类型,空字符串(“”),对于日期和时间类型,隐式默认值为“0”。见第11.5节“数据类型默认值”
因此,这种行为被记录在案。如果要获得错误,必须启用严格SQL模式。只有在mysql中启用严格模式时,才会在更新时产生此错误。在.ini文件中,检查:
[mysqld]
..snipped..
sql_mode="some values here"
如果它不存在,请添加它,并确保应用了严格的设置,例如:
[mysqld]
..snipped..
sql_mode="STRICT_TRANS_TABLES"
重新启动服务器,然后查看新的错误:)
我复制了你的问题,但没有,当我添加并重新启动mysql时,错误开始出现
当非空字段中已经有值时,Mysql仍然可以运行,因此不会产生硬错误。只有严格模式才会强制它抛出一个。你是否100%认为该列没有应用默认值
0
?如果它在更新sql中工作,请尝试此操作,看看它是否工作听起来与本周早些时候的问题类似。与往返mySQL相反,为什么不先检查null,然后手动引发异常呢。不会直接回答问题,但效率更高(对于阅读代码的其他用户来说也更清晰)。用我的产品(换句话说,它在工作)。PHP5.4.9/win32、MySQL 5.5.25/win32 i的insert语句也能正常工作。你能试一下你的例子的更新语句吗?谢谢,谢谢你的帮助。正如@Ben Griffith提到的,当我打开严格模式时,我得到了预期的错误。
[mysqld]
..snipped..
sql_mode="STRICT_TRANS_TABLES"