在数据库中存储性别信息

149

我希望以最少的(大小/性能)代价将用户的性别存储在数据库中。

目前,我想到了三种情况:

  1. Int - 与代码中的Enum相对应(1= 男性,2 = 女性,3 = ...)
  2. char(1) - 存储mf或其他单个字符标识符
  3. Bit (布尔值) - 是否有适用于此选项的字段名称?

我之所以这样问是因为该回答提到字符(chars)布尔值(booleans)

我应该澄清一下,我正在使用MS SQL 2008,它确实具有位(datatype)数据类型。


使用布尔类型:0 - 女性,1 - 男性。 - user15023244
8个回答

205

已经有一个ISO标准了,不需要发明自己的方案:

http://en.wikipedia.org/wiki/ISO_5218

根据该标准,列名应称为“性别”,最接近的数据类型应为tinyint,具体应根据需要使用CHECK约束或查找表。


4
为什么“不适用”跳到9?3-8呢? - Kenmore
4
这是关于性别的。OP明确要求性别,而性别和生理性别可能有不同的可能值需要记录。 - indigochild
5
@indigochild 在问题标题中使用了这两个词,并明显认为它们是等价的,至少对于他的用例来说(YMMV)。我的观点很简单,就是在这个领域中存在一个ISO标准,当存在一个官方标准时,你不应该浪费时间设计自己的方案。当然,除非那个标准没有涵盖到你的特定情况,这是完全可能的。 - Pondlife
1
这应该是被接受的答案。它专注于数据完整性(这是永恒的),而不是优化(这是情境相关的)。 - Paul Cantrell
是否有更新的ISO标准,包含性别流动或其他非二元性别状况的代码?还是我们仍在探索该如何处理这些情况?显然,你可以随意编写代码,但也许提供一些当前最佳实践的链接会更好。或者可能对于不同类型的软件来说,最佳实践也会有所不同。 - Peter Cordes
2
这肯定是答案。 @PeterCordes 这个ISO用于性别(生物学上的性别),而不是性别认同(你认为自己是什么) - 解释在这里。我猜如果想要存储性别(我不知道你使用它的用途),一个小的整型仍然足够好,只要你想存储少于255个性别(例如说 0 = 未知/不想声明,1 = 男人,2 = 女人,3 = 认为自己是女人的男人等)。 - Solid

89

我会把这一列叫做“性别”。

Data Type   Bytes Taken          Number/Range of Values
------------------------------------------------
TinyINT     1                    255 (zero to 255)
INT         4            -       2,147,483,648 to 2,147,483,647
BIT         1 (2 if 9+ columns)  2 (0 and 1)
CHAR(1)     1                    26 if case insensitive, 52 otherwise

BIT 数据类型不能满足需求,因为它只支持两种性别。而INT 支持超过两个选项,但需要4字节的空间,使用尺寸更小/更窄的数据类型会提高性能。

CHAR(1)TinyINT 更优 - 两者占用相同的字节数,但 CHAR 提供了更少的值范围。使用 CHAR(1) 将使得 "m"、"f" 等自然键易于使用,而不是使用被称为替代/人造键的数字数据。此外,CHAR(1) 在任何数据库中都受支持,可以方便地进行移植。

结论

我会选择选项2:CHAR(1)。

补充说明

对于低基数列的索引,对性别列建立索引很可能没有作用。这意味着,该索引的值变化太少,无法为查询提供帮助。


有关性能方面的参考吗?我知道这几乎是微观优化,我不应该这样做,但这可以满足我的好奇心。 - Marko
谢谢@OMG Ponies,那性能呢?在这种情况下,char比bit更昂贵吗? - Marko
4
@Marko:像我之前说的一样,它们是相等的。但是,索引可能不会有用,因为在低基数列上建立索引没有任何价值。这意味着,在值中没有足够的变化量,使得索引无法提供任何价值。 - OMG Ponies
但是使用char(1)会引入字符集问题,特别是当您在同一表中具有多字节字段时。您必须为性别列指定不同的字符集。 - addlistener
1
使用4字节数据类型在64位平台上性能真的会提高多少呢?只是说说而已...;-) - Craig Tullis
如果有需要呢? - shogged

