在 MySql 列中接受空值但默认情况下不接受

Accept null values but not by default in a MySql column

我就是找不到问题的答案。如果堆栈溢出,只需 post 它,我将删除我的 post.

我的问题:

我想在 mysql 列中接受 null 值,但默认情况下不接受。当我插入一行时,我还应该为该列设置一个值,这应该是必需的。

现在,在 phpmyadmin 中,如果我选中 Null 字段(接受 null 值),字段 Default (默认值)将自动设置为 null 值。这意味着我可以省略在 insert 查询中为该列设置值,它将自动填充 null 值。

我什么时候说过如果没有设置列应该自动填充?我说接受空值,不是自动填充

我错过了什么吗?

引用 the docs:

Implicit Default Handling

If a data type specification includes no explicit DEFAULT value, MySQL determines the default value as follows: If the column can take NULL as a value, the column is defined with an explicit DEFAULT NULL clause.

因此,如果您的列可以为 null,它 总是 有一个默认值 - 无论是显式设置(通过 DEFAULT ... 子句)还是隐式设置(如上所述)。

正如@Barmar 所注意到的,(至少在理论上)有一种方法可以通过提供始终失败的 DEFAULT 表达式来处理此问题(因为 MySQL 8.0.13 允许它)。

另一种方法(在 8.0.13 之前的版本上可用)是设置一个无论如何都不应该放在您的列中的默认值,并创建一个预插入触发器,根据这种特殊情况检查插入的值。

这种方法的好处是您可以更灵活地针对该情况提供特定错误。缺点是您可能认为特殊的值最终会被现实世界的场景实际使用,从而导致一个非常奇怪的错误。这对于数字来说更容易预防(0 代表未签名的 ID 等),但对于用户创建的字符串和类似实体来说更难预防。

如果列具有 NULL 属性,而您没有指定明确的 DEFAULT 属性,就好像您使用 DEFAULT NULL 定义它一样。这在 "Implicit Default Handling":

的文档中指定

If the column can take NULL as a value, the column is defined with an explicit DEFAULT NULL clause.

如果你想防止在插入时遗漏列,我想你可以通过指定一个导致错误的DEFAULT表达式来实现。这要求您至少使用 MySQL 的 8.0.13 版本,因为在此之前 DEFAULT 必须是文字,而不是表达式。

您可以通过创建一个接受 null 的列,然后应用检查 null 的 BEFORE INSERT 触发器来实现。

例如:

CREATE TABLE `testNulls` (
  `id` int NOT NULL AUTO_INCREMENT,
  `nullField` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 ;

现在创建触发器

DELIMITER $$
CREATE TRIGGER `testNulls_BEFORE_INSERT` BEFORE INSERT ON `testNulls` FOR EACH ROW BEGIN
  if (new.nullField is null) then  
      signal sqlstate '45000' set message_text = 'Cannot insert NULL in nullField';
      END IF;
END$$
DELIMITER ;

尝试在 nullField 列中插入 NULL 将 return 错误 45000,但更新包含 NULL 的行将会成功。

测试 MySQL 8 演示:https://www.db-fiddle.com/f/8eV4VihbeB5woEYwuGMFvK/0