为什么PDO将空值视为空?

a c*_*der 1 php mysql null pdo

我正试图在汽车表中插入一条记录.这是桌子的精简版.

注意:这不是真实的工作模型,不应该使用或评估.我只是以简化的方式展示了我遇到的问题.

mysql> describe desc_autos;
+-----------------+------------------+------+-----+---------------------+----------------+
| Field           | Type             | Null | Key | Default             | Extra          |
+-----------------+------------------+------+-----+---------------------+----------------+
| car_id          | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| automobile_name | varchar(25)      | NO   | MUL |                     |                |
+-----------------+------------------+------+-----+---------------------+----------------+
7 rows in set (0.00 sec)

mysql> select count(*) FROM desc_autos WHERE automobile_name IS NULL;
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

mysql> select count(*) FROM desc_autos WHERE automobile_name = '';
+----------+
| count(*) |
+----------+
|    19322 |
+----------+
1 row in set (0.02 sec)

+-------------+
CREATE TABLE `desc_autos` (
  `car_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `automobile_name` varchar(15) NOT NULL,
  PRIMARY KEY (`car_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 |
+-------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

所以你看到该automobile_name字段是NOT NULL,并且正在为许多记录显示空白值. (忽略字段名称 - 只接受有一个非空值的字段)

我正在从原生MySQL函数转换为PDO.如果我插入一个非空automobile_name值的记录,没问题 - 工作正常.如果automobile_name是空白,则PDO无效.

    $automobile_name = '';
    try 
    {
        $q = "
            INSERT INTO
                desc_autos
                (
                    automobile_name
                )
            VALUES
                (
                    :automobile_name
                )
        ";
        $stmt = $dbx_pdo->prepare($q);
        $stmt->bindParam(':automobile_name',    $automobile_name,   PDO::PARAM_STR);
        $stmt->execute();
        return true;
    } catch(PDOException $err) {
        log_error();
        return false;
    }       
}
Run Code Online (Sandbox Code Playgroud)

这会导致以下错误:

Error: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'automobile_name' cannot be null
Run Code Online (Sandbox Code Playgroud)

我以为我必须隐式告诉PDO插入一个NULL值,否则将插入空值作为...空值.

例如:

$ stmt-> bindValue(':automobile_name',!empty($ automobile_name)?$ automobile_name:NULL,PDO :: PARAM_STR);

在这种情况下我不需要插入NULL - 我需要在给定字段中删除一个空的非null值.

问题:

为什么PDO将空值视为空?

Mic*_*ski 5

听起来你需要将ATTR_ORACLE_NULLS(从未指定名称)设置为适当的设置,因此它不会将空字符串转换为NULL.显然,您当前的值PDO::NULL_EMPTY_STRING导致空字符串''变为空.

// Set it to "natural" mode so NULLs and empty strings aren't modified
$dbx_pdo->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_NATURAL);
Run Code Online (Sandbox Code Playgroud)

文档:PDO连接属性

注意:根据我的快速测试,PDO::NULL_NATURAL似乎是默认设置,但也许你的其他地方被修改了.

根据您的SHOW CREATE TABLE输出,该automobile_nameNOT NULL但未显式定义默认值.我可能会采用将默认设置为空字符串''并允许PDO插入的方法NULL.正如马里奥在主要评论帖中提到的那样:

ALTER TABLE desc_autos MODIFY `automobile_name` varchar(15) NOT NULL DEFAULT '';
Run Code Online (Sandbox Code Playgroud)

在PDOStatement中bindParam(),您可以使用PHP null或空字符串''强制数据库使用其默认值.这不需要更改当前行:

$stmt->bindParam(':automobile_name',    $automobile_name,   PDO::PARAM_STR);
Run Code Online (Sandbox Code Playgroud)