数据库-数据类型,表的约束和基本查询操作
一、数值类型
1. 整数类型
| 类型 | 字节 | 有符号范围 | 无符号范围 | 操作注意事项 | 
|---|---|---|---|---|
| TINYINT | 1 | -128 ~ 127 | 0 ~ 255 | 默认有符号, UNSIGNED定义无符号 | 
| SMALLINT | 2 | -32768 ~ 32767 | 0 ~ 65535 | 无符号需显式声明 | 
| INT | 4 | -2^31 ~ 2^31-1 | 0 ~ 2^32-1 | 推荐优先使用 INT | 
| BIGINT | 8 | -2^63 ~ 2^63-1 | 0 ~ 2^64-1 | 存储超长整数时使用 | 
示例:
CREATE TABLE tt2(num TINYINT UNSIGNED);  -- 无符号TINYINT
INSERT INTO tt2 VALUES(255);             -- 有效
INSERT INTO tt2 VALUES(-1);              -- 报错:越界
2. 小数类型
| 类型 | 特点 | 语法示例 | 精度对比 | 
|---|---|---|---|
| FLOAT | 单精度,约7位有效数字 | FLOAT(M, D) | 快速计算但精度低 | 
| DOUBLE | 双精度,约15位有效数字 | DOUBLE(M, D) | 精度高于FLOAT | 
| DECIMAL | 精确小数,高精度计算 | DECIMAL(M, D) | 精确存储(如金额) | 
示例:
CREATE TABLE tt8 (salary FLOAT(10,8), salary2 DECIMAL(10,8));
INSERT INTO tt8 VALUES(23.12345612, 23.12345612);
SELECT * FROM tt8; 
-- 结果:FLOAT显示23.12345695,DECIMAL显示23.12345612(精度更高)
3. BIT类型
- 语法:BIT(M),M范围1~64,默认1。
- 显示规则:按ASCII码显示。
- 适用场景:存储二进制标志(如性别0/1)。
示例:
CREATE TABLE tt5(gender BIT(1));  -- 存储0或1
INSERT INTO tt5 VALUES(0), (1);   -- 有效
INSERT INTO tt5 VALUES(2);        -- 报错:越界
二、字符串类型
1. CHAR与VARCHAR对比
| 类型 | 特点 | 最大长度 | 存储方式 | 适用场景 | 
|---|---|---|---|---|
| CHAR | 定长,固定占用空间 | 255字符 | 预先分配空间 | 身份证、MD5值 | 
| VARCHAR | 变长,按需分配空间 | 65535字节 | 动态分配空间 | 姓名、地址 | 
示例:
CREATE TABLE tt10(name VARCHAR(6) CHARSET=utf8);  -- UTF8下最大21844字符
INSERT INTO tt10 VALUES('我爱你,中国');           -- 6个字符(UTF8每个汉字3字节)
2. BLOB与TEXT
- BLOB:存储二进制数据(如图片、文件)。
- TEXT:存储大文本,不支持全文索引和默认值。
三、时间日期类型
| 类型 | 格式 | 范围 | 占用空间 | 特点 | 
|---|---|---|---|---|
| DATE | YYYY-MM-DD | 1000-01-01 ~ 9999-12-31 | 3字节 | 仅日期 | 
| DATETIME | YYYY-MM-DD HH:MM:SS | 1000-01-01 ~ 9999-12-31 | 8字节 | 日期+时间 | 
| TIMESTAMP | YYYY-MM-DD HH:MM:SS | 1970-01-01 ~ 2038-01-19 | 4字节 | 自动更新为当前时间 | 
示例:
CREATE TABLE birthday (t1 DATE, t2 DATETIME, t3 TIMESTAMP);
INSERT INTO birthday(t1,t2) VALUES('2000-01-01', '2023-10-01 12:00:00');
UPDATE birthday SET t1='2005-05-05';  -- t3自动更新为当前时间
四、ENUM与SET类型
1. ENUM(单选)
- 语法:ENUM('选项1', '选项2', ...),存储对应数字(1,2,…)。
- 示例:CREATE TABLE votes(gender ENUM('男','女')); INSERT INTO votes VALUES('男'), (2); -- 2对应'女'
2. SET(多选)
- 语法:SET('选项1', '选项2', ...),存储对应数字(1,2,4,8,…)。
- 查询:使用FIND_IN_SET函数。CREATE TABLE votes(hobby SET('登山','游泳','篮球')); INSERT INTO votes VALUES('登山,游泳'); SELECT * FROM votes WHERE FIND_IN_SET('登山', hobby); -- 查询包含"登山"的记录
五、关键注意事项
- 数值类型选择: - 优先使用DECIMAL存储精确小数(如金额)。
- 避免使用UNSIGNED,直接升级类型(如INT→BIGINT)更安全。
 
