【问题标题】:I set a MySQL column to "NOT NULL" but still I can insert an empty value我将一个 MySQL 列设置为“NOT NULL”,但我仍然可以插入一个空值
【发布时间】:2014-03-19 03:27:31
【问题描述】:

在 MySQL 中,我有一个 Column1 为 NOT NULL 的表:

create table myTable 
(
    Column1 int not null,
    Column2 int not null
)

我仍然可以像这样插入一个空值:

INSERT INTO `myTable` ( `Column1` ,  `Column2` )
VALUES ( '66', '' );

如何使 MySQL 列也不允许空白字符串?

【问题讨论】:

  • @zac1987:你真的可以在int 列中插入一个空字符串吗?你是怎么做到的(为什么要尝试?)
  • @Martin Smith,如何检查我使用的是什么 RDBMS? phpMyadmin 是 RDBMS 吗?我正在使用 phpMyadmin。
  • @ypercube,是的,我可以在 int 列中插入一个空字符串,但它会自动将其转换为“0”。我想防止用户向数据库插入空值,例如,用户打开 2 个选项卡,他在 1 个选项卡上注销了他的帐户,然后他提交了第 2 个选项卡的表单,表单提交会将空的 user_id 保存到数据库列,因为他已经从他的帐户。我认为最好将数据库列设置为不接受空条目。
  • 我看到在 Mysql 中强制执行这样一个约束的唯一其他方法(我想你会使用它)是从 Column2 添加一个 FOREIGN KEY 约束,它引用 anotherTable(column) 哪个列有一个列表Column2 的允许值。
  • 好主意(在没有真正的 CHECK 约束的情况下),但不要对货币价值等字段这样做;)

标签: mysql database


【解决方案1】:

空字符串

在 ORACLE 中,一个空字符串用于表示 NULL。然而,在几乎所有其他情况下,空字符串仍然是字符串,因此不是 NULL。


INTS

在您的情况下,您实际上是将 STRINGS 插入到 INT 列中。这会强制执行隐式 CAST 操作。

当您的 RDBMS 将字符串 '' 转换为 INT 时,它必须获得值 0。因为 0 不是 NULL,所以它被插入。

更有效的测试是:

INSERT INTO `plekz`.`countries` (`Column1 ` , `Column2`)
VALUES (66, NULL);


编辑

对不起,我只看了一半你的问题。您还问如何阻止'' 被插入。

您的第一个问题是您正在插入 STRINGS,并且该表被定义为具有 INT 字段。您可以对插入的数据施加约束,但这些约束会将值 after 转换为 INT。除非您想阻止值 0 也被插入,否则您无法对表执行任何操作来防止这种情况发生。

最好的办法是首先说明为什么要插入字符串。您可以使用一个存储过程,在将字符串转换为 INT 然后插入它们之前获取并检查这些字符串。或者,更好的是,您可以在客户端应用程序中进行检查。

技术上可用的选项是使字段 CHAR 字段,然后对字段施加约束,防止插入 ''。我会强烈建议不要这样做。

【讨论】:

  • 如果 OP 在 MySQL 上不是 check constraints just ignored?
  • 我明白了,谢谢。我测试了 Null 并看到错误消息“#1048 - Column 'Column2' cannot be null”。我需要写 php if ($user_id == "") then $user_id = Null;在将 $user_id 的值插入数据库之前?
  • martin smith:幸运的是,这是推动 OP 在调用他的 SQL 语句之前验证数据的另一个原因。 zac1987:这是一个选项,是的。在将数据扔到数据库之前,您总是最好检查您的数据。
【解决方案2】:

您插入的是一个空字符串,而不是NULL。该约束仅针对 NULL 值,并且看起来您的数据库在将空字符串转换为 INT 时并未将它们强制为 NULL(这引发了另一个问题,即为什么要将字符串文字插入 INT 列......)

【讨论】:

  • 好点。我似乎记得在 MySQL 中被强制为 0。
  • 这里的推论是你需要一个CHECK 约束来拒绝空字符串(可能字符串只包含空格)。
  • Jeffrey Hantin:该字段是一个 INT,您不能在那里检查空字符串(值在插入之前转换为 INT,在 CHECK 约束之前也是如此)。更不用说 MySQL 显然忽略了 CHECK 约束(我不确定它为什么会有它们......)
  • @Dems:它拥有它们,因此来自其他 RDBMS(具有 CHECK 约束)的 CREATE TABLE 语句不会产生错误(我猜)。
【解决方案3】:

MySQL,如何禁止空字符串:

  1. 创建你的表:

    mysql> create table yar (val VARCHAR(25) not null);
    Query OK, 0 rows affected (0.02 sec)
    
  2. 创建“插入前”触发器以检查空白字符串并禁止。

    mysql> create trigger foo before insert on yar
        -> for each row
        -> begin
        -> if new.val = '' then
        -> signal sqlstate '45000';
        -> end if;
        -> end;$$
    Query OK, 0 rows affected (0.01 sec)
    
  3. 尝试在列中插入 null 和空白字符串:

    mysql> delimiter ;
    
    mysql> insert into yar values("");
    ERROR 1644 (45000): Unhandled user-defined exception condition
    
    mysql> insert into yar values(NULL);
    ERROR 1048 (23000): Column 'val' cannot be null
    
    mysql> insert into yar values ("abc");
    Query OK, 1 row affected (0.01 sec)
    
    mysql> select * from yar;
    +-----+
    | val |
    +-----+
    | abc |
    +-----+
    1 row in set (0.00 sec)
    

最后,对自己发牢骚,并打掉最近的负责选择 mysql 而不是 postgresql 的人。

【讨论】:

【解决方案4】:

正如 Martin 所说,这取决于您的 RDBMS。 Oracle 将空字符串视为 NULL,而其他字符串则不。看到这个SO post

【讨论】:

    【解决方案5】:

    NULL 不等于空。在 MySQL 中,每个列条目都有一个额外的字节来保存“为空”信息。为了节省空间,如果 null 状态不会向数据模型添加任何内容,则通常将列定义为“not null”以节省这个额外的字节。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-24
      • 2020-01-15
      • 2011-04-05
      • 1970-01-01
      • 2022-12-15
      • 2020-01-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多