视图与存储过程

最后更新: 2026-01-22 作者: MySQL Team
页面目录

第六章:视图与存储过程


6.1 视图

创建视图

-- 基本语法
CREATE VIEW view_name AS
SELECT column1, column2, ...
FROM table_name
WHERE condition;

-- 用户订单视图
CREATE VIEW user_orders_view AS
SELECT u.id, u.username, o.order_no, o.total_amount
FROM users u INNER JOIN orders o ON u.id = o.user_id
WHERE u.status = 1;

-- 复杂统计视图
CREATE VIEW monthly_sales_view AS
SELECT DATE_FORMAT(created_at, '%Y-%m') AS month,
       COUNT(*) AS order_count, SUM(total_amount) AS total_sales
FROM orders GROUP BY DATE_FORMAT(created_at, '%Y-%m');

视图操作

-- 查看视图
SHOW CREATE VIEW user_orders_view;

-- 更新视图
CREATE OR REPLACE VIEW user_orders_view AS
SELECT u.id, u.username, o.order_no FROM users u JOIN orders o ON u.id = o.user_id;

-- 删除视图
DROP VIEW IF EXISTS user_orders_view;

-- 可更新视图(简单视图可 INSERT/UPDATE/DELETE)
CREATE VIEW active_users AS
SELECT id, username, email FROM users WHERE status = 1;

INSERT INTO active_users (username, email) VALUES ('test', 'test@example.com');
UPDATE active_users SET email = 'new@example.com' WHERE username = 'test';
DELETE FROM active_users WHERE username = 'test';

6.2 存储过程

基本语法

DELIMITER //
CREATE PROCEDURE procedure_name(IN param_name param_type)
BEGIN
    -- SQL 语句
END //
DELIMITER ;

-- 调用
CALL procedure_name(value);

参数类型

DELIMITER //

-- IN 输入参数
CREATE PROCEDURE insert_user(IN p_username VARCHAR(50), IN p_email VARCHAR(100))
BEGIN
    INSERT INTO users (username, email) VALUES (p_username, p_email);
    SELECT LAST_INSERT_ID();
END //

-- OUT 输出参数
CREATE PROCEDURE get_count(OUT cnt INT)
BEGIN
    SELECT COUNT(*) INTO cnt FROM users;
END //

-- 调用 OUT 参数
CALL get_count(@cnt);
SELECT @cnt;

-- INOUT 参数
CREATE PROCEDURE increment(INOUT num INT)
BEGIN
    SET num = num + 1;
END //

SET @x = 10;
CALL increment(@x);
SELECT @x;  -- 11

DELIMITER ;

变量与条件

DELIMITER //

CREATE PROCEDURE grade_demo(IN score INT, OUT grade CHAR(1))
BEGIN
    DECLARE max_price DECIMAL(10,2) DEFAULT 0;
    
    IF score >= 90 THEN SET grade = 'A';
    ELSEIF score >= 80 THEN SET grade = 'B';
    ELSEIF score >= 70 THEN SET grade = 'C';
    ELSE SET grade = 'D';
    END IF;
END //

-- CASE 语句
CREATE PROCEDURE status_name(IN status INT, OUT name VARCHAR(20))
BEGIN
    CASE status
        WHEN 0 THEN SET name = '禁用';
        WHEN 1 THEN SET name = '启用';
        ELSE SET name = '未知';
    END CASE;
END //

DELIMITER ;

循环

DELIMITER //

-- WHILE 循环
CREATE PROCEDURE insert_n_records(IN n INT)
BEGIN
    DECLARE i INT DEFAULT 1;
    WHILE i <= n DO
        INSERT INTO test_table (name) VALUES (CONCAT('record_', i));
        SET i = i + 1;
    END WHILE;
END //

-- REPEAT 循环
CREATE PROCEDURE repeat_demo(IN n INT)
BEGIN
    DECLARE i INT DEFAULT 1;
    REPEAT
        INSERT INTO test_table (name) VALUES (CONCAT('record_', i));
        SET i = i + 1;
    UNTIL i > n END REPEAT;
END //

-- LOOP + LEAVE
CREATE PROCEDURE loop_demo(IN n INT)
BEGIN
    DECLARE i INT DEFAULT 1;
    loop_label: LOOP
        IF i > n THEN LEAVE loop_label; END IF;
        INSERT INTO test_table (name) VALUES (CONCAT('record_', i));
        SET i = i + 1;
    END LOOP loop_label;
END //

DELIMITER ;

游标

DELIMITER //

CREATE PROCEDURE process_orders()
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE v_id INT;
    DECLARE v_amount DECIMAL(10,2);
    
    DECLARE cur CURSOR FOR SELECT id, total_amount FROM orders WHERE status = 0;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    
    OPEN cur;
    read_loop: LOOP
        FETCH cur INTO v_id, v_amount;
        IF done THEN LEAVE read_loop; END IF;
        UPDATE orders SET status = 1 WHERE id = v_id;
    END LOOP;
    CLOSE cur;
END //

DELIMITER ;

管理存储过程

SHOW PROCEDURE STATUS;
SHOW CREATE PROCEDURE procedure_name;
DROP PROCEDURE IF EXISTS procedure_name;

6.3 函数

函数创建

DELIMITER //

-- 返回状态名称
CREATE FUNCTION get_status(status INT)
RETURNS VARCHAR(20) DETERMINISTIC
BEGIN
    RETURN CASE status WHEN 0 THEN '禁用' WHEN 1 THEN '启用' ELSE '未知' END;
END //

-- 计算含税总额
CREATE FUNCTION calc_total(subtotal DECIMAL(10,2))
RETURNS DECIMAL(10,2) DETERMINISTIC
BEGIN
    RETURN subtotal * 1.06;
END //

-- 统计订单数
CREATE FUNCTION order_count(user_id INT)
RETURNS INT DETERMINISTIC
BEGIN
    DECLARE cnt INT;
    SELECT COUNT(*) INTO cnt FROM orders WHERE user_id = user_id;
    RETURN cnt;
END //

DELIMITER ;

-- 调用函数
SELECT username, get_status(status) FROM users;
SELECT calc_total(100.00);  -- 106.00

管理函数

SHOW FUNCTION STATUS;
SHOW CREATE FUNCTION function_name;
DROP FUNCTION IF EXISTS function_name;

6.4 事件调度器

-- 启用事件调度器
SET GLOBAL event_scheduler = ON;

-- 每天清理过期数据
CREATE EVENT cleanup_event
ON SCHEDULE EVERY 1 DAY
DO
BEGIN
    DELETE FROM logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
END //

-- 禁用事件
ALTER EVENT cleanup_event DISABLE;

-- 查看事件
SHOW EVENTS;
DROP EVENT IF EXISTS cleanup_event;

6.5 本章小结

✅ 视图:简化查询,提供数据访问控制
✅ 存储过程:预编译SQL,支持复杂逻辑
✅ 函数:可返回值的SQL表达式
✅ 事件调度器:定时执行任务