为插入创建一个列 NULL,为更新创建一个 NOT NULL

Make a column NULL for insert and NOT NULL for update

这是我在多个项目中偶然发现的,每次都感觉自己在重新发明轮子:

我有一个 table 存储用户数据。每当创建用户时,我都会在 table 上创建一行。此行在创建时有几个 NULL 字段,因为用户只是告知了一些关键信息(其他非关键信息将在稍后填写)。

但是,当用户完成数据填充后,我想强制这个cols为NOT NULL。

有什么方法可以让不涉及触发器的INSERT列为NULL,而UPDATE列为NOT NULL吗?或者任何其他聪明的解决方案?

谢谢

如果您在 CREATE TABLE 语句中使用列选项,则列无法同时为 NULLable 和 NOT NULL。无法区分插入和更新。

另一种方法是让该列可以为空,但在更新后添加一个引发异常的触发器(在 MySQL 术语中称为 SIGNAL),如果该列在更新后仍然为 NULL。

这是一个快速演示:

mysql> create table mytable (id int primary key, x int);
Query OK, 0 rows affected (0.05 sec)

mysql> delimiter //

mysql> create trigger notnullonupdate before update on mytable
    -> for each row 
    -> begin
    -> if NEW.x IS NULL then
    -> signal sqlstate '45000'
    -> set message_text = 'x must be updated to non-NULL value';
    -> end if;
    -> end//

mysql> delimiter ;

mysql> insert into mytable set id = 42, x = null;
Query OK, 1 row affected (0.03 sec)

mysql> update mytable set id = 42;
ERROR 1644 (45000): x must be updated to non-NULL value

尽管这是可能的,但工作量很大。

大多数开发人员只会通过编写应用程序代码来处理此问题,以确保在执行更新之前该值不为空。当然,这样做的风险是,如果您忘记了应用程序中进行更新的情况之一,或者如果有人在 mysql 客户端中进行了临时更新,则可能会导致您的数据处于无效状态你不会知道的。

CREATE TABLE users ( regular_column SOMETYPE NOT NULL,
                     smart_column SOMETYPE NULL,
                     completed ENUM('no', 'yes') NOT NULL DEFAULT 'no',
                     CHECK ((completed = 'no') OR (smart_column IS NOT NULL)) );

This row has several NULL fields on creation, because the user just informed some critical information (and other non-critical info is going to be filled later).

此时completed = 'no',CHECK约束为TRUE,smart_column可能为NULL。

when the user completes the filling of the data, I want to enforce this cols to be NOT NULL.

此刻 completed = 'yes',CHECK 约束不允许 smart_column 中的 NULL 值。

即将 completed 列设置为 'yes' 可修复 smart_column - 您可以更改它但不能将其设置为 NULL。在 smart_column 被设置为一个值之前,您不能将 completed 设置为 'yes'