- 优先使用
- 字符串类型优化: - CHAR适合定长数据(如手机号),- VARCHAR适合变长数据(如地址)。
 
- 时间类型自动更新: - TIMESTAMP字段在数据更新时会自动刷新为当前时间。
 
- ENUM/SET查询技巧: - 避免直接使用数字插入,优先用可读字符串。
 
一、约束类型概览
| 约束类型 | 作用 | 关键字 | 特点 | 
|---|---|---|---|
| 空属性约束 | 控制字段是否允许为NULL | NOT NULL | 强制字段必须有值 | 
| 默认值约束 | 指定字段的默认值 | DEFAULT | 插入数据时可选使用默认值 | 
| 列描述约束 | 为字段添加注释 | COMMENT | 仅描述作用,不影响数据 | 
| 零填充约束 | 数字显示时自动填充前导零 | ZEROFILL | 仅影响显示,不改变存储值 | 
| 主键约束 | 唯一标识表中的记录 | PRIMARY KEY | 唯一、非空,一张表只能有一个 | 
| 自增长约束 | 自动生成递增的整数值 | AUTO_INCREMENT | 需与主键/唯一键搭配使用 | 
| 唯一键约束 | 确保字段值唯一(允许NULL) | UNIQUE KEY | 可多个,NULL不参与唯一性检查 | 
| 外键约束 | 强制关联主表的主键或唯一键 | FOREIGN KEY | 维护表间数据一致性 | 
二、核心约束详解
1. 空属性约束(NOT NULL)
- 语法:CREATE TABLE 表名 (字段名 数据类型 NOT NULL);
- 示例:CREATE TABLE myclass (class_name VARCHAR(20) NOT NULL,class_room VARCHAR(10) NOT NULL );
- 操作细节: - 插入数据时,若未给NOT NULL字段赋值,会报错:ERROR 1364 (HY000): Field 'class_room' doesn't have a default value
 
- 插入数据时,若未给
2. 默认值约束(DEFAULT)
- 语法:CREATE TABLE 表名 (字段名 数据类型 DEFAULT 默认值);
- 示例:CREATE TABLE tt10 (name VARCHAR(20) NOT NULL,age TINYINT UNSIGNED DEFAULT 0,sex CHAR(2) DEFAULT '男' );
- 操作细节: - 插入时省略字段,自动填充默认值:INSERT INTO tt10(name) VALUES('张三'); -- age=0, sex='男'
 
- 插入时省略字段,自动填充默认值:
3. 列描述约束(COMMENT)
- 语法:CREATE TABLE 表名 (字段名 数据类型 COMMENT '注释内容');
- 查看注释:SHOW CREATE TABLE 表名\G
4. 零填充约束(ZEROFILL)
- 语法:CREATE TABLE 表名 (字段名 INT(显示长度) ZEROFILL);
- 示例:ALTER TABLE tt3 CHANGE a a INT(5) UNSIGNED ZEROFILL;
- 效果: - 存储值1→ 显示为00001,实际存储仍为1。
 
- 存储值
5. 主键约束(PRIMARY KEY)
- 语法:-- 单字段主键 CREATE TABLE 表名 (字段名 数据类型 PRIMARY KEY);-- 复合主键 CREATE TABLE 表名 (字段1 数据类型, 字段2 数据类型, PRIMARY KEY(字段1, 字段2));
- 示例:CREATE TABLE tt14 (id INT UNSIGNED,course CHAR(10),PRIMARY KEY(id, course) -- 复合主键 );
- 操作细节: - 插入重复主键报错:ERROR 1062 (23000): Duplicate entry '1-123' for key 'PRIMARY'
- 删除主键:ALTER TABLE 表名 DROP PRIMARY KEY;
 
