数据库中将数字类型存储成字符型有哪些坏处?

2024-02-29 22:32

本文主要是介绍数据库中将数字类型存储成字符型有哪些坏处?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    工作中经常见到一些设计粗糙的数据库,其中将数字类型的字段定义和存储成字符型是一种比较常见的情况。部分开发同学或者非数据库岗位很多为了图方便,往往又不在意这些细节,除非等到出现可见的或者一些不可见的问题时才会去研究隐藏其后的真相。所以,这里简单总结一下,在数据库系统中,将数字类型存储成字符类型会有哪些不好的地方。以关系型数据库MySQL示例。

    ①字符类型往往比数字类型占用更多的存储

    首先,字符类型往往占用更多的存储,但非总是占用更多的存储。MySQL以固定长度存储数字类型:TINYINT、SMALLINT、MEDIUMINT、INT和BIGINT分别占用1、2、3、4和8个Byte存储。所以,就“1024”这个数值,如果以BIGINT、CHAR(4)和VARCHAR存储,不考虑其他,分别需要8、4和5个Byte存储(VARCHAR类型以是否存储了超过255个字符为界限分别需要额外1个或者2个Byte来记录存储长度)。但实际使用中,我们遇到的数字类型,其值域或者说取值空间是很宽大的,或者刚好可以放入一个较小的数字类型定义中。绝大多数情况下,总是可以通过选用数字类型从而节省存储空间。文件型数据库,数据最终是存储在磁盘上的文件,当需要对其查询时再读取到内存中。所以,更少的存储空间消耗与更高的查询性能是直接相关的。

    ②数字类型存储成字符类型可能使索引失效

    字段间进行比较时,如果字段类型不一致,在查询之前需要类型转换,否则无法直接进行比较。因为额外的类型转换操作,使得字段上的索引不可用。因此,将数字类型存储成字符类型,并且为其定义了索引,当其与其他数字类型字段关联查询时,该索引就失效了。

    ③数字类型存储成字符类型可能使部分SQL函数和命令失效

    数字的计算比较是作为一个整体在CPU中进行的。当数字类型存储成字符型时,会受到编码和排序规则影响;对字符型的查询是从左往右一个字符一个字符依次进行的,即最左前缀匹配。因此,将字符型数字直接传入部分函数或命令会使结果失真。

    首先创建两张示例表,插入相同的数据,但数据类型定义不一致。

CREATE TABLE `i` (`i` INT(11) NULL DEFAULT NULL
)
;
INSERT INTO `i` (`i`) VALUES (4);
INSERT INTO `i` (`i`) VALUES (8);
INSERT INTO `i` (`i`) VALUES (11);
INSERT INTO `i` (`i`) VALUES (23);
INSERT INTO `i` (`i`) VALUES (1024);
INSERT INTO `i` (`i`) VALUES (2147483647);
CREATE TABLE `s` (`s` VARCHAR(50) NULL DEFAULT NULL
)
;
INSERT INTO `s` (`s`) VALUES ('4');
INSERT INTO `s` (`s`) VALUES ('8');
INSERT INTO `s` (`s`) VALUES ('11');
INSERT INTO `s` (`s`) VALUES ('23');
INSERT INTO `s` (`s`) VALUES ('1024');
INSERT INTO `s` (`s`) VALUES ('2147483647');

    数字类型存储成字符型使得SQL查询结果失真。

mysql> SELECT MAX(i.i) FROM i;
+------------+
| MAX(i.i)   |
+------------+
| 2147483647 |
+------------+
1 row in set (0.00 sec)mysql> SELECT MAX(s.s) FROM s;
+----------+
| MAX(s.s) |
+----------+
| 8        |
+----------+
1 row in set (0.00 sec)
mysql> SELECT i.i FROM i ORDER BY i.i;
+------------+
| i          |
+------------+
|          4 |
|          8 |
|         11 |
|         23 |
|       1024 |
| 2147483647 |
+------------+
6 rows in set (0.00 sec)mysql> SELECT s.s FROM s ORDER BY s.s;
+------------+
| s          |
+------------+
| 1024       |
| 11         |
| 2147483647 |
| 23         |
| 4          |
| 8          |
+------------+
6 rows in set (0.00 sec)

    为了得到预想的数值结果,必须额外进行一次数据类型转换操作,包括隐式转换和显式转换两种方式。隐式转换是进行一个简单的不改变数值大小的数学计算;显式转换是借助CAST或者CONVERT函数。隐式操作在开发维护工作中往往就是出问题的根源,所以如果真的到了需要进行类型转换的时候,建议使用标准SQL规范的CAST。

