Auto commit

This commit is contained in:
smallkun 2025-03-22 19:49:55 +08:00
parent 92bbbfb089
commit f6f91c0fd4
9 changed files with 3044 additions and 48 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,651 @@
### 练习一
![image-20250315225248590](https://yp.smallkun.cn/markdown/image-20250315225248590.png!compress)
```sql
#(1)创建数据库
CREATE DATABASE test04_Market DEFAULT CHARACTER SET utf8;
USE test04_Market;
#(2)创建数据表
CREATE TABLE customers(
c_num INT(11) PRIMARY KEY AUTO_INCREMENT,
c_name VARCHAR(50),
c_contact VARCHAR(50),
c_city VARCHAR(50),
c_birth DATETIME NOT NULL
);
#(3)更改字段的位置
#AFTER/BEFORE 字段名 设置位置在指定字段前/后
ALTER TABLE 表名 MODIFY 字段名 数据类型 AFTER/BEFORE 字段名;
ALTER TABLE customers MODIFY c_contact VARCHAR(50) AFTER c_birth;
#(4)更改字段的数据类型
ALTER TABLE customers MODIFY c_name VARCHAR(70);
#(5)更改字段名
ALTER TABLE customers CHANGE c_contact c_phone VARCHAR(50);
#(6)添加字段
ALTER TABLE customers ADD c_gender CHAR(1);
#(7)更改表名
ALTER TABLE customers RENAME TO customers_info;
#(8)删除字段
ALTER TABLE customers_info DROP c_city;
```
![image-20250315225304324](https://yp.smallkun.cn/markdown/image-20250315225304324.png!compress)
```sql
#(1)创建表时 添加外键约束并指定外键约束名称
CREATE TABLE orders(
o_num INT(11) PRIMARY KEY AUTO_INCREMENT,
o_date DATE,
c_id INT(11),
CONSTRAINT fk_cid FOREIGN KEY(c_id) REFERENCES customers_info(c_num)
);
#(2)
#删除指定外键
ALTER TABLE orders DROP FOREIGN KEY orders_ibfk_1;
#删除指定表
DROP TABLE orders;
```
---
### 练习二
![image-20250315225318753](https://yp.smallkun.cn/markdown/image-20250315225318753.png!compress)
![image-20250315225328264](https://yp.smallkun.cn/markdown/image-20250315225328264.png!compress)
```sql
#(1)创建表、插入记录
CREATE TABLE pet(
`name` VARCHAR(20) NOT NULL COMMENT '宠物名称',
`owner` VARCHAR(20) COMMENT '宠物主人',
species VARCHAR(20) NOT NULL COMMENT '种类',
sex CHAR(1) NOT NULL COMMENT '性别',
birth YEAR NOT NULL COMMENT '出生日期',
death YEAR COMMENT '死亡日期'
);
INSERT INTO pet()
VALUES
('Fluffy', 'Harold', 'cat', 'f', 2003, 2010),
('Claws', 'Gwen', 'cat', 'm', 2004,NULL ),
('Buffy', NULL, 'dog', 'f', 2009, NULL),
('Fang', 'Benny', 'dog', 'm', 2000, NULL),
('Bowser', 'Diane', 'dog', 'm', 2003, 2009),
('Chirpy', NULL, 'bird', 'f', 2008, NULL);
#(2)更新记录
UPDATE pet
SET `owner` = 'Kevin'
WHERE `name` = 'Fang';
#(3)
UPDATE pet
SET `owner` = 'Kevin'
WHERE `owner` IS NULL;
#(4)
DELETE FROM pet
WHERE death IS NOT NULL;
#(5)
TRUNCATE pet;
```
---
### 练习三
![image-20250315225417117](https://yp.smallkun.cn/markdown/image-20250315225417117.png!compress)
![image-20250315225431297](https://yp.smallkun.cn/markdown/image-20250315225431297.png!compress)
```sql
#1.创建数据库
CREATE DATABASE test_compay DEFAULT CHARACTER SET utf8;
#2.创建表
CREATE TABLE department(
depid INT PRIMARY KEY AUTO_INCREMENT,
depname VARCHAR(20) NOT NULL,
deinfo VARCHAR(50)
);
CREATE TABLE employee(
empid INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(20) NOT NULL,
sex CHAR(1) NOT NULL DEFAULT '男',
title VARCHAR(20) NOT NULL,
birthday DATE NOT NULL,
depid INT,
CONSTRAINT fk_eid_did FOREIGN KEY(depid) REFERENCES department(depid)
);
CREATE TABLE salary(
empid INT,
basesalary DECIMAL(10, 2),
titleSalary DECIMAL(10, 2),
decuction DECIMAL(10, 2)
);
#3添加外键并设置级联更新、级联删除
ALTER TABLE salary ADD CONSTRAINT fk_sal_eid FOREIGN KEY(empid)
REFERENCES employee(empid) ON UPDATE CASCADE ON DELETE CASCADE;
#4插入记录
INSERT INTO department (depid, depname, deinfo)
VALUES
(111, '生产部', NULL),
(222, '销售部', NULL),
(333, '人事部', NULL),
(444, '财务部', '负责公司财务管理'),
(555, '技术部', '负责技术研发与支持'),
(666, '市场部', '负责市场推广与品牌建设'),
(777, '客服部', '负责客户服务与支持'),
(888, '采购部', '负责公司物资采购'),
(999, '法务部', '负责公司法律事务'),
(1010, '行政部', '负责公司日常行政管理'),
(1011, '研发部', '负责新产品研发'),
(1012, '培训部', '负责员工培训与发展');
INSERT INTO employee (empid, name, sex, title, birthday, depid)
VALUES
(1001, '张三', '男', '高级工程师', '1975-1-1', 111),
(1002, '李四', '女', '助工', '1985-1-1', 111),
(1003, '王五', '男', '工程师', '1978-11-11', 222),
(1004, '赵六', '男', '工程师', '1999-1-1', 222),
(1005, '陈七', '女', '会计师', '1980-5-15', 444),
(1006, '刘八', '男', '软件工程师', '1990-8-20', 555),
(1007, '孙九', '女', '市场经理', '1985-12-25', 666),
(1008, '周十', '男', '客服专员', '1992-3-10', 777),
(1009, '吴十一', '女', '采购经理', '1988-7-22', 888),
(1010, '郑十二', '男', '法务顾问', '1983-9-30', 999),
(1011, '王十三', '女', '行政助理', '1995-4-18', 1010),
(1012, '李十四', '男', '研发工程师', '1991-11-5', 1011),
(1013, '赵十五', '女', '培训讲师', '1987-6-12', 1012),
(1014, '孙十六', '男', '技术支持', '1993-2-14', 555),
(1015, '杨十七', '女', '销售代表', '1994-8-8', 222);
INSERT INTO salary (empid, basesalary, titleSalary, decuction)
VALUES
(1001, 2200, 1100, 200),
(1002, 1200, 200, NULL),
(1003, 2900, 700, 200),
(1004, 1950, 700, 150),
(1005, 2500, 800, 100),
(1006, 3000, 1200, 250),
(1007, 2800, 1000, 200),
(1008, 1800, 300, 50),
(1009, 3200, 900, 300),
(1010, 3500, 1000, 400),
(1011, 2000, 400, 100),
(1012, 3100, 1100, 200),
(1013, 2700, 800, 150),
(1014, 2300, 700, 100),
(1015, 2600, 600, 200);
```
![image-20250315225441802](https://yp.smallkun.cn/markdown/image-20250315225441802.png!compress)
```sql
#5
SELECT e.empid, e.`name`, e.title, d.depname, s.basesalary + s.titleSalary, s.basesalary + s.titleSalary-IFNULL(s.decuction, 0)
FROM employee e, department d, salary s
WHERE e.depid = d.depid AND e.empid = s.empid;
#6
SELECT e.`name`, s.basesalary
FROM employee e, department d, salary s
WHERE e.depid = d.depid AND e.empid = s.empid AND d.depname = '销售部';
#7
SELECT *
FROM employee e
WHERe e.`name` LIKE '张%' AND TIMESTAMPDIFF(YEAR,e.birthday, NOW()) < 40;
#8
SELECT e.`name`, s.basesalary, s.titleSalary
FROM employee e, salary s
WHERE e.sex = '男' AND e.empid AND s.empid;
#9
SELECT e.`name`, e.title, d.depname
FROM employee e, department d, salary s
WHERE e.depid = d.depid AND e.empid = s.empid AND s.basesalary < 2000;
#10
SELECT COUNT(*)
FROM employee;
#11
SELECT COUNT(*)
FROM department d;
#12
SELECT AVG(s.basesalary + s.titleSalary), MAX(s.basesalary + s.titleSalary), MIN(s.basesalary + s.titleSalary)
FROM employee e, salary s
WHERE e.empid = s.empid;
#13
SELECT d.depname, AVG(s.basesalary + s.titleSalary)
FROM employee e, salary s, department d
WHERE e.empid = s.empid AND e.depid = d.depid
GROUP BY d.depid;
#14
SELECT d.depname, AVG(s.basesalary + s.titleSalary) avg
FROM employee e, salary s, department d
WHERE e.empid = s.empid AND e.depid = d.depid
GROUP BY d.depid
HAVING avg<2000;
#15
SELECT e.empid, e.`name`, s.basesalary, s.titleSalary, s.decuction
FROM employee e, salary s, department d
WHERE e.empid = s.empid AND e.depid = d.depid
ORDER BY s.titleSalary, s.basesalary;
#16
SELECT e.empid, e.`name`, e.birthday,
IF(YEAR(e.birthday) < 1980, '老年',
IF(YEAR(e.birthday)< 1990, '中年', '青壮年'))
FROM employee e;
#17
SELECT e.*, depname
FROM employee e, department d
WHERE e.depid = d.depid;
#18
SELECT d.*, e.*
FROM employee e, department d
WHERE e.depid = d.depid;
#19
SELECT *
FROM employee e
WHERE e.title LIKE '%工程师%' AND e.sex = '男';
#20
SELECT d.depname, e.sex, COUNT(*), AVG(s.basesalary)
FROM employee e, department d, salary s
WHERE e.depid = d.depid AND e.empid = s.empid
GROUP BY d.depid, e.sex;
```
---
### 练习四
![image-20250315225803115](https://yp.smallkun.cn/markdown/image-20250315225803115.png!compress)
![image-20250315225818026](https://yp.smallkun.cn/markdown/image-20250315225818026.png!compress)
```sql
#1
CREATE DATABASE test_school DEFAULT CHARACTER SET 'UTF8';
#2
DROP TABLE department;
CREATE TABLE department(
depNo INT(10) PRIMARY KEY COMMENT '部门号',
depName VARCHAR(50) NOT NULL COMMENT '部门名称',
depNote VARCHAR(20) COMMENT '部门备注'
);
CREATE TABLE teacher(
number INT PRIMARY KEY COMMENT '教工号',
`name` VARCHAR(30) NOT NULL COMMENT '姓名',
sex VARCHAR(4) COMMENT '性别',
birth DATE COMMENT '出生日期',
depNo INT COMMENT '部门号',
salary FLOAT COMMENT '工资',
address VARCHAR(100) COMMENT '家庭住址'
);
INSERT INTO department()
VALUES
(601, '软件技术系', '软件技术等专业'),
(602, '网络技术系', '多媒体技术等专业'),
(603, '艺术设计系', '广告艺术设计等专业'),
(604, '管理工程系', '连锁经营管理等专业');
INSERT INTO teacher()
VALUES
(2001, 'Tom', '女', '1970-01-10', 602, 4500, '四川省绵阳市'),
(2002, 'Lucy', '男', '1983-12-18', 601, 2500, '北京市昌平区'),
(2003, 'Mike', '男', '1990-06-01', 604, 1500, '重庆市渝中区'),
(2004, 'James', '女', '1980-10-20', 602, 3500, '四川省成都市'),
(2005, 'Jack', '男', '1975-05-30', 603, 1200, '重庆市南岸区');
```
![image-20250315225829272](https://yp.smallkun.cn/markdown/image-20250315225829272.png!compress)
```sql
#4
SELECT *
FROM teacher;
#5
SELECT t.number '教工号', d.depName '部门名称'
FROM teacher t, department d
WHERE t.depNo = d.depNo AND t.address LIKE '%北京%';
#6
SELECT t.number, t.`name`
FROM teacher t
ORDER BY t.salary DESC
LIMIT 1;
#7
SELECT t.number, t.`name`
FROM teacher t
WHERE t.salary BETWEEN 2500 AND 4000;
#8
SELECT t.`name`, t.sex, t.salary
FROM teacher t, department d
WHERE t.depNo = d.depNo AND d.depName = '网络技术系';
```
---
### 练习五
![image-20250315230015174](https://yp.smallkun.cn/markdown/image-20250315230015174.png!compress)
```sql
-- 创建数据库并设置字符集为 utf8mb4
CREATE DATABASE test_student CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE test_student;
-- 创建表 Classes
CREATE TABLE Classes (
专业 VARCHAR(50),
班级 VARCHAR(50),
姓名 VARCHAR(50),
性别 VARCHAR(10),
座位 INT
);
-- 向表 Classes 插入数据
INSERT INTO Classes (专业, 班级, 姓名, 性别, 座位) VALUES
('计算机网络', '1班', '张三', '男', 8),
('软件工程', '2班', '李四', '男', 12),
('计算机维护', '1班', '王五', '男', 9),
('计算机网络', '2班', 'LILY', '女', 15),
('软件工程', '1班', '小强', '男', 20),
('计算机维护', '1班', 'CoCo', '女', 18);
-- 创建表 Score
CREATE TABLE Score (
姓名 VARCHAR(50),
英语 INT,
数学 INT,
语文 INT
);
-- 向表 Score 插入数据
INSERT INTO Score (姓名, 英语, 数学, 语文) VALUES
('张三', 65, 75, 98),
('李四', 87, 45, 86),
('王五', 98, 85, 65),
('LILY', 75, 86, 87),
('小强', 85, 60, 58),
('CoCo', 96, 87, 70);
-- 创建表 Records
CREATE TABLE Records (
姓名 VARCHAR(50),
记录 VARCHAR(50)
);
-- 向表 Records 插入数据
INSERT INTO Records (姓名, 记录) VALUES
('小强', '迟到'),
('小强', '事假'),
('李四', '旷课'),
('李四', '旷课'),
('李四', '迟到'),
('CoCo', '病假'),
('LILY', '事假');
```
![image-20250315230025538](https://yp.smallkun.cn/markdown/image-20250315230025538.png!compress)
```sql
#3
UPDATE score s
SET s.`语文` = 88
WHERE s.`姓名` = '张三';
#4
SELECT AVG(s.`英语`), AVG(s.`数学`), AVG(s.`语文`)
FROM classes c, score s
WHERE c.`姓名` = s.`姓名` AND c.`班级` = 1 AND c.`专业` = '计算机维护';
#5
SELECT *
FROM score s
WHERE s.`数学` < 60 OR s.`英语` < 60 OR s.`语文` < 60;
#6
SELECT *
FROM score s
WHERE s.`姓名` IN (
SELECT r.`姓名`
FROM records r
GROUP BY r.`姓名`
HAVING COUNT(*) > 2
);
```
---
### 练习六
![image-20250315230057816](https://yp.smallkun.cn/markdown/image-20250315230057816.png!compress)
```sql
-- 创建数据库 test_xuankedb 并设置字符集为 utf8mb4
CREATE DATABASE test_xuankedb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE test_xuankedb;
-- 创建学生表 Student
CREATE TABLE Student (
Sn0 VARCHAR(20) PRIMARY KEY, -- 学号,主键
Sname VARCHAR(50), -- 姓名
Ssex VARCHAR(10), -- 性别
Sage INT, -- 年龄
Sdept VARCHAR(50) -- 所在系
);
-- 创建课程表 Course
CREATE TABLE Course (
Cn0 VARCHAR(20) PRIMARY KEY, -- 课程号,主键
Cname VARCHAR(100), -- 课程名
Cpn0 VARCHAR(20), -- 选修课号
Ccredit INT -- 学分
);
-- 创建成绩表 SG
CREATE TABLE SG (
Sn0 VARCHAR(20), -- 学号
Cn0 VARCHAR(20), -- 课程号
Grade INT, -- 成绩
PRIMARY KEY (Sn0, Cn0), -- 复合主键 (学号, 课程号)
FOREIGN KEY (Sn0) REFERENCES Student(Sn0), -- 外键,引用 Student 表
FOREIGN KEY (Cn0) REFERENCES Course(Cn0) -- 外键,引用 Course 表
);
INSERT INTO Student (Sno, Sname, Ssex, Sage, Sdept, Scome) VALUES
('05001', '张三', '男', 20, '计算机系', '2021-09-01'),
('05002', '李四', '女', 21, '数学系', '2021-09-01'),
('05003', '王五', '男', 22, '计算机系', '2021-09-01'),
('05004', '李洋', '男', 19, '物理系', '2021-09-01'),
('05019', '赵六', '女', 20, '计算机系', '2021-09-01');
INSERT INTO Course (Cno, Cname, Cpno, Ccredit) VALUES
('1', '数据库', NULL, 4),
('2', '数学', NULL, 3),
('3', '物理', NULL, 3),
('4', '操作系统', '1', 4);
INSERT INTO SG (Sno, Cno, Grade) VALUES
('05001', '1', 85),
('05001', '2', 90),
('05002', '1', 78),
('05002', '3', 88),
('05003', '1', 92),
('05003', '4', 76),
('05004', '3', 95),
('05019', '1', 80),
('05019', '4', 85);
```
---
### 练习七
![image-20250315230113710](https://yp.smallkun.cn/markdown/image-20250315230113710.png!compress)
![image-20250315230128412](https://yp.smallkun.cn/markdown/image-20250315230128412.png!compress)
```sql
-- 创建数据库 test_library 并设置字符集为 utf8mb4
CREATE DATABASE test_library CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE test_library;
-- 创建表 press出版社
CREATE TABLE press (
pressid INT PRIMARY KEY, -- 出版社编号,主键
pressname VARCHAR(100), -- 出版社名称
address VARCHAR(100) -- 出版社地址
);
-- 创建表 sort种类
CREATE TABLE sort (
sortno INT PRIMARY KEY, -- 种类编号,主键
scount INT, -- 数量
describes VARCHAR(100) -- 描述
);
-- 创建表 book图书
CREATE TABLE book (
bid INT PRIMARY KEY, -- 图书编号,主键
bname VARCHAR(100), -- 图书名称
bsortno INT, -- 种类编号
pressid INT, -- 出版社编号
FOREIGN KEY (bsortno) REFERENCES sort(sortno), -- 外键,引用 sort 表
FOREIGN KEY (pressid) REFERENCES press(pressid) -- 外键,引用 press 表
);
-- 向 press 表插入数据
INSERT INTO press (pressid, pressname, address) VALUES
(100, '外研社', '上海'),
(101, '北大出版社', '北京'),
(102, '教育出版社', '北京');
-- 向 sort 表插入数据
INSERT INTO sort (sortno, scount, describes) VALUES
(11, 50, '小说'),
(12, 100, '科幻'),
(13, 100, '神话');
-- 向 book 表插入数据
INSERT INTO book (bid, bname, bsortno, pressid) VALUES
(1, '红与黑', 11, 100),
(2, '幻城', 12, 102),
(3, '希腊神话', 13, 102);
#5
SELECT b.*
FROM book b, press p
WHERE p.pressid = b.pressid AND p.pressid = 100;
#6
SELECT b.*
FROM book b, press p
WHERE p.pressid = b.pressid AND p.pressname = '外研社';
#7
SELECT *
FROM sort s
WHERE s.scount > 100;
#8
SELECT p.*
FROM book b, press p
WHERE p.pressid = b.pressid
GROUP BY b.pressid
HAVING COUNT(*) = (
SELECT COUNT(*)
FROM book b, press p
WHERE p.pressid = b.pressid
GROUP BY b.pressid
ORDER BY COUNT(*) DESC
LIMIT 1
);
```
---
### 练习八
![image-20250315230214156](https://yp.smallkun.cn/markdown/image-20250315230214156.png!compress)
![image-20250315230227129](https://yp.smallkun.cn/markdown/image-20250315230227129.png!compress)
```sql
-- 创建数据库 test_tour 并设置字符集为 utf8mb4
CREATE DATABASE test_tour CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE test_tour;
-- 创建表 agency旅行社表
CREATE TABLE agency (
id INT PRIMARY KEY, -- 旅行社编号,主键
name VARCHAR(100) NOT NULL, -- 旅行社名
address VARCHAR(100) NOT NULL, -- 旅行社地址
areaid INT -- 所属区域编号
);
-- 创建表 travel旅行线路表
CREATE TABLE travel (
tid INT PRIMARY KEY, -- 旅行线路编号,主键
time VARCHAR(50) NOT NULL, -- 所需时间
position VARCHAR(100) NOT NULL, -- 目的地
money FLOAT, -- 花费
aid INT NOT NULL, -- 所属旅行社编号
count INT, -- 报名人数
FOREIGN KEY (aid) REFERENCES agency(id) -- 外键,引用 agency 表
);
-- 向 agency 表插入数据
INSERT INTO agency (id, name, address) VALUES
(101, '青年旅行社', '北京海淀'),
(102, '天天旅行社', '天津海院');
-- 向 travel 表插入数据
INSERT INTO travel (tid, time, position, money, aid, count) VALUES
(1, '5天', '八达岭', 3000, 101, 10),
(2, '7天', '水长城', 5000, 101, 14),
(3, '8天', '水长城', 6000, 102, 11);
#4
SELECT a.*
FROM travel t, agency a
WHERE t.aid =a.id
GROUP BY a.id
HAVING COUNT(*) = (
SELECT COUNT(*)
FROM travel t, agency a
WHERE t.aid =a.id
GROUP BY a.id
ORDER BY COUNT(*) DESC
LIMIT 1
);
#5
SELECT t.*
FROM travel t
WHERE t.count = (
SELECT t.count
FROM travel t
ORDER BY t.count DESC
LIMIT 1
);
#6
SELECT *
FROM travel t
WHERE t.money < 5000;
#7
SELECT a.`name`
FROM travel t, agency a
WHERE t.aid =a.id AND t.money = (
SELECT t.money
FROM travel t, agency a
WHERE t.aid =a.id
ORDER BY t.money DESC
LIMIT 1
);
#8
SELECT SUM(t.time)
FROM travel t, agency a
WHERE t.aid =a.id AND a.`name` = '青年旅行社';
```

View File

@ -0,0 +1,155 @@
### 语法结构
```sql
DELIMITER //
CREATE FUNCTION calculate_annual_salary (
monthly_salary DECIMAL(10, 2)
)
RETURNS DECIMAL(10, 2)
DETERMINISTIC | NOT DETERMINISTIC #结果确定/不确定
BEGIN
RETURN monthly_salary * 12;
END //
DELIMITER ;
```
### 表结构与数据
```sql
-- 创建数据库
CREATE DATABASE company CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 使用数据库
USE company;
-- 创建 department 表
CREATE TABLE department (
dept_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '部门ID主键',
dept_name VARCHAR(100) NOT NULL COMMENT '部门名称',
location VARCHAR(100) NOT NULL COMMENT '部门所在地'
);
-- 创建 job 表
CREATE TABLE job (
job_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '职位ID主键',
job_title VARCHAR(100) NOT NULL COMMENT '职位名称',
min_salary DECIMAL(10, 2) NOT NULL COMMENT '最低工资',
max_salary DECIMAL(10, 2) NOT NULL COMMENT '最高工资'
);
-- 创建 employee 表
CREATE TABLE employee (
emp_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '员工ID主键',
emp_name VARCHAR(100) NOT NULL COMMENT '员工姓名',
salary DECIMAL(10, 2) NOT NULL COMMENT '员工工资',
hire_date DATE NOT NULL COMMENT '入职日期',
dept_id INT COMMENT '部门ID外键',
job_id INT COMMENT '职位ID外键',
FOREIGN KEY (dept_id) REFERENCES department(dept_id),
FOREIGN KEY (job_id) REFERENCES job(job_id)
);
INSERT INTO department (dept_name, location) VALUES
('HR', 'New York'),
('IT', 'San Francisco'),
('Finance', 'Chicago'),
('Marketing', 'Los Angeles'),
('Sales', 'Boston'),
('Operations', 'Houston'),
('Research', 'Seattle'),
('Customer Support', 'Austin');
INSERT INTO job (job_title, min_salary, max_salary) VALUES
('Manager', 60000.00, 100000.00),
('Developer', 50000.00, 80000.00),
('Analyst', 45000.00, 70000.00),
('Designer', 40000.00, 65000.00),
('Sales Executive', 35000.00, 60000.00),
('HR Specialist', 40000.00, 70000.00),
('Finance Analyst', 50000.00, 75000.00),
('Marketing Coordinator', 45000.00, 70000.00),
('Operations Manager', 55000.00, 90000.00),
('Research Scientist', 60000.00, 95000.00),
('Customer Support Representative', 35000.00, 55000.00);
INSERT INTO employee (emp_name, salary, hire_date, dept_id, job_id) VALUES
('Alice', 70000.00, '2020-01-15', 1, 1),
('Bob', 65000.00, '2019-03-22', 2, 2),
('Charlie', 55000.00, '2018-07-30', 2, 3),
('David', 60000.00, '2021-05-10', 3, 4),
('Eva', 50000.00, '2017-11-05', 4, 5),
('Frank', 75000.00, '2016-09-12', 5, 1),
('Grace', 48000.00, '2022-02-20', 1, 2),
('Henry', 52000.00, '2021-08-15', 2, 3),
('Ivy', 58000.00, '2020-04-10', 3, 4),
('Jack', 62000.00, '2019-12-01', 4, 5),
('Katie', 53000.00, '2021-07-25', 5, 6),
('Leo', 67000.00, '2018-05-18', 6, 7),
('Mona', 49000.00, '2020-11-30', 7, 8),
('Nina', 71000.00, '2019-02-14', 8, 9),
('Oscar', 56000.00, '2022-03-05', 1, 10),
('Paul', 63000.00, '2021-09-12', 2, 11),
('Quincy', 54000.00, '2020-06-20', 3, 1),
('Rachel', 59000.00, '2019-08-15', 4, 2),
('Steve', 68000.00, '2018-12-10', 5, 3),
('Tina', 51000.00, '2022-01-22', 6, 4),
('Uma', 72000.00, '2021-04-18', 7, 5),
('Victor', 57000.00, '2020-07-30', 8, 6),
('Wendy', 64000.00, '2019-10-05', 1, 7),
('Xander', 50000.00, '2022-05-12', 2, 8),
('Yara', 69000.00, '2021-03-25', 3, 9),
('Zack', 55000.00, '2020-09-15', 4, 10),
('Amy', 61000.00, '2019-06-20', 5, 11),
('Brian', 74000.00, '2018-04-10', 6, 1),
('Cathy', 52000.00, '2022-07-18', 7, 2),
('Derek', 67000.00, '2021-12-01', 8, 3);
```
### 练习题
#### 练习题 1: 计算员工年薪
创建一个存储函数 `calculate_annual_salary`,接受员工的月薪作为参数,返回其年薪(假设年薪为月薪的 12 倍)。
#### 练习题 2: 计算员工工龄
创建一个存储函数 `calculate_years_of_service`,接受员工的入职日期作为参数,返回该员工的工龄(以年为单位)。
#### 练习题 3: 根据部门计算平均工资
创建一个存储函数 `calculate_avg_salary_by_dept`,接受部门 ID 作为参数,返回该部门的平均工资。
#### 练习题 4: 根据职位计算平均工资
创建一个存储函数 `calculate_avg_salary_by_job`,接受职位 ID 作为参数,返回该职位的平均工资。
#### 练习题 5: 计算员工税后工资
创建一个存储函数 `calculate_net_salary`,接受员工的工资作为参数,返回其税后工资(假设税率为 15%)。
#### 练习题 6: 判断员工是否满足加薪条件
创建一个存储函数 `is_eligible_for_raise`接受员工的工资和工龄作为参数返回一个布尔值1 或 0。加薪条件如下
- 如果工资低于 60000 且工龄大于等于 3 年,返回 1满足条件
- 否则返回 0不满足条件
#### 练习题 7: 计算部门总工资
创建一个存储函数 `calculate_total_salary_by_dept`,接受部门 ID 作为参数,返回该部所有员工的总工资。
#### 练习题 8: 计算职位总工资
创建一个存储函数 `calculate_total_salary_by_job`,接受职位 ID 作为参数,返回该职位所有员工的总工资。
#### 练习题 9: 判断员工是否属于高薪部门
创建一个存储函数 `is_high_salary_department`,接受部门 ID 作为参数返回一个布尔值1 或 0。如果该部门的平均工资大于等于 70000返回 1高薪部门否则返回 0非高薪部门
#### 练习题 10: 计算员工的总收入
创建一个存储函数 `calculate_total_income`,接受员工的工资和奖金(假设奖金为工资的 10%)作为参数,返回其总收入(工资 + 奖金)。

View File

@ -0,0 +1,529 @@
### 语法结构
```sql
DELIMITER //
CREATE PROCEDURE GetEmployeeCountByDept (
IN dept_id INT,
OUT employee_count INT
)
BEGIN
SELECT COUNT(*) INTO employee_count
FROM employee
WHERE dept_id = dept_id;
END //
DELIMITER ;
IF condition THEN
-- 条件为真时执行的代码
ELSEIF another_condition THEN
-- 另一个条件为真时执行的代码
ELSE
-- 所有条件都不满足时执行的代码
END IF;
CASE expression
WHEN value1 THEN
-- 当 expression = value1 时执行的代码
WHEN value2 THEN
-- 当 expression = value2 时执行的代码
ELSE
-- 当 expression 不匹配任何值时执行的代码
END CASE;
CASE
WHEN condition1 THEN
-- 当 condition1 为真时执行的代码
WHEN condition2 THEN
-- 当 condition2 为真时执行的代码
ELSE
-- 当所有条件都不满足时执行的代码
END CASE;
```
---
### 表结构与数据
```sql
-- 创建数据库
CREATE DATABASE company CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 使用数据库
USE company;
-- 创建 department 表
CREATE TABLE department (
dept_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '部门ID主键',
dept_name VARCHAR(100) NOT NULL COMMENT '部门名称',
location VARCHAR(100) NOT NULL COMMENT '部门所在地'
);
-- 创建 job 表
CREATE TABLE job (
job_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '职位ID主键',
job_title VARCHAR(100) NOT NULL COMMENT '职位名称',
min_salary DECIMAL(10, 2) NOT NULL COMMENT '最低工资',
max_salary DECIMAL(10, 2) NOT NULL COMMENT '最高工资'
);
-- 创建 employee 表
CREATE TABLE employee (
emp_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '员工ID主键',
emp_name VARCHAR(100) NOT NULL COMMENT '员工姓名',
salary DECIMAL(10, 2) NOT NULL COMMENT '员工工资',
hire_date DATE NOT NULL COMMENT '入职日期',
dept_id INT COMMENT '部门ID外键',
job_id INT COMMENT '职位ID外键',
FOREIGN KEY (dept_id) REFERENCES department(dept_id),
FOREIGN KEY (job_id) REFERENCES job(job_id)
);
INSERT INTO department (dept_name, location) VALUES
('HR', 'New York'),
('IT', 'San Francisco'),
('Finance', 'Chicago'),
('Marketing', 'Los Angeles'),
('Sales', 'Boston'),
('Operations', 'Houston'),
('Research', 'Seattle'),
('Customer Support', 'Austin');
INSERT INTO job (job_title, min_salary, max_salary) VALUES
('Manager', 60000.00, 100000.00),
('Developer', 50000.00, 80000.00),
('Analyst', 45000.00, 70000.00),
('Designer', 40000.00, 65000.00),
('Sales Executive', 35000.00, 60000.00),
('HR Specialist', 40000.00, 70000.00),
('Finance Analyst', 50000.00, 75000.00),
('Marketing Coordinator', 45000.00, 70000.00),
('Operations Manager', 55000.00, 90000.00),
('Research Scientist', 60000.00, 95000.00),
('Customer Support Representative', 35000.00, 55000.00);
INSERT INTO employee (emp_name, salary, hire_date, dept_id, job_id) VALUES
('Alice', 70000.00, '2020-01-15', 1, 1),
('Bob', 65000.00, '2019-03-22', 2, 2),
('Charlie', 55000.00, '2018-07-30', 2, 3),
('David', 60000.00, '2021-05-10', 3, 4),
('Eva', 50000.00, '2017-11-05', 4, 5),
('Frank', 75000.00, '2016-09-12', 5, 1),
('Grace', 48000.00, '2022-02-20', 1, 2),
('Henry', 52000.00, '2021-08-15', 2, 3),
('Ivy', 58000.00, '2020-04-10', 3, 4),
('Jack', 62000.00, '2019-12-01', 4, 5),
('Katie', 53000.00, '2021-07-25', 5, 6),
('Leo', 67000.00, '2018-05-18', 6, 7),
('Mona', 49000.00, '2020-11-30', 7, 8),
('Nina', 71000.00, '2019-02-14', 8, 9),
('Oscar', 56000.00, '2022-03-05', 1, 10),
('Paul', 63000.00, '2021-09-12', 2, 11),
('Quincy', 54000.00, '2020-06-20', 3, 1),
('Rachel', 59000.00, '2019-08-15', 4, 2),
('Steve', 68000.00, '2018-12-10', 5, 3),
('Tina', 51000.00, '2022-01-22', 6, 4),
('Uma', 72000.00, '2021-04-18', 7, 5),
('Victor', 57000.00, '2020-07-30', 8, 6),
('Wendy', 64000.00, '2019-10-05', 1, 7),
('Xander', 50000.00, '2022-05-12', 2, 8),
('Yara', 69000.00, '2021-03-25', 3, 9),
('Zack', 55000.00, '2020-09-15', 4, 10),
('Amy', 61000.00, '2019-06-20', 5, 11),
('Brian', 74000.00, '2018-04-10', 6, 1),
('Cathy', 52000.00, '2022-07-18', 7, 2),
('Derek', 67000.00, '2021-12-01', 8, 3);
```
---
### 练习题
#### 练习题 1: 插入新员工
创建一个存储过程 `add_employee`接受员工姓名、工资、入职日期、部门ID和职位ID作为参数并将其插入到 `employee` 表中。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS add_employee;
CREATE PROCEDURE add_employee(IN emp_name VARCHAR(100), IN salary DECIMAL(10,2), IN hire_date DATE, IN dept_id INT, IN job_id INT)
BEGIN
INSERT INTO employee()
VALUES(DEFAULT, emp_name, salary, hire_date, dept_id, job_id);
END $$
DELIMITER ;
CALL add_employee('李泽龙', 6666, '2025-3-20', 1, 1);
```
#### 练习题 2: 更新员工工资
创建一个存储过程 `update_employee_salary`接受员工ID和新的工资作为参数更新该员工的工资。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS update_employee_salary;
CREATE PROCEDURE update_employee_salary(IN emp_id INT, IN salary DECIMAL(10, 2))
BEGIN
UPDATE employee e
SET e.salary = salary
WHERE e.emp_id = emp_id;
END $$
DELIMITER ;
CALL update_employee_salary(1, 60000);
```
#### 练习题 3: 删除员工
创建一个存储过程 `delete_employee`接受员工ID作为参数删除该员工的记录。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS delete_employee;
CREATE PROCEDURE delete_employee(IN id INT)
BEGIN
DELETE FROM employee
WHERE emp_id = id;
END $$
DELIMITER ;
CALL delete_employee(1);
```
#### 练习题 4: 查询部门员工
创建一个存储过程 `get_department_employees`接受部门ID作为参数返回该部门所有员工的详细信息。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_department_employees;
CREATE PROCEDURE get_department_employees(IN id INT)
BEGIN
SELECT e.*
FROM employee e
WHERE e.dept_id = id;
END $$
DELIMITER ;
CALL get_department_employees(1);
```
#### 练习题 5: 查询职位员工
创建一个存储过程 `get_job_employees`接受职位ID作为参数返回该职位所有员工的详细信息。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_job_employees;
CREATE PROCEDURE get_job_employees(IN id INT)
BEGIN
SELECT e.*
FROM employee e
WHERE e.job_id = id;
END $$
DELIMITER ;
CALL get_job_employees(1);
```
#### 练习题 6: 计算部门平均工资
创建一个存储过程 `calculate_avg_salary_by_dept`接受部门ID作为参数返回该部门的平均工资。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS calculate_avg_salary_by_dept;
CREATE PROCEDURE calculate_avg_salary_by_dept(IN id INT)
BEGIN
SELECT AVG(e.salary)
FROM employee e
WHERE e.dept_id = id;
END $$
DELIMITER ;
CALL calculate_avg_salary_by_dept(1);
```
#### 练习题 7: 计算职位平均工资
创建一个存储过程 `calculate_avg_salary_by_job`接受职位ID作为参数返回该职位的平均工资。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS calculate_avg_salary_by_job;
CREATE PROCEDURE calculate_avg_salary_by_job(IN id INT)
BEGIN
SELECT AVG(e.salary)
FROM employee e
WHERE e.job_id = id;
END $$
DELIMITER ;
CALL calculate_avg_salary_by_job(1);
```
#### 练习题 8: 查询高薪员工
创建一个存储过程 `get_high_salary_employees`,接受一个工资阈值作为参数,返回所有工资高于该阈值的员工。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_high_salary_employees;
CREATE PROCEDURE get_high_salary_employees(IN sal DECIMAL(10, 2))
BEGIN
SELECT e.*
FROM employee e
WHERE e.salary > sal;
END $$
DELIMITER ;
CALL get_high_salary_employees(50000);
```
#### 练习题 9: 查询员工工龄
创建一个存储过程 `get_employee_years_of_service`接受员工ID作为参数返回该员工的工龄以年为单位
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_employee_years_of_service;
CREATE PROCEDURE get_employee_years_of_service(IN id INT)
BEGIN
SELECT -TIMESTAMPDIFF(YEAR,NOW(),e.hire_date)
FROM employee e
WHERE e.emp_id = id;
END $$
DELIMITER ;
CALL get_employee_years_of_service(1);
```
#### 练习题 10: 查询部门员工总数
创建一个存储过程 `get_department_employee_count`接受部门ID作为参数返回该部门的员工总数。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_department_employee_count;
CREATE PROCEDURE get_department_employee_count(IN id INT)
BEGIN
SELECT COUNT(*)
FROM employee e
WHERE e.dept_id = id;
END $$
DELIMITER ;
CALL get_department_employee_count(1);
```
#### 练习题 11: 查询职位员工总数
创建一个存储过程 `get_job_employee_count`接受职位ID作为参数返回该职位的员工总数。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_job_employee_count;
CREATE PROCEDURE get_job_employee_count(IN id INT)
BEGIN
SELECT COUNT(*)
FROM employee e
WHERE e.job_id = id;
END $$
DELIMITER ;
CALL get_job_employee_count(1);
```
#### 练习题 12: 查询员工详细信息
创建一个存储过程 `get_employee_details`接受员工ID作为参数返回该员工的姓名、工资、部门名称和职位名称。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_employee_details;
CREATE PROCEDURE get_employee_details(IN emp_id INT)
BEGIN
SELECT e.emp_name, e.salary, d.dept_name, j.job_title
FROM employee e, department d, job j
WHERE e.emp_id = emp_id AND e.dept_id = d.dept_id AND e.job_id = j.job_id;
END $$
DELIMITER ;
CALL get_employee_details(1);
```
#### 练习题 13: 查询部门最高工资
创建一个存储过程 `get_department_max_salary`接受部门ID作为参数返回该部门的最高工资。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_department_max_salary;
CREATE PROCEDURE get_department_max_salary(IN id INT)
BEGIN
SELECT MAX(e.salary)
FROM employee e
WHERE e.dept_id = id;
END $$
DELIMITER ;
CALL get_department_max_salary(1);
```
#### 练习题 14: 查询职位最低工资
创建一个存储过程 `get_job_min_salary`接受职位ID作为参数返回该职位的最低工资。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_job_min_salary;
CREATE PROCEDURE get_job_min_salary(IN id INT)
BEGIN
SELECT MIN(e.salary)
FROM employee e
WHERE e.dept_id = id;
END $$
DELIMITER ;
CALL get_job_min_salary(1);
```
#### 练习题 15: 查询员工工资排名
创建一个存储过程 `get_employee_salary_rank`接受员工ID作为参数返回该员工在公司中的工资排名。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_employee_salary_rank;
CREATE PROCEDURE get_employee_salary_rank(IN emp_id INT)
BEGIN
SELECT COUNT(*) + 1
FROM employee e
WHERE e.salary > (
SELECT e.salary
FROM employee e
WHERE e.emp_id = emp_id
);
END $$
DELIMITER ;
CALL get_employee_salary_rank(2);
```
#### 练习题 16: 查询部门工资总和
创建一个存储过程 `get_department_total_salary`接受部门ID作为参数返回该部门所有员工的工资总和。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_department_total_salary;
CREATE PROCEDURE get_department_total_salary(IN id INT)
BEGIN
SELECT SUM(e.salary)
FROM employee e
WHERE e.dept_id = id;
END $$
DELIMITER ;
CALL get_department_total_salary(1);
```
#### 练习题 17: 查询职位工资总和
创建一个存储过程 `get_job_total_salary`接受职位ID作为参数返回该职位所有员工的工资总和。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_job_total_salary;
CREATE PROCEDURE get_job_total_salary(IN id INT)
BEGIN
SELECT SUM(e.salary)
FROM employee e
WHERE e.job_id = id;
END $$
DELIMITER ;
CALL get_job_total_salary(1);
```
#### 练习题 18: 查询员工入职年份分布
创建一个存储过程 `get_employees_by_hire_year`,接受年份作为参数,返回该年份入职的所有员工。
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_employees_by_hire_year;
CREATE PROCEDURE get_employees_by_hire_year(IN y INT)
BEGIN
SELECT *
FROM employee e
WHERE YEAR(e.hire_date) = y;
END $$
DELIMITER ;
CALL get_employees_by_hire_year(2020);
```
#### 练习题 19: 查询部门工资分布
创建一个存储过程 `get_department_salary_distribution`接受部门ID作为参数返回该部门工资的分布情况如最高、最低、平均工资
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_department_salary_distribution;
CREATE PROCEDURE get_department_salary_distribution(IN id INT)
BEGIN
SELECT MAX(e.salary), MIN(e.salary), AVG(e.salary)
FROM employee e
WHERE e.dept_id = id;
END $$
DELIMITER ;
CALL get_department_salary_distribution(1);
```
#### 练习题 20: 查询职位工资分布
创建一个存储过程 `get_job_salary_distribution`接受职位ID作为参数返回该职位工资的分布情况如最高、最低、平均工资
```sql
DELIMITER $$
DROP PROCEDURE IF EXISTS get_job_salary_distribution;
CREATE PROCEDURE get_job_salary_distribution(IN id INT)
BEGIN
SELECT MAX(e.salary), MIN(e.salary), AVG(e.salary)
FROM employee e
WHERE e.job_id = id;
END $$
DELIMITER ;
CALL get_job_salary_distribution(1);
```

View File

@ -0,0 +1,610 @@
### 语法结构
```sql
DELIMITER //
CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE} ON table_name
FOR EACH ROW
BEGIN
-- 触发器的逻辑代码
-- 可以包含 SQL 语句、流程控制语句(如 IF、CASE 等)、变量声明等
END//
DELIMITER ;
```
### 表结构和数据
```sql
-- 创建数据库
CREATE DATABASE company CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 使用数据库
USE company;
-- 创建 department 表
CREATE TABLE department (
dept_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '部门ID主键',
dept_name VARCHAR(100) NOT NULL COMMENT '部门名称',
location VARCHAR(100) NOT NULL COMMENT '部门所在地'
);
-- 创建 job 表
CREATE TABLE job (
job_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '职位ID主键',
job_title VARCHAR(100) NOT NULL COMMENT '职位名称',
min_salary DECIMAL(10, 2) NOT NULL COMMENT '最低工资',
max_salary DECIMAL(10, 2) NOT NULL COMMENT '最高工资'
);
-- 创建 employee 表
CREATE TABLE employee (
emp_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '员工ID主键',
emp_name VARCHAR(100) NOT NULL COMMENT '员工姓名',
salary DECIMAL(10, 2) NOT NULL COMMENT '员工工资',
hire_date DATE NOT NULL COMMENT '入职日期',
dept_id INT COMMENT '部门ID外键',
job_id INT COMMENT '职位ID外键',
FOREIGN KEY (dept_id) REFERENCES department(dept_id),
FOREIGN KEY (job_id) REFERENCES job(job_id)
);
INSERT INTO department (dept_name, location) VALUES
('HR', 'New York'),
('IT', 'San Francisco'),
('Finance', 'Chicago'),
('Marketing', 'Los Angeles'),
('Sales', 'Boston'),
('Operations', 'Houston'),
('Research', 'Seattle'),
('Customer Support', 'Austin');
INSERT INTO job (job_title, min_salary, max_salary) VALUES
('Manager', 60000.00, 100000.00),
('Developer', 50000.00, 80000.00),
('Analyst', 45000.00, 70000.00),
('Designer', 40000.00, 65000.00),
('Sales Executive', 35000.00, 60000.00),
('HR Specialist', 40000.00, 70000.00),
('Finance Analyst', 50000.00, 75000.00),
('Marketing Coordinator', 45000.00, 70000.00),
('Operations Manager', 55000.00, 90000.00),
('Research Scientist', 60000.00, 95000.00),
('Customer Support Representative', 35000.00, 55000.00);
INSERT INTO employee (emp_name, salary, hire_date, dept_id, job_id) VALUES
('Alice', 70000.00, '2020-01-15', 1, 1),
('Bob', 65000.00, '2019-03-22', 2, 2),
('Charlie', 55000.00, '2018-07-30', 2, 3),
('David', 60000.00, '2021-05-10', 3, 4),
('Eva', 50000.00, '2017-11-05', 4, 5),
('Frank', 75000.00, '2016-09-12', 5, 1),
('Grace', 48000.00, '2022-02-20', 1, 2),
('Henry', 52000.00, '2021-08-15', 2, 3),
('Ivy', 58000.00, '2020-04-10', 3, 4),
('Jack', 62000.00, '2019-12-01', 4, 5),
('Katie', 53000.00, '2021-07-25', 5, 6),
('Leo', 67000.00, '2018-05-18', 6, 7),
('Mona', 49000.00, '2020-11-30', 7, 8),
('Nina', 71000.00, '2019-02-14', 8, 9),
('Oscar', 56000.00, '2022-03-05', 1, 10),
('Paul', 63000.00, '2021-09-12', 2, 11),
('Quincy', 54000.00, '2020-06-20', 3, 1),
('Rachel', 59000.00, '2019-08-15', 4, 2),
('Steve', 68000.00, '2018-12-10', 5, 3),
('Tina', 51000.00, '2022-01-22', 6, 4),
('Uma', 72000.00, '2021-04-18', 7, 5),
('Victor', 57000.00, '2020-07-30', 8, 6),
('Wendy', 64000.00, '2019-10-05', 1, 7),
('Xander', 50000.00, '2022-05-12', 2, 8),
('Yara', 69000.00, '2021-03-25', 3, 9),
('Zack', 55000.00, '2020-09-15', 4, 10),
('Amy', 61000.00, '2019-06-20', 5, 11),
('Brian', 74000.00, '2018-04-10', 6, 1),
('Cathy', 52000.00, '2022-07-18', 7, 2),
('Derek', 67000.00, '2021-12-01', 8, 3);
```
### `SIGNAL` 语句的基本语法
```sql
SIGNAL SQLSTATE '状态码'
SET MESSAGE_TEXT = '错误消息';
```
- **SQLSTATE**:一个 5 字符的字符串表示错误的状态码。MySQL 使用 `'45000'` 表示用户定义的错误。
- **MESSAGE_TEXT**:自定义的错误消息,用于描述错误的原因。
### 练习题
#### 练习题 1: 工资范围验证
创建一个触发器 `before_employee_insert`,在插入 `employee` 表数据之前,检查员工的工资是否在其对应职位的 `min_salary``max_salary` 范围内。如果超出范围,阻止插入并抛出错误。
```sql
DELIMITER $$
DROP TRIGGER IF EXISTS before_employee_insert;
CREATE TRIGGER before_employee_insert
BEFORE INSERT ON employee
FOR EACH ROW
BEGIN
IF NEW.salary > (
SELECT j.max_salary
FROM job j
WHERE j.job_id = NEW.job_id
) OR NEW.salary < (
SELECT j.min_salary
FROM job j
WHERE j.job_id = NEW.job_id
) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '工资值错误,不在职务工资范围内';
END IF;
END $$
DELIMITER ;
INSERT INTO employee
VALUES(DEFAULT, '雷昊', 0, NOW(), 1, 1);
```
#### 练习题 2: 自动更新部门人数
创建一个触发器 `after_employee_insert`,在插入 `employee` 表数据之后,自动更新 `department` 表中的部门人数(假设 `department` 表新增一个字段 `employee_count`)。
```sql
ALTER TABLE department ADD employee_count INT UNSIGNED;
DELIMITER $$
DROP TRIGGER IF EXISTS after_employee_insert;
CREATE TRIGGER after_employee_insert
AFTER INSERT ON employee
FOR EACH ROW
BEGIN
UPDATE department d
SET d.employee_count = (
SELECT COUNT(*)
FROM employee e
WHERE e.dept_id = d.dept_id
);
END $$
DELIMITER ;
INSERT INTO employee
VALUES(DEFAULT, '雷昊', 60000.00, NOW(), 1, 1);
```
#### 练习题 3: 工资变更日志
创建一个触发器 `after_employee_update`,在更新 `employee` 表的 `salary` 字段后,将变更记录插入到一个新的日志表 `salary_log` 中,记录员工 ID、旧工资、新工资和变更时间。
```sql
DROP TABLE IF EXISTS salary_log;
CREATE TABLE salary_log(
emp_id INT,
old_salary DECIMAL(10, 2),
new_slaray DECIMAL(10, 2),
update_date DATE
);
DELIMITER $$
DROP TRIGGER IF EXISTS after_employee_update;
CREATE TRIGGER after_employee_update
BEFORE UPDATE ON employee
FOR EACH ROW
BEGIN
IF NEW.salary <> OLD.salary THEN
INSERT INTO salary_log()
VALUES(NEW.emp_id, OLD.salary, NEW.salary, NOW());
END IF;
END $$
DELIMITER ;
UPDATE employee e
SET e.salary = 10
WHERE e.emp_id = 1;
```
#### 练习题 4: 删除员工时备份数据
创建一个触发器 `before_employee_delete`,在删除 `employee` 表数据之前,将被删除的员工数据插入到一个备份表 `employee_backup` 中。
```sql
CREATE TABLE employee_backup AS
SELECT *
FROM employee
WHERE 0;
DELIMITER $$
DROP TRIGGER IF EXISTS before_employee_delete;
CREATE TRIGGER before_employee_delete
BEFORE DELETE ON employee
FOR EACH ROW
BEGIN
INSERT INTO employee_backup()
VALUES(OLD.emp_id, OLD.emp_name, OLD.salary, OLD.hire_date, OLD.dept_id, OLD.job_id);
END $$
DELIMITER ;
DELETE FROM employee
WHERE emp_id = 20;
```
#### 练习题 5: 自动设置默认职位
创建一个触发器 `before_employee_insert`,在插入 `employee` 表数据时,如果未指定 `job_id`,则自动将其设置为 `job` 表中的默认职位(假设默认职位的 `job_id` 为 1
```sql
DELIMITER $$
DROP TRIGGER IF EXISTS before_employee_insert;
CREATE TRIGGER before_employee_insert
BEFORE INSERT ON employee
FOR EACH ROW
BEGIN
IF NEW.job_id IS NULL THEN
SET NEW.job_id = 1;
END IF;
END $$
DELIMITER ;
INSERT INTO employee
VALUES(DEFAULT, '雷昊', 60000.00, NOW(), 1, NULL);
```
#### 练习题 6: 防止修改入职日期
创建一个触发器 `before_employee_update`,在更新 `employee` 表数据时,防止修改 `hire_date` 字段。如果尝试修改,抛出错误。
```sql
DELIMITER $$
DROP TRIGGER IF EXISTS before_employee_update;
CREATE TRIGGER before_employee_update
BEFORE UPDATE ON employee
FOR EACH ROW
BEGIN
IF NEW.hire_date <> OLD.hire_date THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT='不允许修改用户的入职时间';
END IF;
END $$
DELIMITER ;
UPDATE employee e
SET e.hire_date = '2025-3-20'
WHERE e.emp_id = 1;
```
#### 练习题 7: 自动计算工龄
创建一个触发器 `before_employee_insert`,在插入 `employee` 表数据时,自动计算员工的工龄(以年为单位),并将其存储到一个新字段 `years_of_service` 中。
```sql
ALTER TABLE employee ADD years_of_service INT;
DELIMITER $$
DROP TRIGGER IF EXISTS before_employee_insert;
CREATE TRIGGER before_employee_insert
BEFORE INSERT ON employee
FOR EACH ROW
BEGIN
SET NEW.years_of_service = TIMESTAMPDIFF(YEAR,NEW.hire_date,NOW());
END $$
DELIMITER ;
SELECT TIMESTAMPDIFF(YEAR,e.hire_date,NOW())
FROM employee e;
INSERT INTO employee
VALUES(DEFAULT, '雷昊', 60000.00, '2022-12-31', 1, 1, NULL);
```
#### 练习题 8: 防止删除部门
创建一个触发器 `before_department_delete`,在删除 `department` 表数据之前,检查该部门是否还有员工。如果有员工,阻止删除并抛出错误。
```sql
DELIMITER $$
DROP TRIGGER IF EXISTS before_department_delete;
CREATE TRIGGER before_department_delete
BEFORE DELETE ON department
FOR EACH ROW
BEGIN
IF (SELECT COUNT(*) FROM employee e WHERE e.dept_id = OLD.dept_id) > 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '该部门有员工无法删除';
END IF;
END $$
DELIMITER ;
DELETE FROM department
WHERE dept_id = 1;
```
#### 练习题 9: 自动更新职位工资范围
创建一个触发器 `after_job_update`,在更新 `job` 表的 `min_salary``max_salary` 字段后,自动调整 `employee` 表中相关员工的工资,使其符合新的工资范围。
```sql
DELIMITER $$
DROP TRIGGER IF EXISTS after_job_update;
CREATE TRIGGER after_job_update
AFTER UPDATE ON job
FOR EACH ROW
BEGIN
UPDATE employee
SET salary = IF(salary > NEW.max_salary, NEW.max_salary, IF(salary < NEW.min_salary, min_salary, salary))
WHERE job_id = NEW.job_id;
END $$
DELIMITER ;
```
#### 练习题 10: 记录部门变更
创建一个触发器 `after_employee_update`,在更新 `employee` 表的 `dept_id` 字段后,将变更记录插入到一个新的日志表 `department_change_log` 中,记录员工 ID、旧部门 ID、新部门 ID 和变更时间。
```sql
CREATE TABLE department_change_log(
emp_id INT,
old_dept_id INT,
new_dept_id INT,
update_date DATE
);
DELIMITER $$
DROP TRIGGER IF EXISTS after_employee_update;
CREATE TRIGGER after_employee_update
AFTER UPDATE ON employee
FOR EACH ROW
BEGIN
IF NEW.dept_id <> OLD.dept_id THEN
INSERT INTO department_change_log()
VALUES(NEW.emp_id, OLD.dept_id, NEW.dept_id, NOW());
END IF;
END $$
DELIMITER ;
```
#### 练习题 11: 防止插入重复职位
创建一个触发器 `before_job_insert`,在插入 `job` 表数据之前,检查职位名称是否已存在。如果存在,阻止插入并抛出错误。
```sql
DELIMITER $$
DROP TRIGGER IF EXISTS before_job_insert;
CREATE TRIGGER before_job_insert
BEFORE INSERT ON job
FOR EACH ROW
BEGIN
IF (SELECT COUNT(*) FROM job WHERE job_id = NEW.job_id) = 1 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '职位名称已存在';
END IF;
END $$
DELIMITER ;
```
#### 练习题 12: 自动更新员工总数
创建一个触发器 `after_employee_insert`,在插入 `employee` 表数据之后,自动更新一个统计表 `employee_statistics` 中的员工总数。
```sql
CREATE TABLE employee_statistics(
marking VARCHAR(20),
num INT
);
INSERT INTO employee_statistics()
VALUES('count', 0);
DELIMITER $$
DROP TRIGGER IF EXISTS after_employee_insert;
CREATE TRIGGER after_employee_insert
AFTER INSERT ON employee
FOR EACH ROW
BEGIN
UPDATE employee_statistics
SET num = (SELECT COUNT(*) FROM employee)
WHERE marking = 'count';
END $$
DELIMITER ;
```
#### 练习题 13: 防止修改部门所在地
创建一个触发器 `before_department_update`,在更新 `department` 表数据时,防止修改 `location` 字段。如果尝试修改,抛出错误。
```sql
DELIMITER $$
DROP TRIGGER IF EXISTS before_department_update;
CREATE TRIGGER before_department_update
BEFORE UPDATE ON department
FOR EACH ROW
BEGIN
IF NEW.location <> OLD.location THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '无法更新部分的位置';
END IF;
END $$
DELIMITER ;
```
#### 练习题 14: 自动调整工资
创建一个触发器 `before_employee_insert`,在插入 `employee` 表数据时,如果工资低于职位的最低工资,则自动将其调整为最低工资。
```sql
DELIMITER $$
DROP TRIGGER IF EXISTS before_employee_insert;
CREATE TRIGGER before_employee_insert
BEFORE INSERT ON employee
FOR EACH ROW
BEGIN
IF NEW.salary < (SELECT min_salary FROM job WHERE job_id = NEW.job_id ) THEN
SET NEW.salary = min_salary;
END IF;
END $$
DELIMITER ;
```
#### 练习题 15: 记录职位变更
创建一个触发器 `after_employee_update`,在更新 `employee` 表的 `job_id` 字段后,将变更记录插入到一个新的日志表 `job_change_log` 中,记录员工 ID、旧职位 ID、新职位 ID 和变更时间。
```sql
CREATE TABLE job_change_log(
emp_id INT,
old_job_id INT,
new_job_id INT,
update_date DATE
);
DELIMITER $$
DROP TRIGGER IF EXISTS after_employee_update;
CREATE TRIGGER after_employee_update
AFTER UPDATE ON employee
FOR EACH ROW
BEGIN
IF NEW.job_id <> OLD.job_id THEN
INSERT INTO job_change_log()
VALUES(NEW.emp_id, OLD.job_id, NEW.job_id, NOW());
END IF;
END $$
DELIMITER ;
```
#### 练习题 16: 防止删除职位
创建一个触发器 `before_job_delete`,在删除 `job` 表数据之前,检查该职位是否还有员工。如果有员工,阻止删除并抛出错误。
```sql
DELIMITER $$
DROP TRIGGER IF EXISTS before_job_delete;
CREATE TRIGGER before_job_delete
BEFORE DELETE ON job
FOR EACH ROW
BEGIN
IF (SELECT COUNT(*) FROM employee WHERE job_id = OLD.job_id) > 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '该职位还有员工';
END IF;
END $$
DELIMITER ;
```
#### 练习题 17: 自动更新部门平均工资
创建一个触发器 `after_employee_insert`,在插入 `employee` 表数据之后,自动更新 `department` 表中的部门平均工资(假设 `department` 表新增一个字段 `avg_salary`)。
```sql
DELIMITER $$
DROP TRIGGER IF EXISTS after_employee_insert;
CREATE TRIGGER after_employee_insert
AFTER INSERT ON employee
FOR EACH ROW
BEGIN
UPDATE department d
SET d.avg_salary = (SELECT AVG(e.salary) FROM employee e WHERE d.dept_id = e.dept_id)
WHERE NEW.dept_id = d.dept_id;
END $$
DELIMITER ;
```
#### 练习题 18: 防止插入未来入职日期
创建一个触发器 `before_employee_insert`,在插入 `employee` 表数据时,检查 `hire_date` 是否晚于当前日期。如果是,阻止插入并抛出错误。
```sql
DELIMITER $$
DROP TRIGGER IF EXISTS before_employee_insert;
CREATE TRIGGER before_employee_insert
BEFORE INSERT ON employee
FOR EACH ROW
BEGIN
IF NEW.hire_date < CURDATE() THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '入职日期不得晚于当前日期';
END IF;
END $$
DELIMITER ;
```
#### 练习题 19: 自动生成员工编号
创建一个触发器 `before_employee_insert`,在插入 `employee` 表数据时,自动生成一个唯一的员工编号(格式为 `EMP-年份-序号`,例如 `EMP-2023-001`),并将其存储到一个新字段 `emp_code` 中。
```sql
ALTER TABLE employee ADD emp_code VARCHAR(30);
DELIMITER $$
DROP TRIGGER IF EXISTS before_employee_insert;
CREATE TRIGGER before_employee_insert
BEFORE INSERT ON employee
FOR EACH ROW
BEGIN
SET NEW.emp_code = CONCAT('EMP-',YEAR(NOW()),'-', (LAST_INSERT_ID()+1));
END $$
DELIMITER ;
INSERT INTO employee
VALUES(DEFAULT, '雷昊', 0, NOW(), 1, 1, NULL, NULL);
```
#### 练习题 20: 记录员工离职
创建一个触发器 `after_employee_delete`,在删除 `employee` 表数据之后,将被删除的员工信息插入到一个离职记录表 `employee_exit_log` 中,记录员工 ID、姓名、离职时间和原因假设原因由用户输入
```sql
CREATE TABLE employee_exit_log(
emp_id INT,
emp_name VARCHAR(20),
quit_date DATE,
quit_reason VARCHAR(50)
);
DELIMITER $$
DROP TRIGGER IF EXISTS after_employee_delete;
CREATE TRIGGER after_employee_delete
AFTER DELETE ON employee
FOR EACH ROW
BEGIN
INSERT INTO employee_exit_log()
VALUES(OLD.emp_id, OLD.emp_name, NOW(), NULL);
END $$
DELIMITER ;
```

View File

@ -1,16 +1,16 @@
/*----------------------------------------------------------------------
------------------------------------------------------------------------
C arr size 使 bool main
1 2 3 4 5 5 6 a
C arr size 使 bool main
1 2 3 4 5 5 6 a
------------------------------------------------------------------------
main
Program-End之间填入若干语句
Program-End之外的内容否则不得分
main
Program-End之间填入若干语句
Program-End之外的内容否则不得分
----------------------------------------------------------------------*/
#include <stdio.h>
#include <stdbool.h>
@ -36,12 +36,12 @@ int main() {
int *arr = (int *)malloc(capacity * sizeof(int));
if (arr == NULL) {
printf("内存分配失败!\n");
printf("内存分配失败!\n");
return 1;
}
int size = 0;
int num;
printf("【请输入多个整数(输入非数字字符结束输入):】");
printf("【请输入多个整数(输入非数字字符结束输入):】");
while (scanf("%d", &num) == 1) {
@ -50,7 +50,7 @@ int main() {
arr = (int *)realloc(arr, capacity * sizeof(int));
if (arr == NULL) {
printf("内存分配失败!\n");
printf("内存分配失败!\n");
return 1;
}
}
@ -62,9 +62,9 @@ int main() {
if (hasDuplicates(arr, size)) {
printf("数组中存在重复元素。\n");
printf("数组中存在重复元素。\n");
} else {
printf("数组中不存在重复元素。\n");
printf("数组中不存在重复元素。\n");
}

View File

@ -1,43 +1,43 @@
/*----------------------------------------------------------------------
------------------------------------------------------------------------
100 100 10
600
10% 100×10% = 10
100 100 10
600
10% 100×10% = 10
1
1
5
380 200 390 400 300
3
5
3
5
2
2
4
190 140 110 80
------------------------------------------------------------------------
main
Program-End之间填入若干语句
Program-End之外的内容否则不得分
main
Program-End之间填入若干语句
Program-End之外的内容否则不得分
----------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h> // 引入stdlib.h用于动态内存分配相关操作
#include <stdlib.h> // 引入stdlib.h用于动态内存分配相关操作
#define TANK_CAPACITY 100 // 电池总容量(单位:度)
#define LOW_FUEL_LIMIT (0.10 * TANK_CAPACITY) // 低电量阈值10%
#define AVG_CONSUMPTION_PER_100KM 10 // 平均电耗(单位:度/百公里)
#define FUEL_CONSUMPTION_PER_KM (AVG_CONSUMPTION_PER_100KM / 100.0) // 每公里电耗(单位:度/公里)
#define TANK_CAPACITY 100 // 电池总容量(单位:度)
#define LOW_FUEL_LIMIT (0.10 * TANK_CAPACITY) // 低电量阈值10%
#define AVG_CONSUMPTION_PER_100KM 10 // 平均电耗(单位:度/百公里)
#define FUEL_CONSUMPTION_PER_KM (AVG_CONSUMPTION_PER_100KM / 100.0) // 每公里电耗(单位:度/公里)
int checkRefuelStops(int trips[], int count, int results[]) {
int refuel_count = 0;
@ -56,17 +56,17 @@ int checkRefuelStops(int trips[], int count, int results[]) {
int main() {
int num_trips;
printf("【请输入赛程段数:】\n");
printf("【请输入赛程段数:】\n");
scanf("%d", &num_trips);
int *trips = (int *)malloc(num_trips * sizeof(int));
if (trips == NULL) {
printf("内存分配失败!\n");
printf("内存分配失败!\n");
return 1;
}
printf("【请输入各段赛程距离,单位公里:】\n");
printf("【请输入各段赛程距离,单位公里:】\n");
for (int i = 0; i < num_trips; ++i) {
scanf("%d", &trips[i]);
}
@ -74,7 +74,7 @@ int main() {
int *results = (int *)malloc(num_trips * sizeof(int));
if (results == NULL) {
printf("内存分配失败!\n");
printf("内存分配失败!\n");
free(trips);
return 1;
}
@ -82,12 +82,12 @@ int main() {
int refuel_count = checkRefuelStops(trips, num_trips, results);
if (refuel_count > 0) {
printf("【需要在以下几段赛程前充电:】\n");
printf("【需要在以下几段赛程前充电:】\n");
for (int i = 0; i < refuel_count; i++) {
printf("第 %d 段赛程前\n", results[i]);
printf("第 %d 段赛程前\n", results[i]);
}
} else {
printf("无需充电。\n");
printf("无需充电。\n");
}
free(trips);