- 插入重复主键报错:
6. 自增长约束(AUTO_INCREMENT)
- 语法:CREATE TABLE 表名 (字段名 INT PRIMARY KEY AUTO_INCREMENT);
- 示例:CREATE TABLE tt21 (id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,name VARCHAR(10) NOT NULL DEFAULT '' );
- 操作细节: - 插入时省略自增长字段,自动生成递增值:INSERT INTO tt21(name) VALUES('a'); -- id=1 INSERT INTO tt21(name) VALUES('b'); -- id=2
- 获取最后插入的ID:SELECT LAST_INSERT_ID();
 
- 插入时省略自增长字段,自动生成递增值:
7. 唯一键约束(UNIQUE KEY)
- 语法:CREATE TABLE 表名 (字段名 数据类型 UNIQUE KEY);
- 示例:CREATE TABLE student (id CHAR(10) UNIQUE COMMENT '学号',name VARCHAR(10) );
- 操作细节: - 允许插入多个NULL值,但非NULL值必须唯一:INSERT INTO student VALUES(NULL, '张三'); -- 允许 INSERT INTO student VALUES('001', '李四'); -- 重复则报错
 
- 允许插入多个
8. 外键约束(FOREIGN KEY)
- 语法:CREATE TABLE 从表名 (字段名 数据类型,FOREIGN KEY (从表字段) REFERENCES 主表名(主表字段) );
- 示例:-- 主表 CREATE TABLE myclass (id INT PRIMARY KEY, name VARCHAR(30) NOT NULL);-- 从表 CREATE TABLE stu (id INT PRIMARY KEY,class_id INT,FOREIGN KEY (class_id) REFERENCES myclass(id) );
- 操作细节: - 插入无效外键值报错:ERROR 1452 (23000): Cannot add or update a child row
- 允许外键为NULL:INSERT INTO stu VALUES(102, NULL); -- 允许未分配班级
 
- 插入无效外键值报错:
三、综合案例解析
场景:设计商店数据库(商品、客户、购买表)
-- 商品表
CREATE TABLE goods (goods_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '商品编号',goods_name VARCHAR(32) NOT NULL COMMENT '商品名称',unitprice INT NOT NULL DEFAULT 0 COMMENT '单价(分)',category VARCHAR(12) COMMENT '分类',provider VARCHAR(64) NOT NULL COMMENT '供应商'
);-- 客户表
CREATE TABLE customer (customer_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '客户编号',name VARCHAR(32) NOT NULL COMMENT '姓名',email VARCHAR(64) UNIQUE KEY COMMENT '邮箱',sex ENUM('男','女') NOT NULL COMMENT '性别',card_id CHAR(18) UNIQUE KEY COMMENT '身份证'
);-- 购买表(外键关联)
CREATE TABLE purchase (order_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '订单号',customer_id INT COMMENT '客户编号',goods_id INT COMMENT '商品编号',nums INT DEFAULT 0 COMMENT '购买数量',FOREIGN KEY (customer_id) REFERENCES customer(customer_id),FOREIGN KEY (goods_id) REFERENCES goods(goods_id)
);
四、关键注意事项
- 主键与业务无关:推荐使用自增ID,避免业务调整影响主键。
- 外键性能:外键约束可能影响插入/更新性能,高频写入场景需谨慎使用。
- 唯一键与NULL:唯一键允许NULL,但多个NULL不视为重复。
- 自增长字段:仅支持整数类型,且一张表只能有一个自增长字段。
MySQL基本查询操作
1. Create(增)
- 语法:INSERT INTO 表名 [(列名,...)] VALUES (值列表)[, (值列表)...];
- 操作细节: - 全列插入:值与表结构列顺序一致,可省略列名。INSERT INTO students VALUES (100, 10000, '唐三藏', NULL);
- 指定列插入:插入部分列,未指定列使用默认值或NULL。INSERT INTO students (id, sn, name) VALUES (102, 20001, '曹孟德');
- 冲突处理: - 更新重复键:ON DUPLICATE KEY UPDATEINSERT INTO students (id, sn, name) VALUES (100, 10010, '唐大师') ON DUPLICATE KEY UPDATE sn = 10010, name = '唐大师';
- 替换重复键:REPLACE(删除旧记录后插入新记录)。REPLACE INTO students (sn, name) VALUES (20001, '曹阿晴');
 
