【问题标题】:Why does TINYINT(1) function as a boolean but INT(1) does not?为什么 TINYINT(1) 用作布尔值,而 INT(1) 没有?
【发布时间】:2013-05-23 19:40:02
【问题描述】:

为什么TINYINT(1) 用作布尔值?我理解官方文档的方式,(1)应该意味着它的显示宽度为1,所以如果我在其中存储56,我认为它应该打印5。但由于某种原因,它总是打印10

另一种情况是,如果我将56 存储在INT(1) 中,那么它会打印56(至少根据SQLFiddle)。这是怎么回事?

【问题讨论】:

标签: mysql sql database sqlite phpmyadmin


【解决方案1】:

这是一个mysql Jdbc配置主题。

您可以通过将 jdbc url 配置属性“tinyInt1isBit”设置为“true”(默认)或“false”来配置 mysql jdbc 以将 TinyInt(1) 转换为 Boolean 或 Integer。

来自:https://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html

驱动程序是否应该将数据类型 TINYINT(1) 视为 BIT 类型(因为服务器在创建表时会静默转换 BIT -> TINYINT(1))?

默认值:真

【讨论】:

    【解决方案2】:

    TINYINT 列可以存储从-128127 的数字。

    TINYINT(1) 有点奇怪。它是(可能是因为它应该充当BOOLEAN 数据类型),在某些情况下只返回01,而它仍然保留存储的(-128 到 127)值。

    更正:我只在 SQL-Fiddle 中看到这种奇怪的行为,而不是在本地访问 MySQL 时,所以它很可能是 SQL-Fiddle 的怪癖,可能与 BOOLEAN 的等效性有关)而不是 MySQL 问题。

    SQL-Fiddle

    CREATE TABLE test
    ( i TINYINT(1)
    ) ;
    
    INSERT INTO test 
      (i)
    VALUES
      (0),  (1), (6), (120), (-1) ;
    

    我们得到的地方(仅在 SQL-Fiddle 中,否则如果我们访问 MySQL,则不会!):

    SELECT i
    FROM test ;
    
      i
    -----
      0
      1
      1
      1
      1
    

    但是:

    SELECT CAST(i AS SIGNED) i2
    FROM test ;
    
      i2
    -----
       0
       1
       6
     120
      -1
    

    【讨论】:

    • 您知道的任何地方都记录了这一点吗?当前关于 BOOL、TINYINT([M]) 和 anyINT([M]) 的文档非常强烈地暗示了 OP 预期的行为。
    • 我在 SQLfiddle 上看到这可行,但我无法在我的 MySQL 5.5.31 实例上重现它。你知道让 tinyint(1) 以这种方式表现需要什么吗?也许是 SQL 模式?
    • @pilcrow,BillKarwin:真的不知道。也许这是 SQL-Fiddle 而不是 MySQL 的古怪之处。
    【解决方案3】:

    MySQL 整数类型的括号中的 (1) 与数据类型接受的值范围或存储方式无关。它只是为了展示。

    另请参阅我对Types in MySQL: BigInt(20) vs Int(20) etc 的回复。

    TINYINT 与 TINYINT(1) 或 TINYINT(2) 或 TINYINT(64) 没有区别。它是一个 8 位有符号整数数据类型,它接受从 -128 到 127 的任何 8 位整数值。

    mysql> create table b (i tinyint(1));
    
    mysql> insert into b values (42);
    
    mysql> select * from b;
    +------+
    | i    |
    +------+
    |   42 |
    +------+
    

    为方便起见,MySQL 支持 BOOL 的别名,该别名立即被 TINYINT(1) 替换。

    mysql> create table b2 (i bool);
    
    mysql> show create table b2;
    
    CREATE TABLE `b2` (
      `i` tinyint(1) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1
    

    正如我所说,使用 (1) 几乎没有任何意义,它只是一种约定,因此如果您看到 TINYINT(1),则可以合理地假设该列 打算 用作布尔值。但是 MySQL 中没有任何东西可以阻止您在其中存储其他整数值。

    如果您希望一列只接受 0 或 1,则可以使用 BIT(1):

    mysql> create table b3 (i bit(1));
    
    mysql> insert into b3 values (0), (1);
    Query OK, 2 rows affected (0.00 sec)
    Records: 2  Duplicates: 0  Warnings: 0
    
    mysql> insert into b3 values (-1);
    ERROR 1406 (22001): Data too long for column 'i' at row 1
    
    mysql> insert into b3 values (2);
    ERROR 1406 (22001): Data too long for column 'i' at row 1
    

    与 TINYINT 相比,这并没有节省任何空间,因为给定列的存储会向上舍入到最接近的字节。

    PS:尽管来自@samdy1 的回答,TINYINT 根本不存储 字符串 '0''1',它存储 整数 01 ,以及从-128到127的其他整数。在SQL中不需要引用整数,我经常不明白为什么这么多开发人员这样做。

    【讨论】:

    • 这是什么版本的 MySQL?这不是 OP、本问答中其他地方链接的 SQLfiddle 或 ypercube 的回答所报告的行为......
    • 这些代码示例是从在 MySQL 5.5.31 上运行时复制而来的。其实就是 Percona Server,但是 Percona Server 在数据类型处理上没有区别。
    • 我的本地实例(MySQL 5.5,而不是 Percona)同意您的发现。我在您的行中写了一个答案,然后进行了测试,并且对 Fiddle 中的这些结果感到非常惊讶。
    • JakeFeasel 已回复(the Heap)这与 JBDC 有关。
    • 好的,我刚刚测试了 MySQL Connector/J 5.1.22,它在 INSERT 或 SELECT 上进行任何此类布尔转换。我不知道 Jake 使用的是什么 JDBC 驱动程序。
    【解决方案4】:

    引擎足够聪明,知道TINYINT(1)BOOL 是相同的。然而INT(1) 只影响显示宽度而不是底层存储大小。仅当值小于显示宽度时,显示宽度才起作用。然后它被填充。

    http://alexander.kirk.at/2007/08/24/what-does-size-in-intsize-of-mysql-mean/

    【讨论】:

      【解决方案5】:

      据我了解,TINYINT(1) 只能持有'0''1'(根据自己的经验)。
      因此,可以假设'0''1' 被翻译成truefalse

      【讨论】:

      • 不完全是:sqlfiddle.com/#!2/0dc1d/5 只显示为 1,实际上并不存储 1。
      • 哦,好的,它仍然返回true吗?
      • 嗯,这有点令人困惑,问题是它不会返回 false (0),任何不是 false (0) 的东西都算作 true,但不一定等于 true (1 )。 sqlfiddle.com/#!2/0dc1d/11。见the docs,里面的例子是相关的。
      猜你喜欢
      • 2012-01-30
      • 1970-01-01
      • 2011-11-25
      • 2022-08-05
      • 1970-01-01
      • 2011-04-14
      • 2021-12-29
      • 1970-01-01
      • 2011-01-02
      相关资源
      最近更新 更多