mysql> SELECT MAX(s.s + 0) FROM s;
+--------------+
| MAX(s.s + 0) |
+--------------+
|   2147483647 |
+--------------+
1 row in set (0.01 sec)mysql> SELECT MAX(CAST(s.s AS DECIMAL)) FROM s;
+---------------------------+
| MAX(CAST(s.s AS DECIMAL)) |
+---------------------------+
|                2147483647 |
+---------------------------+
1 row in set (0.00 sec)

 

 

    参考:

https://dev.mysql.com/doc/refman/5.7/en/mysql-indexes.html

https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_max

https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_cast

这篇关于数据库中将数字类型存储成字符型有哪些坏处?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/760316

相关文章

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

Python实现特殊字符判断并去掉非字母和数字的特殊字符

《Python实现特殊字符判断并去掉非字母和数字的特殊字符》在Python中,可以通过多种方法来判断字符串中是否包含非字母、数字的特殊字符,并将这些特殊字符去掉,本文为大家整理了一些常用的,希望对大家... 目录1. 使用正则表达式判断字符串中是否包含特殊字符去掉字符串中的特殊字符2. 使用 str.isa

数据库面试必备之MySQL中的乐观锁与悲观锁

《数据库面试必备之MySQL中的乐观锁与悲观锁》:本文主要介绍数据库面试必备之MySQL中乐观锁与悲观锁的相关资料,乐观锁适用于读多写少的场景,通过版本号检查避免冲突,而悲观锁适用于写多读少且对数... 目录一、引言二、乐观锁(一)原理(二)应用场景(三)示例代码三、悲观锁(一)原理(二)应用场景(三)示例

Node.js 数据库 CRUD 项目示例详解(完美解决方案)

《Node.js数据库CRUD项目示例详解(完美解决方案)》:本文主要介绍Node.js数据库CRUD项目示例详解(完美解决方案),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考... 目录项目结构1. 初始化项目2. 配置数据库连接 (config/db.js)3. 创建模型 (models/

MySQL 中查询 VARCHAR 类型 JSON 数据的问题记录

《MySQL中查询VARCHAR类型JSON数据的问题记录》在数据库设计中,有时我们会将JSON数据存储在VARCHAR或TEXT类型字段中,本文将详细介绍如何在MySQL中有效查询存储为V... 目录一、问题背景二、mysql jsON 函数2.1 常用 JSON 函数三、查询示例3.1 基本查询3.2

Pydantic中Optional 和Union类型的使用

《Pydantic中Optional和Union类型的使用》本文主要介绍了Pydantic中Optional和Union类型的使用,这两者在处理可选字段和多类型字段时尤为重要,文中通过示例代码介绍的... 目录简介Optional 类型Union 类型Optional 和 Union 的组合总结简介Pyd

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

Ubuntu中远程连接Mysql数据库的详细图文教程

《Ubuntu中远程连接Mysql数据库的详细图文教程》Ubuntu是一个以桌面应用为主的Linux发行版操作系统,这篇文章主要为大家详细介绍了Ubuntu中远程连接Mysql数据库的详细图文教程,有... 目录1、版本2、检查有没有mysql2.1 查询是否安装了Mysql包2.2 查看Mysql版本2.

Oracle数据库常见字段类型大全以及超详细解析

《Oracle数据库常见字段类型大全以及超详细解析》在Oracle数据库中查询特定表的字段个数通常需要使用SQL语句来完成,:本文主要介绍Oracle数据库常见字段类型大全以及超详细解析,文中通过... 目录前言一、字符类型(Character)1、CHAR:定长字符数据类型2、VARCHAR2:变长字符数

Win11安装PostgreSQL数据库的两种方式详细步骤

《Win11安装PostgreSQL数据库的两种方式详细步骤》PostgreSQL是备受业界青睐的关系型数据库,尤其是在地理空间和移动领域,:本文主要介绍Win11安装PostgreSQL数据库的... 目录一、exe文件安装 (推荐)下载安装包1. 选择操作系统2. 跳转到EDB(PostgreSQL 的