- 更新重复键:
 
- 全列插入:值与表结构列顺序一致,可省略列名。
2. Retrieve(查)
- 语法:SELECT [DISTINCT] 列名 FROM 表名 [WHERE ...] [ORDER BY ...] [LIMIT ...];
- 操作细节: -  基础查询: - 全列查询(不推荐):SELECT * FROM exam_result;
- 指定列查询:SELECT id, name FROM exam_result;
- 表达式查询:SELECT name, math + 10 AS math_plus FROM exam_result;
- 别名:SELECT name, chinese + math + english 总分 FROM exam_result;
- 去重:SELECT DISTINCT math FROM exam_result;
 
- 全列查询(不推荐):
-  条件过滤(WHERE): - 比较运算符:>,=,<=>,BETWEEN,IN,LIKE(%匹配任意字符,_匹配单个字符)。
- 逻辑运算符:AND,OR,NOT。
- 案例:-- 英语不及格 SELECT name, english FROM exam_result WHERE english < 60; -- 姓孙的同学 SELECT name FROM exam_result WHERE name LIKE '孙%'; -- 总分 < 200(WHERE中不能使用别名) SELECT name, chinese + math + english 总分 FROM exam_result WHERE chinese + math + english < 200;
 
- 比较运算符:
-  排序(ORDER BY): - 默认升序(ASC),降序用DESC。
- 多字段排序:按书写顺序优先级。SELECT name, math, english FROM exam_result ORDER BY math DESC, english;
 
-  分页(LIMIT): - 语法:LIMIT n OFFSET s(从s开始取n条,s起始为0)。-- 第2页(每页3条) SELECT * FROM exam_result ORDER BY id LIMIT 3 OFFSET 3;
 
- 语法:
 
-  
3. Update(改)
- 语法:UPDATE 表名 SET 列名=值 [WHERE ...] [ORDER BY ...] [LIMIT ...];
- 操作细节: - 单列更新:UPDATE exam_result SET math = 80 WHERE name = '孙悟空';
- 多列更新:UPDATE exam_result SET math = 60, chinese = 70 WHERE name = '曹孟德';
- 表达式更新:-- 总分倒数前三的数学加30分 UPDATE exam_result SET math = math + 30 ORDER BY chinese + math + english LIMIT 3;
- 慎用全表更新:无WHERE条件时更新全表。
 
- 单列更新:
4. Delete(删)
- 语法:DELETE FROM 表名 [WHERE ...] [ORDER BY ...] [LIMIT ...];
- 操作细节: - 删除指定数据:DELETE FROM exam_result WHERE name = '孙悟空';
- 清空表: - DELETE FROM 表名:逐行删除,自增值保留。
- TRUNCATE 表名:快速清空,重置自增值,不可回滚。
 
 
- 删除指定数据:
5. 高级操作
-  聚合函数: - COUNT,- SUM,- AVG,- MAX,- MIN,支持- DISTINCT。- -- 统计数学成绩种类数 SELECT COUNT(DISTINCT math) FROM exam_result; -- 计算平均总分 SELECT AVG(chinese + math + english) 平均总分 FROM exam_result;
 
-  GROUP BY 分组: - 按部门统计平均工资:SELECT deptno, AVG(sal) FROM EMP GROUP BY deptno;
- HAVING过滤分组:- SELECT deptno, AVG(sal) FROM EMP GROUP BY deptno HAVING AVG(sal) < 2000;
 
- 按部门统计平均工资:
6. 注意事项
- 执行顺序:
 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT。
- NULL处理: - = NULL不安全,需用- IS NULL或- <=>。
- 聚合函数忽略NULL(如COUNT(qq)仅统计非NULL值)。
 
- 性能提示: - 避免全列查询(SELECT *)。
- 分页时建议用LIMIT防止全表扫描。
 
- 避免全列查询(
7. 实战技巧
- 去重插入:通过临时表实现原子操作。CREATE TABLE no_duplicate_table LIKE duplicate_table; INSERT INTO no_duplicate_table SELECT DISTINCT * FROM duplicate_table; RENAME TABLE duplicate_table TO old_table, no_duplicate_table TO duplicate_table;
- 分页优化:按主键分页,避免OFFSET过大时性能问题。
