5

使用 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, 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_PREPARES 设置为 false (正如这个问题PHP mysql PDO 拒绝设置 NULL 值所建议的那样)

我的原始绑定:

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)
4

2 回答 2

2

仅当您在 mysql 中启用严格模式时才会产生此更新错误。在您的 .ini 文件中,检查:

[mysqld]
..snipped..
sql_mode="some values here"

如果它不存在,请添加它,并确保应用了严格设置,例如:

[mysqld]
..snipped..
sql_mode="STRICT_TRANS_TABLES"

重新启动服务器,看看你的新错误:)

当这不存在时,我复制了您的问题,一旦我添加并重新启动 mysql,错误就开始出现。

当不可空字段中已经有值时,Mysql仍然可以运行,因此不会产生硬错误。只有严格模式会强制它抛出一个。

于 2012-12-21T23:39:53.943 回答
1

我试过这个小例子

$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 = ?

$id = 1
$name = null

执行没有错误并设置name为空字符串。

更新 2

我终于明白了。这与 PDO 无关,但特定于 MySQL。

请参阅UPDATE Syntax,向下搜索“not null”

如果通过设置为NULL来更新已声明为NOT NULL的列,则在启用严格 SQL 模式时会发生错误;否则,该列将设置为该列数据类型的隐式默认值,并且警告计数会增加。数字类型的隐式默认值为 0,字符串类型的默认值为空字符串 (''),日期和时间类型的默认值为“零”。请参见第 11.5 节,“数据类型默认值”。

因此,此行为已记录在案。如果你想得到一个错误,你必须启用严格的 SQL 模式。

于 2012-12-21T22:37:50.127 回答