【问题标题】:Common MySQL fields and their appropriate data types常见的 MySQL 字段及其适当的数据类型
【发布时间】:2010-09-26 04:01:39
【问题描述】:

我正在建立一个非常小的 MySQL 数据库,用于存储名字、姓氏、电子邮件和电话号码,并且正在努力为每个字段找到“完美”的数据类型。我知道没有完美的答案,但是对于这些常用字段必须有某种通用约定。例如,我已确定未格式化的美国电话号码太大而无法存储为 unsigned int,它必须至少是 bigint。

因为我确信其他人可能会觉得这很有用,所以我不想将我的问题仅限于我上面提到的领域。

哪些数据类型适用于常见的数据库字段?电话号码、电子邮件和地址等字段?

【问题讨论】:

    标签: mysql database types


    【解决方案1】:

    有人会发布比这更好的答案,但只是想说明我个人永远不会在任何整数字段中存储电话号码,主要是因为:

    1. 您无需对其进行任何算术运算,并且
    2. 迟早有人会尝试(做类似的事情)在他们的区号周围加上括号。

    不过,总的来说,我似乎几乎只使用:

    • INT(11) 用于 ID 或引用另一个 ID 的任何内容
    • 时间戳的 DATETIME
    • VARCHAR(255) 用于保证小于 255 个字符(页面标题、名称等)的任何内容
    • 几乎所有其他内容的文本。

    当然也有例外,但我发现这涵盖了大多数可能性。

    【讨论】:

    • 另外,这是错误的。当我刚开始(使用数据库)时,比我聪明得多的人告诉我,仅仅因为某些东西看起来像一个数字并不意味着它是或应该被这样对待......
    • 盲目地使用 varchar(255) 是个坏主意。至少要付出一些基本的努力来猜测长度。
    • @Morgan Tocker:这是最佳做法,任何低于 255 个字符的内容都将占用相同的空间。
    • @Raveren:这是特定于存储引擎的 - 存储并不是唯一的成本。排序数据和临时表(内存引擎)将使用固定数量。
    • 电话号码实际上一个号码,但只是在文字上的理解。 0004194821947 结果与 004194821947 产生相同的整数 number,但在呼叫路由机制中绝对不会以相同的方式处理。
    【解决方案2】:

    根据我的经验,名字/姓氏字段应至少包含 48 个字符 - 有些国家(例如马来西亚或印度)的完整名称很长。

    您应该始终将电话号码和邮政编码视为文本,而不是数字。给出的正常原因是邮政编码以 0 开头,在某些国家/地区,电话号码也可以以 0 开头。但真正的原因是它们不是数字——它们是标识符恰好由数字组成(并且忽略了加拿大等邮政编码中有字母的国家)。所以将它们存储在文本字段中。

    在 MySQL 中,您可以将 VARCHAR 字段用于此类信息。虽然听起来很懒惰,但这意味着您不必太在意正确的最小尺寸。

    【讨论】:

    • 为了进一步支持您对邮政编码的评论,在英国或加拿大等国家/地区,邮政编码是字母数字的。
    • 您可能需要关注正确的最小尺寸stackoverflow.com/questions/262238/…
    • @iamrohitbanga 虽然您对定义明确的数据是正确的,但名称 VARCHAR(255) 是有道理的。
    【解决方案3】:

    由于您要处理可变长度的数据(姓名、电子邮件地址),因此您会希望使用 VARCHAR。 VARCHAR 字段占用的空间量是[field length] + 1 个字节,最大长度为 255,所以我不会太担心尝试找到一个完美的大小。看看您想象的最长长度可能是什么,然后将其加倍并将其设置为您的 VARCHAR 限制。也就是说……:

    我通常将电子邮件字段设置为 VARCHAR(100) - 我还没有提出问题。我设置为 VARCHAR(50) 的名称。

    正如其他人所说,电话号码和邮政编码实际上不是数值,它们是包含数字 0-9(有时更多!)的字符串,因此您应该将它们视为字符串。 VARCHAR(20) 应该足够了。

    请注意,如果您要将电话号码存储为整数,许多系统会假定以 0 开头的数字是八进制(以 8 为基数)数字!因此,完全有效的电话号码“0731602412”将作为十进制数字“124192010”进入您的数据库!!

    【讨论】:

      【解决方案4】:

      以下是我使用的一些常见数据类型(虽然我不是专业人士):

      | Column           | Data type     | Note
      | ---------------- | ------------- | -------------------------------------
      | id               | INTEGER       | AUTO_INCREMENT, UNSIGNED                                                          |  
      | uuid             | CHAR(36)      | or CHAR(16) binary                                                                |  
      | title            | VARCHAR(255)  |                                                                                   |  
      | full name        | VARCHAR(70)   |                                                                                   |  
      | gender           | TINYINT       | UNSIGNED                                                                          |  
      | description      | TINYTEXT      | often may not be enough, use TEXT 
                                           instead          
      | post body        | TEXT          |                                                                                   |  
      | email            | VARCHAR(255)  |                                                                                   |  
      | url              | VARCHAR(2083) | MySQL version < 5.0.3 - use TEXT                                                  |  
      | salt             | CHAR(x)       | randomly generated string, usually of 
                                           fixed length (x)    
      | digest (md5)     | CHAR(32)      |                                                                                   |  
      | phone number     | VARCHAR(20)   |                                                                                   |  
      | US zip code      | CHAR(5)       | Use CHAR(10) if you store extended 
                                           codes      
      | US/Canada p.code | CHAR(6)       |                                                                                   |  
      | file path        | VARCHAR(255)  |                                                                                   |  
      | 5-star rating    | DECIMAL(3,2)  | UNSIGNED                                                                          |  
      | price            | DECIMAL(10,2) | UNSIGNED                                                                          |  
      | date (creation)  | DATE/DATETIME | usually displayed as initial date of 
                                           a post                                       |  
      | date (tracking)  | TIMESTAMP     | can be used for tracking changes in a 
                                           post                                        |  
      | tags, categories | TINYTEXT      | comma separated values *                                                          |  
      | status           | TINYINT(1)    | 1 – published, 0 – unpublished, … You 
                                           can also use ENUM for human-readable 
                                           values
      | json data        | JSON          | or LONGTEXT       
      

      【讨论】:

      【解决方案5】:

      我正在做同样的事情,这就是我所做的。

      我为姓名、地址、电子邮件和号码使用了单独的表,每个表都有一个 NameID 列,该列是除 Name 表之外的所有内容的外键,它是主聚集键。我使用 MainName 和 FirstName 而不是 LastName 和 FirstName 来允许业务条目和个人条目,但您可能不需要。

      NameID 列在所有表中都是一个 smallint,因为我相当确定我不会输入超过 32000 个条目。几乎所有其他内容都是 varchar(n),范围从 20 到 200,具体取决于您要存储的内容(生日、cmets、电子邮件、非常长的名称)。这实际上取决于您存储的内容类型。

      数字表是我偏离的地方。我将它设置为有五个列,分别标记为 NameID、Phone#、CountryCode、Extension 和 PhoneType。我已经讨论过 NameID。 Phone# 是 varchar(12),其检查约束如下所示: CHECK (Phone# like '[0-9][0-9][0-9]-[0-9][0-9][0 -9]-[0-9][0-9][0-9][0-9]')。这样可以确保只有我想要的内容才能进入数据库并且数据保持非常一致。我将扩展名和国家/地区代码称为可为空的 smallint,但如果您愿意,它们也可以是 varchar。 PhoneType 是 varchar(20) 并且不能为空。

      希望这会有所帮助!

      【讨论】:

        【解决方案6】:

        任何表 ID

        使用:INT(11)

        MySQL indexes 将能够以最快的速度解析 int 列表。

        任何安全性

        使用:BINARY(x),或BLOB(x)

        您可以将安全令牌等以十六进制形式直接存储在 BINARY(x) 或 BLOB(x) 中。要从 binary-type 检索,请使用 SELECT HEX(field)...SELECT ... WHERE field = UNHEX("ABCD....")

        任何日期

        使用:DATETIMEDATETIME

        如果您需要同时存储日期和时间(而不是一对字段),请始终使用 DATETIME,因为 DATETIME 索引更适合 MySQL 中的日期比较。

        任何真假

        使用:BIT(1)(仅限 MySQL 8。)否则,使用 BOOLEAN(1)

        BOOLEAN 实际上只是TINYINT(1) 的别名,它实际上存储了 0 到 255(不完全是真/假,是吗?)。

        任何你想调用 `SUM()`、`MAX()` 或类似函数的东西

        使用:INT(11)

        VARCHAR 或其他类型的字段不适用于SUM() 等函数。

        任何超过 1,000 个字符的内容

        使用:文本。

        最大限制为 65,535。

        超过 65,535 个字符

        使用:MEDIUMTEXT。

        最大限制为 16,777,215。

        超过 16,777,215 个字符

        使用:LONGTEXT。

        上限为 4,294,967,295。

        名字,姓氏

        使用:VARCHAR(255)

        UTF-8 字符每个可见字符可以占用三个字符,并且某些文化不区分名字和姓氏。此外,文化可能对哪个名字是first和哪个名字是last存在分歧。您应该将这些字段命名为 Person.GivenNamePerson.FamilyName

        电子邮件地址

        使用:VARCHAR(256)

        电子邮件路径的定义是在 1982 年的 RFC821 中设置的。电子邮件的最大限制是在 2001 年由 RFC2821 设置的,而这些限制在 2008 年由 RFC5321 保持不变。 (参见章节:4.5.3.1. 大小限制和最小值。)RFC3696,2004 年出版,错误地将电子邮件地址限制引用为320 字符,但这是一个“仅限信息”的 RFC,明确“没有定义任何标准” "根据它的介绍,所以忽略它。

        电话

        使用:VARCHAR(255)

        您永远不知道电话号码何时会以“1800...”、“1-800”或“1-(800)”的形式出现,或者它是否以“ext. 42”结尾,或“问苏珊”。

        邮政编码

        使用:VARCHAR(10)

        您将获得类似1234512345-6789 的数据。使用验证来清理此输入。

        网址

        使用:VARCHAR(2000)

        官方标准支持的 URL 比这长得多,但很少有现代浏览器支持超过 2,000 个字符的 URL。见this SO answer: What is the maximum length of a URL in different browsers?

        价格

        使用:DECIMAL(11,2)

        它上升到 11。

        【讨论】:

          猜你喜欢
          • 2011-02-28
          • 2012-09-21
          • 1970-01-01
          • 2010-10-27
          • 2021-01-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-21
          相关资源
          最近更新 更多