【问题标题】:Best datatype to store a long number made of 0 and 1存储由 0 和 1 组成的长数字的最佳数据类型
【发布时间】:2016-05-06 08:43:19
【问题描述】:

我想知道存储这些的最佳数据类型是什么:

  • null
  • 0
  • /* the length of other numbers is always 7 digits */
  • 0000000
  • 0000001
  • 0000010
  • 0000011
  • /* and so on */
  • 1111111

我已经测试过,INT 也可以。但是有一个更好的数据类型。因为我所有的号码都是由01 数字组成的。有没有更好的数据类型?

【问题讨论】:

  • 二进制呢?例如整数字段?使一个 int 字段可以为空并存储为二进制(而不是您拥有的实际数字)并且您被排序......当然除非您确实需要它作为字符串。您可以使用非常小的数据类型,因为看起来您只需要 7 个字节
  • @Charleh “作为字符串” 是什么意思?我想通过像这样的 Trigger 使用它 IF ( SUBSTR(col, 1, 1) = 1) THEN ...col 包含该二进制数。你也可以写一个答案吗?
  • “更好的数据类型”是什么意思?您需要指定您想要达到的目标,以便任何人提出更好的数据类型。
  • @stack 如果您将 010001 存储在 INT 中,您将丢失前导 0,因为 010001 相当于 10001(除非您将其存储为二进制值)。如果您想对该值执行SUBSTR(),则需要将其存储为字符串。或者,您可以存储为字节/数字并使用位掩码在某些位位置检索 0/1。这是简单的二进制:0 = 010 = 2010001 = 17。然后,您只需使用位掩码检查来查看是否设置了任何特定位...例如IF 8 & bitfield = 8 THEN ...。查看加里答案中的链接。
  • @Charleh 好的,根据您的解释,我想将其存储为字符串。因为我需要这个01 ≠ 1。请写出答案。

标签: mysql sql sqldatatypes


【解决方案1】:

你显示的是二进制数

  • 0000000 = 0
  • 0000001 = 2^0 = 1
  • 0000010 = 2^1 = 2
  • 0000011 = 2^0 + 2^1 = 3

因此,只需将这些数字存储在整数数据类型中(当然,它内部存储有位)。您可以为此使用 BIGINT,如按位运算 (http://dev.mysql.com/doc/refman/5.7/en/bit-functions.html) 文档中的建议。

这里是如何设置标志n:

UPDATE mytable
SET bitmask = POW(2, n-1)
WHERE id = 12345;

添加标志的方法如下:

UPDATE mytable
SET bitmask = bitmask | POW(2, n-1)
WHERE id = 12345;

这是检查标志的方法:

SELECT *
FROM mytable
WHERE bitmask & POW(2, n-1)

但正如 cmets 中所述:在关系数据库中,您通常使用列和表来显示属性和关系,而不是编码的标志列表。

【讨论】:

  • TINYINT UNSIGNED 可以容纳8位; SMALLINT UNSIGNED 可以容纳 16 位等。
  • 不要使用POW(n-1),而是使用1 << n
  • 011 不应该等同时,不确定这是如何被接受的答案......不是你的错,只是混淆......!
  • @Charleh:是 OP 感到困惑。如此执着于使用substr(col, n, 1),'01' 和 '1' 的含义并不相同。我们都花了一些时间进一步询问以了解整个情况,直到请求突然改变,所有字符串都是七位数长。 (我仍然希望我的回答真的被接受了,因为我建议在我的最后一句话中重新考虑整个事情:-)
  • 感谢您的评论,这更有意义,通常“您要做什么”这个问题比尝试回答原始问题要好:)
【解决方案2】:

正如您在评论中所说,值 011 不应被视为等效(排除它们所在的二进制文件),因此您可以将其存储为字符串。

它实际上可能比存储为字节 + 偏移量更有效,因为这将占用 9 个字符,而您最多需要 7 个字符

只需存储为 varchar(7) 或 MySql 中的任何等价物。无需太聪明,尤其是当您对提取位置值感兴趣时。

不要忘记记住,这比存储为 bit(7) 占用更多的存储空间,因为您实际上存储了 7 个字节(或者任何存储单元用于 varchar 中的每个精度级别) ,而不是 7 位。

如果这不是问题,则无需过度设计。

【讨论】:

    【解决方案3】:

    您可以将二进制数转换为字符串,并附加一个字节来指定前导零的数量。

    示例 - 010 的表示:

    • 十六进制数值为0x02
    • 有一个前导零,所以第一个字节是0x01
    • 结果字符串为0x01,0x02

    用同样的方法,1010010应该表示为0x00,0x52

    在我看来效率很高。

    【讨论】:

    • 如何在 MySQL 中进行转换?
    • 在你的服务器中进行转换,然后将结果存入sql
    【解决方案4】:

    不确定它是否是最好的数据类型,但您可能想尝试一下 BIT: MySQL, PostgreSQL

    MySQL中还有一些有用的位函数。

    【讨论】:

    • 谢谢。正如我在 cmets 中提到的,我必须为该数字使用 SUBSTR() 函数。你仍然认为我必须使用 BIT 吗?
    • 你不能使用这个方法,因为你已经说过 011 不应该被视为相等,当它们在二进制时是相等的。
    • 您可以维护另一个int 字段来存储长度,但我认为字符串将是您使用的更好选择,您的代码将更容易维护。
    猜你喜欢
    • 1970-01-01
    • 2011-10-09
    • 1970-01-01
    • 2021-01-12
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 2014-09-12
    • 2019-01-06
    相关资源
    最近更新 更多