Mysql数据类型TINYINT(1)与BOOLEAN踩坑记

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: Mysql数据类型TINYINT(1)与BOOLEAN踩坑记 熟悉Mysql的同学应该都知道,Mysql查询的boolean结果将输出为0或者1.   比如: select 1=1;   其输出结果为1。

Mysql数据类型TINYINT(1)与BOOLEAN踩坑记

熟悉Mysql的同学应该都知道,Mysql查询的boolean结果将输出为0或者1.

  比如:

select 1=1;

  其输出结果为1。

  查阅mysql官方文档仅找到如下描述:

11.10 Using Data Types from Other Database Engines

To facilitate the use of code written for SQL implementations from other vendors, MySQL maps data types as shown in the following table. These mappings make it easier to import table definitions from other database systems into MySQL.

Other Vendor Type MySQL Type
BOOL TINYINT
BOOLEAN TINYINT
CHARACTER VARYING(M) VARCHAR(M)
FIXED DECIMAL
FLOAT4 FLOAT
FLOAT8 DOUBLE
INT1 TINYINT
INT2 SMALLINT
INT3 MEDIUMINT
INT4 INT
INT8 BIGINT
LONG VARBINARY MEDIUMBLOB
LONG VARCHAR MEDIUMTEXT
LONG MEDIUMTEXT
MIDDLEINT MEDIUMINT
NUMERIC DECIMAL
Other Vendor Type MySQL Type

Data type mapping occurs at table creation time, after which the original type specifications are discarded. If you create a table with types used by other vendors and then issue a DESCRIBE tbl_name statement, MySQL reports the table structure using the equivalent MySQL types. For example:

 
mysql> CREATE TABLE t (a BOOL, b FLOAT8, c LONG VARCHAR, d NUMERIC); Query OK, 0 rows affected (0.00 sec) mysql> DESCRIBE t; +-------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------------+------+-----+---------+-------+ | a | tinyint(1) | YES | | NULL | | | b | double | YES | | NULL | | | c | mediumtext | YES | | NULL | | | d | decimal(10,0) | YES | | NULL | | +-------+---------------+------+-----+---------+-------+ 4 rows in set (0.01 sec)

  我想说的是,今天使用一套中间件对kafka消息进行解析为mysql 语句,其中遇到如下的问题,

  1. 目标表有一字段设置类型为:tinyint(1)。
  2. 源表同步消息中接收到相同类型的数据。
  3. 其中中间件中有如下解析部分:
    复制代码
    public void setStatement(PreparedStatement statement, DatabaseType databaseType, boolean timestampChangeToLong) throws SQLException {
            if (this.value == null) {
                statement.setNull(this.index, this.sqlType);
            } else {
                switch(this.sqlType) {
                case -15:
                case -9:
                case 1:
                case 12:
                case 2005:
                    String strVal = String.valueOf(this.value);
                    statement.setString(this.index, strVal);
                    break;
                case -7:
                case 16:
                    boolean booleanVal = (Boolean)this.value; //tinyint(1) 类型的表设计字段直接进入该case,由于接收到的消息中的数据未0或者1,直接在该未知报类转换异常。
                    statement.setBoolean(this.index, booleanVal);
                    break;
                case -6:
                    int val2 = (Integer)this.value;
                    statement.setInt(this.index, val2);
                    break;
                case -5:
                    long longVal = (Long)this.value;
                    statement.setLong(this.index, longVal);
                    break;
                case 2:
                    this.setStatementDataTypeNumeric(statement);
                    break;
                case 3:
                    this.setStatementDataTypeDecimal(statement, databaseType, timestampChangeToLong);
                    break;
                case 4:
                    int val = (Integer)this.value;
                    statement.setInt(this.index, val);
                    break;
                case 5:
                    int val1 = (Integer)this.value;
                    statement.setInt(this.index, val1);
                    break;
                case 6:
                    float floatVal = (Float)this.value;
                    statement.setFloat(this.index, floatVal);
                    break;
                case 8:
                    double doubelVal = (Double)this.value;
                    statement.setDouble(this.index, doubelVal);
                    break;
                case 91:
                    this.setStatementDataTypeDate(statement, databaseType);
                    break;
                case 92:
                    Date timeVal = (Date)this.value;
                    Time sqlTime = new Time(timeVal.getTime());
                    statement.setTime(this.index, sqlTime);
                    break;
                case 93:
                    this.setStatementDataTypeTimestamp(statement, timestampChangeToLong);
                    break;
                default:
                    throw new ConsumeException("sqlType " + this.sqlType + " is not support");
                }
    
            }
        }
    复制代码

     

  4. 怎样获取的数字类型呢,代码如下:
    复制代码
    protected Database loadInternal(String database) {
            Connection connection = null;
    
            Database var28;
            try {
                connection = this.dataSource.getConnection();//获取连接
                DatabaseMetaData metaData = connection.getMetaData();//获取元数据
                String catalog = null;
                String[] tableTypes = new String[]{"TABLE"};
                String databasePattern = this.databaseSchema != null ? this.databaseSchema : database;
                ResultSet tablesResultSet = metaData.getTables((String)catalog, databasePattern, "%", tableTypes);
                Database db = new Database();
                db.setName(database);
    
                Table tablei;
                while(tablesResultSet.next()) {
                    String tableName = tablesResultSet.getString("TABLE_NAME");
                    tablei = new Table(tableName);
                    db.addTable(tablei);
                }
    
                Iterator var27 = db.getTables().iterator();
    
                while(var27.hasNext()) {
                    tablei = (Table)var27.next();
                    ResultSet columnsResultSet = metaData.getColumns((String)catalog, databasePattern, tablei.getName(), (String)null);
    
                    while(columnsResultSet.next()) {
                        String columnName = columnsResultSet.getString("COLUMN_NAME");
                        int sqlType = columnsResultSet.getInt("DATA_TYPE");//此处拿到mysql返回的字段类型
                        String typeName = columnsResultSet.getString("TYPE_NAME");
                        int size = columnsResultSet.getInt("COLUMN_SIZE");
                        boolean nullable = 1 == columnsResultSet.getInt("NULLABLE");
                        Column column = new Column();
                        column.setName(columnName);
                        column.setNullable(nullable);
                        column.setSqlType(sqlType);
                        column.setTypeName(typeName);
                        column.setSize(size);
                        tablei.addColumn(column);
                    }
                }
    
                var28 = db;
            } catch (Exception var25) {
                throw new RuntimeException("load schema exception", var25);
            } finally {
                if (connection != null) {
                    try {
                        connection.close();
                    } catch (SQLException var24) {
                        ;
                    }
                }
    
            }
    
            return var28;
        }
    复制代码

     

  5. 也就是说,字段tinyint(1)被当做boolean类型进行了返回。导致java中Integer类型无法进行强转。

  解决方法:alter talbe change `xxx` `xxx` tinyint(4) ...;即可。修改tinyint数据类型长度,mysql也就不再当做boolean类型进行返回了。

  总结:Mysql表结构设计时,要避免设计为tinyint(1)这种类型,以免与boolean类型数据结构进行混淆。引起不必要bug。当然也可以总java代码中进行修改,修改后的影响,还需另外评估。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
