[MySQL初阶]MySQL(2)数据类型精讲静态类型和动态类型的对比
标题:[MySQL初阶]MySQL(2)数据类型精讲&&静态类型和动态类型的对比
@水墨不写bug
文章目录
- (一)动态和静态数据类型的对比
- 1.1内存管理与效率优化
- 1.2类型安全与错误预防
- 1.3代码可读性与维护性
- (二)MySQL的数据类型
- MySQL数据类型全面讲解
- 一、数值类型
- 1. **BIT(M)**
- 2. **TINYINT [UNSIGNED]**
- 3. **BOOL**
- 4. **SMALLINT/INT/BIGINT [UNSIGNED]**
- 5. **FLOAT/DOUBLE [UNSIGNED]**
- 6. **DECIMAL(M,D)**
- 二、文本与二进制类型
- 1. **CHAR(size)**
- 2. **VARCHAR(size)**
- 3. **BLOB/TEXT**
- 三、时间日期类型
- 1. **DATE**
- 2. **DATETIME**
- 3. **TIMESTAMP**
- 四、特殊字符串类型
- 1. **ENUM**
- 2. **SET**
- 五、选择建议
(一)动态和静态数据类型的对比
与C/C++类似,MySQL也有数据类型的区分,数据类型的意义在于:
- 内存管理与效率优化
- 类型安全与错误预防
- 代码可读性与维护性
这些都是MySQL拥有静态类型的优势所在,然而近几年大火的python有动态类型的语法,
这里需要澄清几个重要的概念:
显式/隐式数据类型;
动态/静态数据类型;
显式类型声明:
开发者手动标注变量、函数参数或返回值的类型。例如:
int x = 10; // C/C++ 显式声明
def add(a: int, b: int) -> int: ... # Python 类型提示(可选)
隐式类型声明:
类型由编译器或解释器自动推断,无需手动标注。例如:
x = 10 # Python 隐式推断为 int
let y = "hello"; // Rust 类型推断为 &str
var z = 3.14; // Go 推断为 float64
静态类型系统:
类型检查在编译阶段完成,类型在程序运行前已确定且不可变。
典型语言:C/C++、Java、Go、Rust、Haskell。
int x = 10;
x = "hello"; // 编译报错:类型不匹配
动态类型系统:
类型检查在运行时进行,变量的类型可以动态改变。
典型语言:Python、JavaScript、Ruby、PHP。
x = 10
x = "hello" # 合法:x 的类型从 int 变为 str
而python作为以简单易学的语言,最著名的就是其隐式类型(不需要类型声明)和动态类型(运行时变量的类型可以动态改变).
所以我们接下来的讨论认为是 以C/C++为代表的静态类型显式类型声明 的语言 与以python为代表的动态隐式类型为代表 的语言之间的比较!!
1.1内存管理与效率优化
显式类型(C/C++、MySQL):
数据类型明确告知系统需要分配多少内存。例如:
-
C++中int固定占4字节,double占8字节,编译器直接生成操作这些内存的指令,无需运行时解析。
-
MySQL中VARCHAR(255)会预先分配最大长度空间,而INT直接存储为4字节整数,避免冗余。
隐式类型(Python):
Python变量本质是对象的引用(如a=5实际指向一个动态创建的int对象),类型信息存储在对象中。虽然灵活,但每次操作需动态解析类型,效率较低。
- 显式类型减少内存浪费,提升运行效率;
- 隐式类型牺牲效率换取编码灵活性。
1.2类型安全与错误预防
显式类型:
编译器或数据库引擎会在编译/写入阶段检查类型合法性。例如:
- C++中int a = “hello”;直接编译失败。
- MySQL插入字符串到INT列会报错,避免脏数据。
隐式类型:
Python中a = “5”; b = a + 2直到运行时才会抛出TypeError,需依赖测试覆盖潜在错误.
- 显式类型在早期拦截错误,提升代码健壮性;
- 隐式类型需开发者自行保证类型逻辑正确。
1.3代码可读性与维护性
显式类型(如C++函数签名):
int add(int a, int b) { return a + b; } // 明确要求输入输出为整数
开发者一眼可知参数类型,无需猜测。
隐式类型(Python):
def add(a, b): return a + b # 需文档或注释说明a/b应为int/float
若未写文档,调用者可能误传字符串导致意外行为。
- 显式类型充当文档,降低协作成本;
- 隐式类型需额外文档或类型提示(Type Hints)弥补。
以上是对语言中数据类型的讨论.
(二)MySQL的数据类型
MySQL的数据类型的分类如下:
MySQL数据类型全面讲解
一、数值类型
数值类型用于存储整数、小数和位值,分为以下几类:
1. BIT(M)
- 定义:位类型,存储二进制数据。
- 范围:
M
表示位数(1-64),最多可表示64比特位,默认M=1
。 - 示例:
CREATE TABLE sensor_data ( id INT, status BIT(8) -- 存储8位二进制数据,如 b'10101010' );
如果想要查看bit的内容,仅仅使用
select * from tb_name;
这种显示方式,会把bit(M)中的数字按照ASCII显示,如果想要看到数字对应的字符,需要:
select hex(bits) from tb_name;
这样才能成功显示数字字符。
2. TINYINT [UNSIGNED]
- 定义:小整数,带符号范围
-128~127
,无符号范围0~255
。 - 示例:
CREATE TABLE user_age ( user_id INT, age TINYINT UNSIGNED -- 存储年龄(0~255) );
3. BOOL
- 定义:布尔类型,实际是
TINYINT(1)
的别名,0
表示假,1
表示真。 - 示例:
CREATE TABLE task_list ( task_id INT, is_completed BOOL -- 0(未完成)或 1(完成) );
4. SMALLINT/INT/BIGINT [UNSIGNED]
- 范围:
SMALLINT
:带符号-32768~32767
,无符号0~65535
。INT
:带符号-2^31~2^31-1
,无符号0~2^32-1
。BIGINT
:带符号-2^63~2^63-1
,无符号0~2^64-1
。
- 示例:
CREATE TABLE product ( product_id BIGINT UNSIGNED, -- 超大ID范围 stock INT UNSIGNED -- 库存量(0~42亿) );
整形总结:int有多种类型,若insert超出范围的越界值,则mysql会直接拦截报错,这与C、C++不同;反之,一个数据,如果成功被插入到mysql中,数据插入本身一定是合法的。
因此:mysql中,数据类型本身就是一种约束。
5. FLOAT/DOUBLE [UNSIGNED]
- 定义:浮点数,
FLOAT
占4字节,DOUBLE
占8字节。 - 使用:float/double(M,N)表示显示数字总共占有M位,其中小数部分占有N位。
- 注意:存在精度丢失问题,如
0.1 + 0.2 ≠ 0.3
。 unsigned直接截断负数部分。
插入时,整数多余则超范围报错;小数多余部分则4舍5入插入,4舍5入后的结果超范围也报错插入失败。
- 示例:
CREATE TABLE scientific_data ( temperature FLOAT(4,2), -- 表示[-99.99,99.99]范围的浮点数 distance DOUBLE(5,3) unsigned -- 表示[0,99.999]范围的浮点数 );
6. DECIMAL(M,D)
- 定义:精确小数,
M
是总位数,最大65,默认不填则为10,D
是小数位数,最大30,默认为0。 - 适用场景:金融金额等需要精确计算的场景。
- 示例:
CREATE TABLE account ( user_id INT, balance DECIMAL(10,2) -- 如 12345678.99 );
二、文本与二进制类型
1. CHAR(size)
- 定义:定长字符串,长度不足时用空格填充,size最大
255
。 - 适用场景:长度固定的数据(如 MD5 哈希值)。
- 示例:
CREATE TABLE country ( code CHAR(2), -- 如 'CN', 'US' name VARCHAR(50) );
在mysql中,char(2)可存储“中国”两个汉字。这可能与以往我们的认识不同。 在utf8中,汉字占有三个字节,C、C++中,汉字占有3字节。
2. VARCHAR(size)
- 定义:变长字符串,最大
65535
字节(实际受行大小限制)。 - 适用场景:长度不固定的文本(如用户名、地址)。
- 示例:
CREATE TABLE user_profile ( username VARCHAR(30), -- 如 'john_doe' bio VARCHAR(500) );
varchar通常会空出来1-3个字节来存储长度数据。varchar的字节数是0-65535,如果用其存储汉字,总长度减去3个(数据长度字节)等于65532,65532/3 = 21844,varchar在utf8编码下,最多可以存储21844个汉字。
varchar和char的比较
-
char和varchar都可以指定最大长度;
-
varchar实际用多少,就占用多少内存,但是不能超过最大长度;char不论用不用,都占用指定的最大长度的内存。
-
char长度固定,占用内存固定;varchar长度不固定,需要额外的内存存储长度,占用内粗随存入数据变化。
3. BLOB/TEXT
- 区别:
BLOB
:存储二进制数据(如图片、文件)。TEXT
:存储大文本(如文章内容),不支持默认值。
- 示例:
CREATE TABLE document ( id INT, content TEXT, -- 长文本 attachment BLOB -- PDF文件二进制数据 );
三、时间日期类型
1. DATE
- 格式:
YYYY-MM-DD
,如2023-10-01
。 - 大小:3字节
- 示例:
CREATE TABLE event ( event_date DATE -- 存储日期 );
2. DATETIME
- 格式:
YYYY-MM-DD HH:MM:SS
,范围1000-01-01 00:00:00
到9999-12-31 23:59:59
。 - 大小:8字节
- 示例:
CREATE TABLE order ( order_time DATETIME -- 如 '2023-10-01 14:30:00' );
3. TIMESTAMP
- 格式:同
DATETIME
,但范围较小(1970-01-01 00:00:01
UTC 到2038-01-19 03:14:07
UTC)。 - 大小:4字节
- 特点:自动转换为 UTC 时间存储,检索时根据时区转换。
- 示例:
CREATE TABLE login_log ( login_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 自动记录登录时间 );
四、特殊字符串类型
1. ENUM
- 定义:枚举类型,值从预定义列表中选择;单选。
- 注意:
插入非枚举值会报错,适合固定选项(如性别)。
下标从1开始
- 示例:
CREATE TABLE employee ( gender ENUM('Male', 'Female', 'Other') -- 仅允许这三个值 );
2. SET
- 定义:集合类型,可从预定义列表中选择多个值(用逗号分隔);多选。
- 注意:
数字代表比特位位图;从左到右,从低到高。
- 示例:
CREATE TABLE user_permissions ( roles SET('admin', 'editor', 'viewer') -- 如 'admin,editor' );
五、选择建议
-
数值类型:
- 优先选择最小适用类型(如
TINYINT
代替INT
)。 - 金额使用
DECIMAL
,避免浮点误差。
- 优先选择最小适用类型(如
-
字符串类型:
- 定长用
CHAR
,变长用VARCHAR
。 - 超长文本用
TEXT
,二进制数据用BLOB
。
- 定长用
-
时间类型:
- 需要时区支持用
TIMESTAMP
,否则用DATETIME
。
- 需要时区支持用
-
ENUM/SET:
- 确保值固定且有限时使用,避免过度依赖数据库约束。
通过合理选择数据类型,可以显著提升存储效率和查询性能。
转载请注明出处
完~