为什么 PHP PDO 忽略 NOT NULL 约束?

Why does PHP PDO ignore NOT NULL constraints?

提问人:Lycodo 提问时间:10/14/2023 最后编辑:Bill KarwinLycodo 更新时间:10/15/2023 访问量:47

问:

我在PHP中使用PDO将值插入到我的MariaDB中。但是,当我违反 NOT NULL 约束时,没有任何反应。在这种情况下,我希望抛出异常。

这是我创建表格的方式:

CREATE TABLE person (
    id INT auto_increment NOT NULL,
    firstname varchar(255) NULL,
    lastname varchar(255) NULL,
    telephone varchar(255) NULL,
    alias1 varchar(255) NOT NULL,
    alias2 varchar(255) NULL,
    CONSTRAINT PRIMARY KEY (id)
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_general_ci;

这是我用于测试的PHP脚本:

<?php

$conn = new PDO(
    'mysql:host=localhost;dbname=tibsi-data', 'root', '',
    array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")
);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$conn->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);

try {
    $stm = $conn->prepare("INSERT INTO person (firstname) VALUES (:firstname)");
    $stm->bindValue(':firstname', 'Mike');

    $success = $stm->execute();
    if (!$success) {
        throw new Exception($stm->errorInfo()[2]);
    }
    $stm->closeCursor();

    $insertId = $conn->lastInsertId();

    header('HTTP/1.1 200 OK');
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode(array('id' => $insertId));
    exit;
} catch (Exception $e) {
    header('HTTP/1.1 500 Internal Server Error');
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode(array('error' => $e->getMessage()));
    exit;
} catch (Error $e) {
    header('HTTP/1.1 500 Internal Server Error');
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode(array('error' => $e->getMessage()));
    exit;
}

如您所见,它没有默认值,我在 INSERT 语句中省略了它。当我使用 SQL 脚本尝试同样的事情时,我确实会遇到错误。 我希望这会在 PHP 中引发异常,从而导致 500 响应。相反,它使用 的空字符串插入行。我从未将其设置为默认值。 我可以设置一些属性来获得我想要的行为吗?alias1alias1

php pdo null mariadb 约束

评论


答:

3赞 Bill Karwin 10/14/2023 #1

查看 https://mariadb.com/kb/en/null-values/

如果将 NULL 值单行插入到声明为 的列中,则将返回错误。但是,如果 SQL 模式不是 strict(默认到 MariaDB 10.2.3),如果 NULL 值是多行的 插入到声明为 的列中,这是 的隐式默认值 将插入列类型(而不是 表定义)。隐式默认值是 字符串类型,以及数字、日期和时间类型的零值。NOT NULLNOT NULL

从 MariaDB 10.2.4 开始,默认情况下这两种情况都会导致错误。

如果设置了严格模式,则最后一个语句适用。默认情况下,在 MariaDB 10.2.4 及更高版本中设置了严格模式,但您可能已在实例或会话级别更改了该选项。查看 https://mariadb.com/kb/en/sql-mode/sql_mode

在查询客户端中检查当前:sql_mode

SELECT @@sql_mode;

我不确定为什么文档专门提到多行插入。如果插入单行且未启用严格模式,也会发生同样的事情。

评论

0赞 Lycodo 10/15/2023
谢谢!似乎是一个奇怪的 PDO 默认值。我用这个答案在PDO中设置了它。