45
在医学中,有四种性别:男性、女性、不确定和未知。你可能不需要全部四种,但肯定需要其中的1、2和4。这种数据类型不适合设置默认值,更不应该将其视为具有“是”和“否”状态的布尔类型。

1
@EJP,有趣。你有这方面的参考资料吗? - Marko
根据这些信息,我会选择与枚举对齐的 TinyInt(正如Hugo所建议的),并选择至少1、2和3(其他)。 - IAbstract
1
@EJP,虽然您的回答可能是正确的,但它并没有说出我应该使用什么数据类型,而是 - 什么是(技术上)正确的性别。 - Marko
@Tom Anderson 域名比必要的要大;-) - user207421
25
英国国家医疗服务体系(NHS)数据字典定义了四个值:0 =“未知”,1 =“男性”,2 =“女性”,9 =“未指定”,这些值与ISO 5218的值相对应。请注意,有两种类型:注册时的性别(通常是出生后不久)和当前性别。 - onedaywhen
显示剩余3条评论

3

我的方法是将 Int(或TinyInt)与 Enum 字段对齐。

首先,如果你在数据库中有一个单一的 bit 字段,那么该行仍将使用一个完整的字节,因此就空间而言,只有当你有多个 bit 字段时才会节省空间。

其次,字符串/字符给人一种“神奇的价值”感觉,无论它们在设计时看起来多么明显。更不用说,它让人们存储几乎任何他们不一定要映射到任何明显东西的值。

第三,数值更容易(也是更好的实践)为其创建一个查找表,以强制执行引用完整性,并且可以与枚举相关联,因此在应用程序或数据库中存储该值时内存中的存储方式是相同的。


1

选项3是你最好的选择,但并非所有的数据库引擎都有“bit”类型。如果没有bit类型,则TinyINT将是你最好的选择。


-1

我使用字符'f'、'm'和'u',因为我从姓名、声音和对话中推测性别,有时不确定性别。最终的决定是他们的意见。

这实际上取决于你对这个人的了解程度以及你的标准是身体形态还是个人身份。心理学家可能需要额外的选项——跨越到女性、跨越到男性、变性为女性、变性为男性、两性具有生殖器和未确定。有了9个选项,不被单个字符清晰定义,我可能会采用Hugo的建议使用小整数。


不相关。这不是一个答案。 - hod

-3
CREATE TABLE Admission (
    Rno INT PRIMARY KEY AUTO_INCREMENT,
    Name VARCHAR(25) NOT NULL,
    Gender ENUM('M','F'),
    Boolean_Valu boolean,
    Dob Date,
    Fees numeric(7,2) NOT NULL
);




insert into Admission (Name,Gender,Boolean_Valu,Dob,Fees)values('Raj','M',true,'1990-07-12',50000);
insert into Admission (Name,Gender,Boolean_Valu,Dob,Fees)values('Rani','F',false,'1994-05-10',15000);
select * from admission;

在此输入链接描述


-7

我会选择第三个选项,但是使用多个非空位(bit)列而不是一个。 IsMale (1=是 / 0=否) IsFemale (1=是 / 0=否)

如果需要: IsUnknownGender (1=是 / 0=否),等等……

这样做可以方便地阅读定义,易于扩展、易于编程,没有使用域外的值的可能性,也不需要第二个查找表+FK或CHECK约束来锁定值。

编辑:更正,您需要至少一个约束条件来确保设置标志有效。


3
为什么我的答案会被踩?能否说明原因,谢谢! - HansLindgren
没有约束条件,所有列都可以是1,或者全部为0。这是毫无意义的,因此您的方案并不满足您的某项要求。 - Jay Kominek
是的,你说得对,你确实需要一个约束条件来检查正确数量的标记是否被“选中”。然而,我不认为所有的反对意见都是针对这个遗漏的... - HansLindgren
这是一个非常受欢迎的问题(看看其他答案的赞数!),而你在多年后加入了一个回答,它相当于一种被广泛教授的技术——独热编码,它甚至没有你所归属的少量具体属性。我不认为将你的投票下降到0以下是正确的,但我也不会感到惊讶。 - Jay Kominek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接