MySQL 数据库学习笔记
返回首页
技术分享
2025-12-20
连接MySQL服务器
本地连接
mysql -u root -p
远程连接
mysql -h 主机IP -u 用户名 -p
SSH连接到远程MySQL
ssh 用户名@服务器IP
# 连接成功后再执行
mysql -u root -p
SSH配置(如需远程连接)
编辑SSH配置文件 /etc/ssh/sshd_config:
# 启用SSH端口
Port 22
# 允许root登录
PermitRootLogin yes
# 启用公钥认证
PubkeyAuthentication yes
重启SSH服务:
systemctl restart sshd
创建与维护数据库
1. 创建数据库
基本语法
CREATE DATABASE <数据库名>;
指定字符集
CREATE DATABASE <数据库名> CHARACTER SET <字符集名>;
完整语法
CREATE DATABASE <数据库名>
[DEFAULT] CHARACTER SET <字符集名>
[COLLATE <排序规则名>];
示例
-- 创建基本数据库
CREATE DATABASE navicat_db;
-- 创建指定字符集的数据库
CREATE DATABASE sql_db CHARACTER SET gb2312;
-- 创建UTF8MB4字符集的数据库
CREATE DATABASE myapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
2. 查看数据库
查看所有数据库
SHOW DATABASES;
查看数据库创建信息
SHOW CREATE DATABASE <数据库名>;
示例
SHOW CREATE DATABASE sql_db;
3. 修改数据库
修改字符集
ALTER DATABASE <数据库名> CHARACTER SET <字符集名>;
示例
ALTER DATABASE sql_db CHARACTER SET utf8mb4;
4. 使用数据库
USE <数据库名>;
5. 删除数据库
DROP DATABASE <数据库名>;
示例
DROP DATABASE navicat_db;
DROP DATABASE sql_db;
创建与维护数据表
1. 创建数据表
基本语法
CREATE TABLE <表名> (
字段名 数据类型 [约束条件],
字段名 数据类型 [约束条件],
...
);
完整语法示例
CREATE TABLE course (
cno CHAR(5) NOT NULL PRIMARY KEY,
cname VARCHAR(20) NOT NULL,
credit INT DEFAULT 0,
description TEXT
);
常用数据类型
| 类型 | 说明 | 示例 |
|---|---|---|
| INT | 整数 | age INT |
| VARCHAR | 变长字符串 | name VARCHAR(50) |
| CHAR | 定长字符串 | code CHAR(10) |
| TEXT | 长文本 | content TEXT |
| DATE | 日期 | birth DATE |
| DATETIME | 日期时间 | created_at DATETIME |
| DECIMAL | 精确小数 | price DECIMAL(10,2) |
| BOOLEAN | 布尔值 | is_active BOOLEAN |
约束类型
| 约束 | 说明 | 示例 |
|---|---|---|
| PRIMARY KEY | 主键 | id INT PRIMARY KEY |
| FOREIGN KEY | 外键 | user_id INT REFERENCES users(id) |
| NOT NULL | 非空 | name VARCHAR(50) NOT NULL |
| UNIQUE | 唯一 | email VARCHAR(100) UNIQUE |
| DEFAULT | 默认值 | status INT DEFAULT 0 |
| CHECK | 检查约束 | age INT CHECK(age >= 18) |
复杂表示例
CREATE TABLE student (
sno CHAR(10) NOT NULL PRIMARY KEY,
sname VARCHAR(20) NOT NULL,
ssex CHAR(2) DEFAULT '男',
sage INT CHECK(sage BETWEEN 15 AND 50),
sdept VARCHAR(30),
speciality VARCHAR(50),
enrollment_date DATE,
FOREIGN KEY (sdept) REFERENCES department(dept_name)
);
CREATE TABLE score (
id INT AUTO_INCREMENT PRIMARY KEY,
sno CHAR(10) NOT NULL,
cno CHAR(5) NOT NULL,
score DECIMAL(5,2) CHECK(score BETWEEN 0 AND 100),
exam_time DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (sno) REFERENCES student(sno),
FOREIGN KEY (cno) REFERENCES course(cno),
UNIQUE KEY unique_student_course (sno, cno)
);
2. 插入数据
基本语法
INSERT INTO <表名> (字段1, 字段2, ...) VALUES (值1, 值2, ...);
批量插入
INSERT INTO course (cno, cname) VALUES
('C01', '数据库'),
('C02', '数学'),
('C03', '信息系统'),
('C04', '操作系统'),
('C05', '计算机网络');
插入完整记录
INSERT INTO student VALUES
('2021001', '张三', '男', 20, '计算机', '软件工程', '2021-09-01'),
('2021002', '李四', '女', 19, '数学', '应用数学', '2021-09-01');
3. 修改表结构
添加字段
ALTER TABLE <表名> ADD <字段名> <数据类型> [约束];
示例
-- 添加入学时间字段
ALTER TABLE student ADD enrollment_date DATE;
-- 添加带默认值的字段
ALTER TABLE student ADD status INT DEFAULT 1;
修改字段类型
ALTER TABLE <表名> MODIFY <字段名> <新数据类型> [约束];
示例
-- 修改字段长度
ALTER TABLE student MODIFY sdept VARCHAR(50);
-- 修改字段类型和约束
ALTER TABLE student MODIFY sage INT NOT NULL;
修改字段名
ALTER TABLE <表名> CHANGE <旧字段名> <新字段名> <数据类型> [约束];
示例
-- 重命名字段
ALTER TABLE student CHANGE sdept sdepartment VARCHAR(30);
-- 同时修改字段名和类型
ALTER TABLE student CHANGE sdepartment dept_name VARCHAR(50) NOT NULL;
删除字段
ALTER TABLE <表名> DROP <字段名>;
示例
-- 删除专业字段
ALTER TABLE student DROP speciality;
重命名表
ALTER TABLE <旧表名> RENAME <新表名>;
示例
-- 重命名表
ALTER TABLE teaching RENAME teach;
-- 或者使用RENAME TABLE语句
RENAME TABLE old_table TO new_table;
4. 删除表
DROP TABLE <表名>;
示例
DROP TABLE teach;
5. 复制表
复制表结构和数据
CREATE TABLE <新表名> AS SELECT * FROM <源表名>;
只复制表结构
CREATE TABLE <新表名> LIKE <源表名>;
示例
-- 完全复制
CREATE TABLE student_backup AS SELECT * FROM student;
-- 只复制结构
CREATE TABLE student_structure LIKE student;
常用操作命令总结
数据库操作
-- 创建数据库
CREATE DATABASE db_name CHARACTER SET utf8mb4;
-- 查看所有数据库
SHOW DATABASES;
-- 使用数据库
USE db_name;
-- 查看当前数据库
SELECT DATABASE();
-- 修改数据库字符集
ALTER DATABASE db_name CHARACTER SET utf8mb4;
-- 删除数据库
DROP DATABASE db_name;
表操作
-- 创建表
CREATE TABLE table_name (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 查看所有表
SHOW TABLES;
-- 查看表结构
DESC table_name;
-- 或者
DESCRIBE table_name;
-- 查看创建表的SQL
SHOW CREATE TABLE table_name;
-- 重命名表
RENAME TABLE old_name TO new_name;
-- 删除表
DROP TABLE table_name;
字段操作
-- 添加字段
ALTER TABLE table_name ADD column_name VARCHAR(100);
-- 修改字段类型
ALTER TABLE table_name MODIFY column_name INT;
-- 修改字段名
ALTER TABLE table_name CHANGE old_name new_name VARCHAR(100);
-- 删除字段
ALTER TABLE table_name DROP column_name;
-- 添加主键
ALTER TABLE table_name ADD PRIMARY KEY (id);
-- 添加外键
ALTER TABLE table_name ADD FOREIGN KEY (user_id) REFERENCES users(id);
数据操作
-- 插入数据
INSERT INTO table_name (col1, col2) VALUES (value1, value2);
-- 查询数据
SELECT * FROM table_name WHERE condition;
-- 更新数据
UPDATE table_name SET col1 = value1 WHERE condition;
-- 删除数据
DELETE FROM table_name WHERE condition;
实用技巧
1. 字符集设置
-- 创建数据库时指定字符集
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 创建表时指定字符集
CREATE TABLE mytable (
id INT PRIMARY KEY
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
2. 索引操作
-- 添加普通索引
ALTER TABLE table_name ADD INDEX index_name (column_name);
-- 添加唯一索引
ALTER TABLE table_name ADD UNIQUE INDEX index_name (column_name);
-- 添加全文索引
ALTER TABLE table_name ADD FULLTEXT INDEX index_name (column_name);
3. 查看表信息
-- 查看表状态
SHOW TABLE STATUS LIKE 'table_name';
-- 查看表的索引
SHOW INDEX FROM table_name;
-- 查看表的列信息
SHOW COLUMNS FROM table_name;
4. 备份与恢复
# 备份数据库
mysqldump -u username -p database_name > backup.sql
# 恢复数据库
mysql -u username -p database_name < backup.sql
视图 (VIEW)
1. 什么是视图
视图是基于SQL语句的结果集的可视化表。视图包含行和列,就像一个真实的表。视图中的字段就是来自一个或多个数据库表中的字段。
2. 创建视图
基本语法
CREATE VIEW <视图名> AS
SELECT <列名> FROM <表名> [WHERE 条件];
创建复杂视图
CREATE VIEW student_course_view AS
SELECT
s.sno,
s.sname,
s.sdept,
c.cno,
c.cname,
sc.score
FROM student s
JOIN score sc ON s.sno = sc.sno
JOIN course c ON sc.cno = c.cno;
创建带统计的视图
CREATE VIEW student_score_stats AS
SELECT
s.sno,
s.sname,
COUNT(sc.cno) AS course_count,
AVG(sc.score) AS avg_score,
MAX(sc.score) AS max_score,
MIN(sc.score) AS min_score
FROM student s
LEFT JOIN score sc ON s.sno = sc.sno
GROUP BY s.sno, s.sname;
3. 查看视图
查看所有视图
SHOW FULL TABLES WHERE table_type = 'VIEW';
查看视图结构
DESC <视图名>;
-- 或者
DESCRIBE <视图名>;
查看视图创建语句
SHOW CREATE VIEW <视图名>;
4. 使用视图
查询视图数据
-- 基本查询
SELECT * FROM student_course_view;
-- 带条件查询
SELECT * FROM student_course_view WHERE sdept = '计算机';
-- 统计查询
SELECT sdept, AVG(score) as avg_score
FROM student_course_view
GROUP BY sdept;
5. 修改视图
替换视图
CREATE OR REPLACE VIEW <视图名> AS
SELECT <新查询语句>;
示例
CREATE OR REPLACE VIEW student_course_view AS
SELECT
s.sno,
s.sname,
s.ssex,
s.sdept,
c.cno,
c.cname,
c.credit,
sc.score,
CASE
WHEN sc.score >= 90 THEN '优秀'
WHEN sc.score >= 80 THEN '良好'
WHEN sc.score >= 60 THEN '及格'
ELSE '不及格'
END AS grade_level
FROM student s
JOIN score sc ON s.sno = sc.sno
JOIN course c ON sc.cno = c.cno;
6. 删除视图
DROP VIEW <视图名>;
7. 视图的优点
- 简化查询:将复杂的SQL查询封装为简单的视图
- 安全性:只显示用户需要的数据,隐藏敏感信息
- 逻辑独立性:表结构改变时,只需修改视图
- 数据一致性:确保数据的一致性显示SQL 编程
1. 变量声明与使用
用户变量
-- 声明变量
SET @variable_name = value;
-- 使用变量
SELECT @variable_name;
-- 示例
SET @student_id = '2021001';
SELECT * FROM student WHERE sno = @student_id;
局部变量(在存储过程中使用)
DECLARE variable_name data_type [DEFAULT value];
2. 条件语句
IF-ELSE 语句
IF condition THEN
-- 语句块
ELSEIF condition THEN
-- 语句块
ELSE
-- 语句块
END IF;
示例
SET @score = 85;
SET @grade = '';
IF @score >= 90 THEN
SET @grade = 'A';
ELSEIF @score >= 80 THEN
SET @grade = 'B';
ELSEIF @score >= 60 THEN
SET @grade = 'C';
ELSE
SET @grade = 'D';
END IF;
SELECT @grade AS grade;
CASE 语句
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
ELSE result_n
END
示例
SELECT
sname,
score,
CASE
WHEN score >= 90 THEN '优秀'
WHEN score >= 80 THEN '良好'
WHEN score >= 60 THEN '及格'
ELSE '不及格'
END AS grade
FROM student_course_view;
3. 循环语句
WHILE 循环
WHILE condition DO
-- 循环体
END WHILE;
示例
-- 计算1到10的和
SET @total = 0;
SET @i = 1;
WHILE @i <= 10 DO
SET @total = @total + @i;
SET @i = @i + 1;
END WHILE;
SELECT @total AS sum_result;
REPEAT 循环
REPEAT
-- 循环体
UNTIL condition
END REPEAT;
LOOP 循环
loop_label: LOOP
-- 循环体
IF condition THEN
LEAVE loop_label;
END IF;
END LOOP loop_label;
4. 存储过程
创建存储过程
DELIMITER //
CREATE PROCEDURE procedure_name ([参数列表])
BEGIN
-- 存储过程体
END //
DELIMITER ;
参数类型
-- IN 参数(输入参数)
CREATE PROCEDURE get_student(IN student_id CHAR(10))
BEGIN
SELECT * FROM student WHERE sno = student_id;
END;
-- OUT 参数(输出参数)
CREATE PROCEDURE get_student_count(IN dept_name VARCHAR(30), OUT student_count INT)
BEGIN
SELECT COUNT(*) INTO student_count
FROM student WHERE sdept = dept_name;
END;
-- INOUT 参数(输入输出参数)
CREATE PROCEDURE update_counter(INOUT counter INT, increment_val INT)
BEGIN
SET counter = counter + increment_val;
END;
调用存储过程
-- 调用带IN参数的存储过程
CALL get_student('2021001');
-- 调用带OUT参数的存储过程
CALL get_student_count('计算机', @count);
SELECT @count;
-- 调用带INOUT参数的存储过程
SET @counter = 10;
CALL update_counter(@counter, 5);
SELECT @counter;
实际示例
DELIMITER //
CREATE PROCEDURE update_student_score(
IN student_no CHAR(10),
IN course_no CHAR(5),
IN new_score DECIMAL(5,2),
OUT result_message VARCHAR(100)
)
BEGIN
DECLARE existing_score DECIMAL(5,2) DEFAULT NULL;
-- 检查成绩是否存在
SELECT score INTO existing_score
FROM score
WHERE sno = student_no AND cno = course_no;
IF existing_score IS NOT NULL THEN
-- 更新成绩
UPDATE score SET score = new_score
WHERE sno = student_no AND cno = course_no;
SET result_message = '成绩更新成功';
ELSE
-- 插入新成绩
INSERT INTO score (sno, cno, score)
VALUES (student_no, course_no, new_score);
SET result_message = '成绩插入成功';
END IF;
END //
DELIMITER ;
5. 函数
创建函数
DELIMITER //
CREATE FUNCTION function_name ([参数列表]) RETURNS return_type
BEGIN
-- 函数体
RETURN return_value;
END //
DELIMITER ;
示例
DELIMITER //
CREATE FUNCTION calculate_grade(score DECIMAL(5,2)) RETURNS VARCHAR(10)
DETERMINISTIC
BEGIN
DECLARE grade VARCHAR(10);
IF score >= 90 THEN
SET grade = 'A';
ELSEIF score >= 80 THEN
SET grade = 'B';
ELSEIF score >= 60 THEN
SET grade = 'C';
ELSE
SET grade = 'D';
END IF;
RETURN grade;
END //
DELIMITER ;
使用函数
SELECT
sno,
cno,
score,
calculate_grade(score) AS grade
FROM score;
更多函数示例
-- 计算GPA的函数
DELIMITER //
CREATE FUNCTION calculate_gpa(student_id CHAR(10)) RETURNS DECIMAL(3,2)
DETERMINISTIC
BEGIN
DECLARE gpa DECIMAL(3,2) DEFAULT 0.00;
SELECT AVG(score)/20 INTO gpa
FROM score
WHERE sno = student_id;
RETURN gpa;
END //
DELIMITER ;
-- 字符串处理函数
DELIMITER //
CREATE FUNCTION format_student_name(full_name VARCHAR(50)) RETURNS VARCHAR(50)
DETERMINISTIC
BEGIN
DECLARE formatted_name VARCHAR(50);
-- 将姓名格式化为:姓 名(首字母大写)
SET formatted_name = CONCAT(
UPPER(LEFT(full_name, 1)),
LOWER(SUBSTRING(full_name, 2))
);
RETURN formatted_name;
END //
DELIMITER ;
6. 触发器
创建触发器
DELIMITER //
CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON table_name
FOR EACH ROW
BEGIN
-- 触发器逻辑
END //
DELIMITER ;
示例
-- 插入前触发器:自动设置创建时间
DELIMITER //
CREATE TRIGGER before_student_insert
BEFORE INSERT ON student
FOR EACH ROW
BEGIN
IF NEW.enrollment_date IS NULL THEN
SET NEW.enrollment_date = CURRENT_DATE();
END IF;
END //
DELIMITER ;
-- 更新后触发器:记录修改日志
DELIMITER //
CREATE TRIGGER after_student_update
AFTER UPDATE ON student
FOR EACH ROW
BEGIN
INSERT INTO student_log (
student_id,
old_name,
new_name,
operation,
log_time
) VALUES (
NEW.sno,
OLD.sname,
NEW.sname,
'UPDATE',
NOW()
);
END //
DELIMITER ;
-- 删除前触发器:检查约束
DELIMITER //
CREATE TRIGGER before_student_delete
BEFORE DELETE ON student
FOR EACH ROW
BEGIN
DECLARE score_count INT;
-- 检查学生是否有成绩记录
SELECT COUNT(*) INTO score_count
FROM score WHERE sno = OLD.sno;
IF score_count > 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '无法删除有成绩记录的学生';
END IF;
END //
DELIMITER ;
7. 游标
游标基本使用
DELIMITER //
CREATE PROCEDURE cursor_example()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE student_id CHAR(10);
DECLARE student_name VARCHAR(20);
DECLARE avg_score DECIMAL(5,2);
-- 声明游标
DECLARE student_cursor CURSOR FOR
SELECT sno, sname FROM student;
-- 声明异常处理
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- 创建临时表存储结果
CREATE TEMPORARY TABLE IF NOT EXISTS temp_results (
student_id CHAR(10),
student_name VARCHAR(20),
avg_score DECIMAL(5,2)
);
-- 打开游标
OPEN student_cursor;
read_loop: LOOP
-- 读取游标数据
FETCH student_cursor INTO student_id, student_name;
-- 退出条件
IF done THEN
LEAVE read_loop;
END IF;
-- 计算平均成绩
SELECT AVG(score) INTO avg_score
FROM score
WHERE sno = student_id;
-- 插入结果
INSERT INTO temp_results VALUES
(student_id, student_name, IFNULL(avg_score, 0));
END LOOP;
-- 关闭游标
CLOSE student_cursor;
-- 返回结果
SELECT * FROM temp_results;
-- 清理临时表
DROP TEMPORARY TABLE IF EXISTS temp_results;
END //
DELIMITER ;
8. 事务处理
事务基本语法
-- 开始事务
START TRANSACTION;
-- 执行SQL语句
UPDATE account SET balance = balance - 100 WHERE user_id = 1;
UPDATE account SET balance = balance + 100 WHERE user_id = 2;
-- 提交事务或回滚
COMMIT; -- 提交
-- 或者
ROLLBACK; -- 回滚
事务示例
DELIMITER //
CREATE PROCEDURE transfer_money(
IN from_account INT,
IN to_account INT,
IN amount DECIMAL(10,2),
OUT result_message VARCHAR(100)
)
BEGIN
DECLARE from_balance DECIMAL(10,2);
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SET result_message = '转账失败,已回滚';
END;
-- 开始事务
START TRANSACTION;
-- 检查余额
SELECT balance INTO from_balance
FROM account
WHERE account_id = from_account;
IF from_balance < amount THEN
SET result_message = '余额不足';
ROLLBACK;
ELSE
-- 扣款
UPDATE account
SET balance = balance - amount
WHERE account_id = from_account;
-- 入账
UPDATE account
SET balance = balance + amount
WHERE account_id = to_account;
-- 记录交易日志
INSERT INTO transaction_log (
from_account,
to_account,
amount,
transaction_time
) VALUES (
from_account,
to_account,
amount,
NOW()
);
COMMIT;
SET result_message = '转账成功';
END IF;
END //
DELIMITER ;
9. 错误处理
DECLARE HANDLER 语法
DECLARE handler_type HANDLER
FOR condition_value [, condition_value] ...
statement
-- handler_type:
-- CONTINUE: 继续执行
-- EXIT: 退出执行
-- UNDO: 回滚(事务中使用)
-- condition_value:
-- SQLSTATE 'VALUE'
-- SQLWARNING
-- NOT FOUND
-- SQLEXCEPTION
错误处理示例
DELIMITER //
CREATE PROCEDURE safe_divide(
IN dividend DECIMAL(10,2),
IN divisor DECIMAL(10,2),
OUT result DECIMAL(10,2),
OUT error_message VARCHAR(100)
)
BEGIN
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
error_message = MESSAGE_TEXT;
END;
IF divisor = 0 THEN
SET error_message = '除数不能为零';
SET result = NULL;
ELSE
SET result = dividend / divisor;
SET error_message = '计算成功';
END IF;
END //
DELIMITER ;