关系型数据库 MySQL 数据库
MySQL数据库基础(数据库操作,常用数据类型,表的操作)
MySQL数据库基础(数据库操作,常用数据类型,表的操作)
34 5
|
5月前
|
存储 关系型数据库 MySQL
MySQL数据库的数据类型、语法和高级查询
MySQL数据库的数据类型、语法和高级查询
70 0
|
1月前
|
存储 关系型数据库 MySQL
MySQL支持多种数据类型
MySQL支持多种数据类型
99 3
|
1月前
|
存储 关系型数据库 MySQL
什么是mysql的数据类型?
什么是mysql的数据类型?
47 2
|
1月前
|
存储 关系型数据库 MySQL
MySQL数据类型
MySQL数据类型
52 2
|
3月前
|
关系型数据库 MySQL Linux
数据类型和运算符(MySQL服务器的安装,MySQL客户端,数据类型,运算符,MySQL的语法规范)
无论是对于初学者还是有经验的开发者,了解MySQL的安装、客户端使用、数据类型、运算符和语法规范都是至关重要的。这不仅有助于高效地管理和查询数据,而且对于设计和实现数据库解决方案来说是基础工作。通过深入学习和实践这些知识,您可以更好地发挥MySQL数据库的强大功能。
32 2
|
3月前
|
存储 关系型数据库 MySQL
MySQL 中的 BLOB 数据类型深入解析
【8月更文挑战第31天】
429 0
|
3月前
|
存储 关系型数据库 MySQL
|
3月前
|
存储 XML 关系型数据库
深入理解MySQL中的BLOB和TEXT数据类型
【8月更文挑战第31天】
563 0
|
3月前
|
SQL 关系型数据库 MySQL
SQL Server、MySQL、PostgreSQL:主流数据库SQL语法异同比较——深入探讨数据类型、分页查询、表创建与数据插入、函数和索引等关键语法差异,为跨数据库开发提供实用指导
【8月更文挑战第31天】SQL Server、MySQL和PostgreSQL是当今最流行的关系型数据库管理系统,均使用SQL作为查询语言,但在语法和功能实现上存在差异。本文将比较它们在数据类型、分页查询、创建和插入数据以及函数和索引等方面的异同,帮助开发者更好地理解和使用这些数据库。尽管它们共用SQL语言,但每个系统都有独特的语法规则,了解这些差异有助于提升开发效率和项目成功率。
363 0