两个不能同时为 0 的 tinyint 列的最佳实践

Posted

技术标签:

【中文标题】两个不能同时为 0 的 tinyint 列的最佳实践【英文标题】:Best practice for two tinyint columns that cannot be both 0 【发布时间】:2013-06-17 18:18:29 【问题描述】:

我对这种情况的最佳做法有疑问: 我有一个 mysql 表,其中包含(除了其他列)两列都是 TINYINT(1) 但它们不能都在 0 上,它们可以是 0 和 1、1 和 0、1 和 1 但没有 0 和0。 控制这种情况的最佳方法是什么?甚至是一种控制它的方法?

编辑:我想我会选择 ENUM 选项,但是如果我将 mysql 与 Entity Framework 结合起来,这将如何执行?

【问题讨论】:

这很难。列有什么用?了解它们的实际用途可能有助于人们提出解决方案。 这些列用于系统交付配置,值是 is_physical_delivery,另一个是 is_digital_delivery,因此可以是一个、另一个或两者 那么我可能会同意在一个名为 delivery_configuration 的单个列中建议包含可能值的枚举的答案。 :) 对于这种情况,我同意......像这样:ALTER table ADD delivery ENUM('physical', 'digital', 'both') NOT NULL 会准确地描述数据。 你最终选择了SET 还是ENUM 【参考方案1】:

我能想到的几个选项:

在更新/插入触发器之前验证 在应用程序逻辑中验证 添加具有可接受状态的外键引用 将 ENUM 与所有可能的组合一起使用,并且不允许为 NULL

我个人可能会使用最后一种方法。

编辑:

刚刚意识到——SET 数据类型完美地完成了这一点。

【讨论】:

SET 既酷又快,但在这种情况下,它将允许各种无效值。 @landons Set('0','1') 不允许 '1','1'。 Set('01','10','11') 将允许组合值 '01','10','11'。你指的是哪一组? 我的意思是SET('digital', 'physical') NOT NULL 将允许“数字”、“物理”或“数字、物理” @landons 啊,这比原来的 0,1 更有意义。因此,您有幸提出正确的问题并给出比原始问题更好的答案。但即使在非空 SET 中,您也可以存储空值而不会发出警告。我知道一个枚举在不处于严格模式时也只存储一个空字符串并且输入了错误的值,但这至少给出了一个警告。 @flaschenpost 最初的问题没有考虑到放入 2 ;)。这不能代替正确的验证。【参考方案2】:

我建议使用一个枚举,结合两个值。它们的存储效率很高。所以应该是enum('0;1','1;0','1;1') not null

编辑:

鉴于附加信息,并遵循@landons 的建议,仅作记录:枚举将是

delivery enum('physical', 'digital', 'both') not null;

你可以使用(也关注@landon)

delivery SET('physical','digital');

但这将允许空值。

【讨论】:

你也可以在SET 上使用NOT NULL ;) 我真的很喜欢您将我的主要建议结合到您的答案中的方式【参考方案3】:

一种解决方法是将您的两列合并为一个 BIT(2) 列,然后当您执行更新时,您可以测试您没有将该列更新为 b'00'。

至于内置预防,我不相信有办法做到这一点。

【讨论】:

【参考方案4】:

也许您可以通过将它们放在 1 列中来实现这一点。

第一个数字代表1 第二个数字代表2

然后您的列可能包含值123。如果是0,它们都是。

对于23,第二个数字将是1。对于13,第一个数字将是1

【讨论】:

以上是关于两个不能同时为 0 的 tinyint 列的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

Msq 中tinyint字段对应 java中哪个类型?

为啥 MySQL 将布尔值解释为 TINYINT(1) 而不是 BIT(1)?

MySQL TINYINT(1) 到 BOOL

tinyint 列优化 mysql

为啥 tinyint 在 MySQL 中不能存储超过 255 的数字?

如何将天数(作为列的值)添加到日期?