class-notes/2208/存储过程练习题.md
2025-03-20 16:54:53 +08:00

13 KiB
Raw Permalink Blame History

语法结构

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;

表结构与数据

-- 创建数据库
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 表中。

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和新的工资作为参数更新该员工的工资。

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作为参数删除该员工的记录。

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作为参数返回该部门所有员工的详细信息。

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作为参数返回该职位所有员工的详细信息。

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作为参数返回该部门的平均工资。

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作为参数返回该职位的平均工资。

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,接受一个工资阈值作为参数,返回所有工资高于该阈值的员工。

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作为参数返回该员工的工龄以年为单位

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作为参数返回该部门的员工总数。

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作为参数返回该职位的员工总数。

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作为参数返回该员工的姓名、工资、部门名称和职位名称。

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作为参数返回该部门的最高工资。

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作为参数返回该职位的最低工资。

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作为参数返回该员工在公司中的工资排名。

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作为参数返回该部门所有员工的工资总和。

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作为参数返回该职位所有员工的工资总和。

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,接受年份作为参数,返回该年份入职的所有员工。

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作为参数返回该部门工资的分布情况如最高、最低、平均工资

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作为参数返回该职位工资的分布情况如最高、最低、平均工资

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);