mysql - 为什么要在所需的数据库列上设置 `null: false, default: ""`?

标签 mysql validation devise null relational-database

我正在使用 Devise 构建 Rails 应用程序以进行身份​​验证,其默认数据库迁移设置以下列:

## Database authenticatable
t.string :email,              null: false, default: ""
t.string :encrypted_password, null: false, default: ""

同时设置null: falsedefault: ""有什么用?

我的理解是 null: false 有效地产生了一个必需的值:即, 试图在其中保存一个带有 NULL 值的记录列将在数据库级别失败,而不依赖于对模型的任何验证。

但是 default: "" 基本上通过在保存之前将 NULL 值转换为空字符串来取消它。

我知道对于可选列,您想要拒绝 NULL 值只是为了确保该列中的所有数据都属于同一类型。但是,在这种情况下,电子邮件和密码显然不是可选用户身份验证模型的属性。我确定模型中有验证以确保您不能使用空电子邮件地址创建用户,但是为什么要首先在此处设置 default: ""它是否提供了一些好处或防止了一些我没有考虑过的边缘情况?

最佳答案

广义上讲:

  • 要使列成为必填列,您必须对其设置 null: false。无论您是创建新表还是更新现有表,都是如此。
  • 如果您要更新现有表,数据库引擎将尝试在每一行中用 NULL 填充新列。在这种情况下,您必须使用 default: "" 覆盖此行为,否则它将与 null: false 冲突并且迁移将失败。

关于设计:

Devise 使用两个单独的模板来构建迁移:migration.rb,用于创建新表,以及 migration_existing.rb,用于更新现有表(参见 source on GitHub) .两个模板调用相同的 migration_data method生成有问题的行(即,指定 null: false, default: "" 的行),但如上所述,default: "" 仅在后一种情况下真正相关(有关更多信息,请参见 O. Jones’ answer)。

所以对您的问题的简短回答,特别是在 Devise 迁移的情况下,是“因为生成器使用了并不总是适用的借用代码,但仍然不会破坏任何东西。”

UNIQUE 列的注意事项:

请注意,在大多数流行的 SQL 引擎中,uniquely indexed columns can still contain multiple rows of NULL values ,只要不需要(自然)。但是创建新列的效果既需要是唯一的( null: false, default: "", and unique: true) cannot be added: 数据库引擎尝试用空字符串填充新列行,它与 unique 约束冲突并导致迁移失败。

(此机制失败的唯一情况是,如果您的表中只有一行——它为新列获取一个空字符串值,这自然会通过唯一性约束,因为它是唯一的记录。)

因此,另一种看待它的方式可能是,这些选项是一种安全机制,可防止您运行不应运行的迁移(即,向已填充的表追溯添加所需的列) .

关于mysql - 为什么要在所需的数据库列上设置 `null: false, default: ""`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44904357/

相关文章:

ruby-on-rails - 设计和处理闪光灯

php - 为学校管理系统设计时间表数据库

php - 参数 1 传递给 App\Http\Controllers\Auth\LoginController::authenticated()

c# - 我需要一种模式来对 C# 中的对象应用一些验证

.net - 客户端验证的作用与 .NET 页面验证器/XSS 预防相同吗?

ruby-on-rails - 任何时候 rails 访问 current_user 都会有 400+ms 的开销

ruby-on-rails - Ruby on Rails/gem 设计/模式中的登录页面

php - 未定义索引 : _attribute_set in magento product csv import from admin

mysql - 三表连接的结果不正确

mysql - 有没有办法在不使用子查询的情况下检索聚合值和非聚合值?