【MySQL全面教学】MySQL视图与触发器Day12(2026年)


写在前面

大家好,欢迎来到MySQL全面教学系列的第12天。经过前面11天的学习,我们已经掌握了MySQL的基础知识、SQL语句、索引、事务、锁机制等核心内容。今天,我们将学习两个非常实用的数据库对象:视图(View)触发器(Trigger)

视图可以帮助我们简化复杂的查询,提供数据安全性;触发器则可以实现自动化的业务逻辑,比如审计日志、数据同步等。这两个特性在实际开发中使用频率很高,也是面试中的常考知识点。

让我们一起深入学习吧!


目录

一、什么是视图

1.1 视图的概念

**视图(View)**是一种虚拟存在的表,其内容由查询定义。视图并不在数据库中以存储的数据值集形式存在,行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。

简单来说:视图就是一条SELECT语句的执行结果集

sql 复制代码
-- 视图的本质
视图 = 存储的SQL查询语句

1.2 为什么需要视图

场景 说明
简化复杂查询 将多表JOIN、子查询等复杂SQL封装成视图
数据安全性 限制用户只能访问视图中的特定列或行
逻辑独立性 底层表结构变化时,只需修改视图定义
数据抽象 为不同用户呈现不同的数据视角

1.3 视图 vs 表

对比项 视图(View) 表(Table)
数据存储 不存储实际数据,只存储定义 存储实际数据
占用空间 几乎不占用 占用磁盘空间
数据更新 不一定能更新 可以更新
创建语法 CREATE VIEW CREATE TABLE
查询性能 可能有性能开销 直接查询
数据安全 可以限制访问范围 需要额外权限控制

二、创建和管理视图

2.1 创建视图

基本语法:

sql 复制代码
CREATE [OR REPLACE] VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION];
示例1:简单视图
sql 复制代码
-- 创建一个只包含在职员工信息的视图
CREATE VIEW v_active_employees AS
SELECT 
    employee_id,
    first_name,
    last_name,
    department_id,
    salary
FROM employees
WHERE status = 'ACTIVE';

-- 使用视图
SELECT * FROM v_active_employees WHERE department_id = 10;
示例2:复杂视图(多表JOIN)
sql 复制代码
-- 创建员工部门信息视图
CREATE VIEW v_employee_details AS
SELECT 
    e.employee_id,
    CONCAT(e.first_name, ' ', e.last_name) AS full_name,
    e.email,
    e.phone_number,
    d.department_name,
    l.city,
    e.salary
FROM employees e
INNER JOIN departments d ON e.department_id = d.department_id
INNER JOIN locations l ON d.location_id = l.location_id;

-- 查询视图
SELECT * FROM v_employee_details WHERE department_name = 'Sales';
示例3:带聚合函数的视图
sql 复制代码
-- 创建部门薪资统计视图
CREATE VIEW v_department_salary_stats AS
SELECT 
    d.department_name,
    COUNT(e.employee_id) AS employee_count,
    AVG(e.salary) AS avg_salary,
    MIN(e.salary) AS min_salary,
    MAX(e.salary) AS max_salary,
    SUM(e.salary) AS total_salary
FROM departments d
LEFT JOIN employees e ON d.department_id = e.department_id
GROUP BY d.department_id, d.department_name;

2.2 修改视图

sql 复制代码
-- 方式1:使用ALTER VIEW
ALTER VIEW v_active_employees AS
SELECT 
    employee_id,
    first_name,
    last_name,
    department_id,
    salary,
    hire_date  -- 新增字段
FROM employees
WHERE status = 'ACTIVE';

-- 方式2:使用CREATE OR REPLACE VIEW
CREATE OR REPLACE VIEW v_active_employees AS
SELECT 
    employee_id,
    first_name,
    last_name,
    department_id,
    salary,
    hire_date
FROM employees
WHERE status = 'ACTIVE';

2.3 删除视图

sql 复制代码
-- 删除单个视图
DROP VIEW IF EXISTS v_active_employees;

-- 删除多个视图
DROP VIEW IF EXISTS v_employee_details, v_department_salary_stats;

2.4 查看视图定义

sql 复制代码
-- 查看视图创建语句
SHOW CREATE VIEW v_employee_details;

-- 查看视图结构
DESCRIBE v_employee_details;

-- 查看所有视图
SHOW FULL TABLES WHERE Table_type = 'VIEW';

-- 从information_schema查询
SELECT * FROM information_schema.views 
WHERE table_schema = 'your_database_name';

三、可更新视图

3.1 什么是可更新视图

可更新视图是指可以通过视图对底层基表进行INSERT、UPDATE、DELETE操作的视图。

但不是所有视图都可以更新,需要满足以下条件:

  1. 视图定义中不包含以下元素:

    • 聚合函数(SUM、COUNT、AVG等)
    • DISTINCT关键字
    • GROUP BY / HAVING
    • UNION / UNION ALL
    • 子查询
    • JOIN(MySQL中部分情况支持)
    • 某些系统函数
  2. 视图必须包含基表中所有NOT NULL且没有默认值的列

3.2 可更新视图示例

sql 复制代码
-- 创建可更新视图
CREATE VIEW v_employees_it AS
SELECT 
    employee_id,
    first_name,
    last_name,
    email,
    salary
FROM employees
WHERE department_id = 60;  -- IT部门

-- 通过视图插入数据
INSERT INTO v_employees_it (first_name, last_name, email, salary)
VALUES ('John', 'Doe', 'john.doe@example.com', 8000);

-- 通过视图更新数据
UPDATE v_employees_it 
SET salary = 9000 
WHERE employee_id = 101;

-- 通过视图删除数据
DELETE FROM v_employees_it WHERE employee_id = 102;

3.3 WITH CHECK OPTION

WITH CHECK OPTION用于确保通过视图进行的INSERT和UPDATE操作,结果仍然满足视图的WHERE条件。

sql 复制代码
-- 创建带CHECK OPTION的视图
CREATE VIEW v_employees_high_salary AS
SELECT 
    employee_id,
    first_name,
    last_name,
    salary
FROM employees
WHERE salary >= 10000
WITH CHECK OPTION;  -- 关键:确保数据符合视图条件

-- 以下操作会成功(salary >= 10000)
UPDATE v_employees_high_salary 
SET salary = 12000 
WHERE employee_id = 101;

-- 以下操作会失败(违反CHECK OPTION)
UPDATE v_employees_high_salary 
SET salary = 5000   -- 小于10000,违反视图条件
WHERE employee_id = 101;
-- ERROR 1369 (HY000): CHECK OPTION failed 'db.v_employees_high_salary'
LOCAL vs CASCADED
sql 复制代码
-- CASCADED(默认):检查当前视图及底层所有视图的条件
CREATE VIEW v_view1 AS
SELECT * FROM employees WHERE salary > 5000
WITH CASCADED CHECK OPTION;

-- LOCAL:只检查当前视图的条件
CREATE VIEW v_view2 AS
SELECT * FROM employees WHERE salary > 5000
WITH LOCAL CHECK OPTION;

四、视图的优缺点

4.1 优点

优点 详细说明
简化复杂查询 将复杂的JOIN、子查询封装成简单的视图查询
数据安全性 可以限制用户只能访问特定的行和列
逻辑独立性 应用程序使用视图,底层表结构变化时只需修改视图
数据抽象 为不同角色提供不同的数据视图

4.2 缺点

缺点 详细说明
性能开销 每次查询视图都需要执行定义视图的SQL
更新限制 复杂视图无法更新
调试困难 视图嵌套时,问题定位较复杂

4.3 使用建议

sql 复制代码
-- 经验之谈:视图的最佳实践

-- 1. 视图命名规范:以v_或view_开头
CREATE VIEW v_user_order_summary AS ...

-- 2. 避免视图嵌套过深(建议不超过3层)
-- 不推荐:view_a -> view_b -> view_c -> view_d

-- 3. 对于频繁查询的复杂视图,考虑使用物化视图(MySQL 8.0.13+)
-- 或使用汇总表代替

-- 4. 为视图添加注释
CREATE VIEW v_employee_stats AS
SELECT ...
COMMENT '员工统计信息视图,每日凌晨更新';

五、触发器详解

5.1 什么是触发器

**触发器(Trigger)**是一种特殊的存储过程,它在特定的表上执行特定的操作时自动触发执行。触发器可以在INSERT、UPDATE、DELETE操作之前(BEFORE)或之后(AFTER)执行。

5.2 触发器的应用场景

  • 审计日志:记录数据变更历史
  • 数据同步:一个表变更时同步更新其他表
  • 数据校验:在数据写入前进行复杂校验
  • 自动计算:自动更新统计字段
  • 级联操作:实现外键约束无法完成的级联逻辑

5.3 创建触发器

基本语法:

sql 复制代码
CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON table_name
FOR EACH ROW
[trigger_body];

5.4 NEW和OLD关键字

操作类型 NEW OLD
INSERT 新插入的行数据 NULL(不存在)
UPDATE 更新后的新值 更新前的旧值
DELETE NULL(不存在) 被删除的行数据

5.5 触发器示例

示例1:BEFORE INSERT触发器(数据校验)
sql 复制代码
-- 创建员工表
CREATE TABLE employees (
    employee_id INT PRIMARY KEY AUTO_INCREMENT,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    salary DECIMAL(10, 2),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 创建触发器:确保薪资不为负数
DELIMITER //

CREATE TRIGGER trg_before_employee_insert
BEFORE INSERT ON employees
FOR EACH ROW
BEGIN
    IF NEW.salary < 0 THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Error: Salary cannot be negative';
    END IF;
    
    -- 自动转换邮箱为小写
    SET NEW.email = LOWER(NEW.email);
END //

DELIMITER ;

-- 测试触发器
INSERT INTO employees (first_name, last_name, email, salary)
VALUES ('John', 'Doe', 'JOHN.DOE@EXAMPLE.COM', 5000);
-- 成功:email自动转为小写

INSERT INTO employees (first_name, last_name, email, salary)
VALUES ('Jane', 'Doe', 'jane.doe@example.com', -1000);
-- 失败:触发器抛出错误
示例2:AFTER UPDATE触发器(记录变更)
sql 复制代码
-- 创建薪资变更历史表
CREATE TABLE salary_history (
    history_id INT PRIMARY KEY AUTO_INCREMENT,
    employee_id INT NOT NULL,
    old_salary DECIMAL(10, 2),
    new_salary DECIMAL(10, 2),
    changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    changed_by VARCHAR(100)
);

-- 创建触发器:记录薪资变更
DELIMITER //

CREATE TRIGGER trg_after_salary_update
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
    -- 只在薪资变化时记录
    IF OLD.salary <> NEW.salary THEN
        INSERT INTO salary_history (employee_id, old_salary, new_salary, changed_by)
        VALUES (NEW.employee_id, OLD.salary, NEW.salary, CURRENT_USER());
    END IF;
END //

DELIMITER ;

-- 测试触发器
UPDATE employees SET salary = 8000 WHERE employee_id = 1;
-- 自动在salary_history表中插入记录
示例3:BEFORE DELETE触发器(防止误删)
sql 复制代码
-- 创建触发器:防止删除重要员工
DELIMITER //

CREATE TRIGGER trg_before_employee_delete
BEFORE DELETE ON employees
FOR EACH ROW
BEGIN
    IF OLD.employee_id = 1 THEN  -- 假设ID=1是CEO
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Error: Cannot delete the CEO record';
    END IF;
END //

DELIMITER ;
示例4:多个触发器(MySQL 5.7.2+)
sql 复制代码
-- MySQL 5.7.2+ 支持同一事件多个触发器,使用FOLLOWS/PRECEDES控制顺序

DELIMITER //

CREATE TRIGGER trg_after_insert_audit
AFTER INSERT ON employees
FOR EACH ROW
BEGIN
    INSERT INTO audit_log (action, table_name, record_id, action_time)
    VALUES ('INSERT', 'employees', NEW.employee_id, NOW());
END //

CREATE TRIGGER trg_after_insert_notify
AFTER INSERT ON employees
FOR EACH ROW
FOLLOWS trg_after_insert_audit  -- 在audit触发器之后执行
BEGIN
    INSERT INTO notifications (message, created_at)
    VALUES (CONCAT('New employee added: ', NEW.first_name, ' ', NEW.last_name), NOW());
END //

DELIMITER ;

5.6 管理触发器

sql 复制代码
-- 查看所有触发器
SHOW TRIGGERS;

-- 查看指定表的触发器
SHOW TRIGGERS FROM your_database WHERE `Table` = 'employees';

-- 从information_schema查询
SELECT * FROM information_schema.triggers 
WHERE trigger_schema = 'your_database';

-- 查看触发器创建语句
SHOW CREATE TRIGGER trg_before_employee_insert;

-- 删除触发器
DROP TRIGGER IF EXISTS trg_before_employee_insert;

-- 禁用/启用触发器(MySQL 8.0)
-- 注意:MySQL不支持直接禁用触发器,需要删除重建或使用变量控制

六、实战:用触发器实现审计日志

6.1 需求分析

我们需要实现一个完整的审计日志系统,记录所有对employees表的变更操作。

6.2 表结构设计

sql 复制代码
-- 审计日志表
CREATE TABLE audit_log (
    log_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    table_name VARCHAR(64) NOT NULL,
    operation VARCHAR(10) NOT NULL COMMENT 'INSERT/UPDATE/DELETE',
    record_id VARCHAR(50) NOT NULL,
    old_values JSON,
    new_values JSON,
    executed_by VARCHAR(100) DEFAULT CURRENT_USER(),
    executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    client_host VARCHAR(100),
    INDEX idx_table_time (table_name, executed_at),
    INDEX idx_record (table_name, record_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

6.3 创建审计触发器

sql 复制代码
DELIMITER //

-- INSERT审计触发器
CREATE TRIGGER trg_audit_employees_insert
AFTER INSERT ON employees
FOR EACH ROW
BEGIN
    INSERT INTO audit_log (table_name, operation, record_id, new_values, client_host)
    VALUES (
        'employees',
        'INSERT',
        NEW.employee_id,
        JSON_OBJECT(
            'employee_id', NEW.employee_id,
            'first_name', NEW.first_name,
            'last_name', NEW.last_name,
            'email', NEW.email,
            'salary', NEW.salary
        ),
        CONNECTION_ID()
    );
END //

-- UPDATE审计触发器
CREATE TRIGGER trg_audit_employees_update
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
    INSERT INTO audit_log (table_name, operation, record_id, old_values, new_values, client_host)
    VALUES (
        'employees',
        'UPDATE',
        NEW.employee_id,
        JSON_OBJECT(
            'first_name', OLD.first_name,
            'last_name', OLD.last_name,
            'email', OLD.email,
            'salary', OLD.salary
        ),
        JSON_OBJECT(
            'first_name', NEW.first_name,
            'last_name', NEW.last_name,
            'email', NEW.email,
            'salary', NEW.salary
        ),
        CONNECTION_ID()
    );
END //

-- DELETE审计触发器
CREATE TRIGGER trg_audit_employees_delete
AFTER DELETE ON employees
FOR EACH ROW
BEGIN
    INSERT INTO audit_log (table_name, operation, record_id, old_values, client_host)
    VALUES (
        'employees',
        'DELETE',
        OLD.employee_id,
        JSON_OBJECT(
            'employee_id', OLD.employee_id,
            'first_name', OLD.first_name,
            'last_name', OLD.last_name,
            'email', OLD.email,
            'salary', OLD.salary
        ),
        CONNECTION_ID()
    );
END //

DELIMITER ;

6.4 查询审计日志

sql 复制代码
-- 查看最近的操作记录
SELECT 
    log_id,
    operation,
    record_id,
    old_values,
    new_values,
    executed_by,
    executed_at
FROM audit_log
WHERE table_name = 'employees'
ORDER BY executed_at DESC
LIMIT 10;

-- 查看特定员工的变更历史
SELECT * FROM audit_log
WHERE table_name = 'employees' AND record_id = '101'
ORDER BY executed_at;

-- 统计每日操作次数
SELECT 
    DATE(executed_at) as operation_date,
    operation,
    COUNT(*) as count
FROM audit_log
GROUP BY DATE(executed_at), operation
ORDER BY operation_date DESC;

七、踩坑提醒

7.1 视图相关坑

坑1:视图性能问题
sql 复制代码
-- 问题:视图嵌套导致性能急剧下降
-- 不推荐:
CREATE VIEW v_level1 AS SELECT * FROM huge_table WHERE ...;
CREATE VIEW v_level2 AS SELECT * FROM v_level1 WHERE ...;
CREATE VIEW v_level3 AS SELECT * FROM v_level2 WHERE ...;
-- 查询v_level3时,会逐层展开,性能极差

-- 解决:尽量扁平化,或直接使用原始表
坑2:视图与索引
sql 复制代码
-- 视图本身不能创建索引
-- 但可以在基表上创建索引来优化视图查询

-- 推荐:为视图中常用的WHERE条件列创建索引
CREATE INDEX idx_employees_dept ON employees(department_id);
CREATE INDEX idx_employees_status ON employees(status);

7.2 触发器相关坑

坑1:触发器隐藏逻辑
sql 复制代码
-- 问题:触发器中的逻辑是"隐藏"的,容易导致意外行为
-- 比如:开发人员不知道有触发器,对表进行批量更新

-- 解决:
-- 1. 良好的文档和命名规范
-- 2. 在触发器中添加注释说明
-- 3. 批量操作前考虑临时禁用触发器(MySQL需删除重建)
坑2:递归触发器
sql 复制代码
-- 问题:触发器A修改表B,表B的触发器又修改表A,导致死循环

-- 示例:危险代码
DELIMITER //
CREATE TRIGGER trg_a AFTER UPDATE ON table_a
FOR EACH ROW
BEGIN
    UPDATE table_b SET ...;  -- 触发table_b的触发器
END //

CREATE TRIGGER trg_b AFTER UPDATE ON table_b
FOR EACH ROW
BEGIN
    UPDATE table_a SET ...;  -- 又触发table_a的触发器,死循环!
END //
DELIMITER ;

-- 解决:
-- 1. 仔细设计触发器逻辑,避免循环依赖
-- 2. 使用变量控制,防止递归
坑3:触发器中的错误处理
sql 复制代码
-- 问题:触发器中的错误会导致整个操作失败

-- 推荐:使用条件判断和错误处理
DELIMITER //
CREATE TRIGGER trg_safe_example
BEFORE INSERT ON employees
FOR EACH ROW
BEGIN
    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
    BEGIN
        -- 记录错误日志,但不阻止主操作
        INSERT INTO error_log (error_message, created_at)
        VALUES ('Trigger error occurred', NOW());
    END;
    
    -- 主逻辑
    SET NEW.email = LOWER(NEW.email);
END //
DELIMITER ;
坑4:大数据量下的触发器性能
sql 复制代码
-- 问题:对千万级表进行批量更新时,触发器会逐行执行,极慢

-- 解决:
-- 1. 大批量操作时,考虑先删除触发器,操作完成后再重建
-- 2. 或者使用存储过程批量处理,绕过触发器
-- 3. 考虑使用binlog解析代替触发器做审计

八、面试高频考点

8.1 视图和表的区别是什么?

答案要点:

区别点 视图
本质 虚拟表,存储的是SQL定义 实际存储数据的结构
数据存储 不存储数据,查询时动态生成 物理存储数据
占用空间 极小(仅存储定义) 较大
更新 受限制,复杂视图不可更新 可以自由增删改
性能 可能有性能开销 直接访问
用途 简化查询、安全控制 数据存储

8.2 什么情况下视图不能更新?

答案:

  1. 包含聚合函数(SUM、COUNT、AVG等)
  2. 包含DISTINCT关键字
  3. 包含GROUP BY或HAVING
  4. 包含UNION或UNION ALL
  5. 包含子查询
  6. 包含JOIN(部分情况)
  7. 包含计算列且该列未在基表中定义

8.3 触发器有哪些类型?

答案:

  • 按时机分:BEFORE(操作前)、AFTER(操作后)
  • 按事件分:INSERT、UPDATE、DELETE
  • 按粒度分:FOR EACH ROW(行级)、FOR EACH STATEMENT(语句级,MySQL不支持)

组合起来有6种:BEFORE INSERT、AFTER INSERT、BEFORE UPDATE、AFTER UPDATE、BEFORE DELETE、AFTER DELETE

8.4 NEW和OLD在触发器中有什么区别?

答案:

  • INSERT操作:NEW表示新插入的行数据,OLD为NULL
  • UPDATE操作:NEW表示更新后的新值,OLD表示更新前的旧值
  • DELETE操作:OLD表示被删除的行数据,NEW为NULL

8.5 触发器有什么性能影响?

答案:

  1. 增加写操作开销:每次DML操作都要执行触发器逻辑
  2. 事务影响:触发器失败会导致整个事务回滚
  3. 递归风险:不当设计可能导致死循环
  4. 调试困难:触发器中的错误难以定位
  5. 批量操作性能下降:逐行触发在大数据量时性能极差

优化建议:

  • 触发器逻辑尽量简单
  • 避免在触发器中进行复杂计算
  • 大数据量操作考虑临时禁用触发器
  • 考虑使用应用层逻辑代替触发器

8.6 WITH CHECK OPTION的作用是什么?

答案:

WITH CHECK OPTION用于确保通过视图进行的INSERT和UPDATE操作,其结果仍然满足视图的WHERE条件。

  • CASCADED(默认):检查当前视图及所有底层视图的条件
  • LOCAL:只检查当前视图的条件

九、总结

今天我们学习了MySQL中的两个重要特性:视图触发器

核心知识点回顾

  1. 视图:虚拟表,简化复杂查询,提供数据安全性

    • 创建:CREATE VIEW
    • 可更新视图需要满足特定条件
    • WITH CHECK OPTION保证数据一致性
  2. 触发器:自动执行的存储过程,实现业务自动化

    • BEFORE/AFTER + INSERT/UPDATE/DELETE
    • NEW和OLD关键字访问数据
    • 适合审计日志、数据校验等场景

使用建议

场景 推荐方案
简化复杂查询 视图
数据安全控制 视图 + 权限管理
审计日志 触发器 或 binlog解析
数据校验 触发器 或 CHECK约束
级联更新 外键约束 或 应用层处理

十、下一步预告

Day13 - MySQL性能优化实战

在下一篇文章中,我们将学习:

  • 性能优化的完整方法论
  • 慢查询日志分析
  • SQL优化技巧
  • 索引优化策略
  • 实战:从10秒到10毫秒的优化过程

性能优化是MySQL面试的重中之重,也是实际工作中最常遇到的问题,敬请期待!


参考资料

  1. MySQL 8.0 Reference Manual - Views
  2. MySQL 8.0 Reference Manual - Triggers

互动话题

  1. 你在实际项目中使用过视图和触发器吗?遇到了哪些问题?
  2. 对于审计日志,你更倾向于使用触发器还是binlog解析?为什么?
  3. 分享一个你使用视图或触发器解决实际问题的案例吧!

欢迎在评论区留言讨论,如果觉得文章有帮助,别忘了点赞收藏哦!我们下节课见!


本文是MySQL全面教学系列第12篇,系列文章持续更新中...

相关推荐
沙湖遇雨7 小时前
8.ByteBuf 的数据模型、生命周期和内存分配
后端
by组态7 小时前
Ricon组态系统API参考手册
前端·后端·物联网
oradh8 小时前
Oracle Undo问题总结(两类Undo表空间不足和单个会话占用大量Undo的性能问题)
数据库·oracle
企业数字化笔记8 小时前
固定资产财务账与实物账怎么对账?折旧快照、差异检测与SQL核对
android·数据库·sql
再吃一根胡萝卜8 小时前
Agent 如何选择与生成 SQL —— Text2SQL 全链路详解
后端
苍何8 小时前
把操作流程直接录成 Skill,豆包太夯了!
后端
DBA_G8 小时前
GBase 8a表空间多路径存储数据迁移链路适配解析
数据库·oracle
java1234_小锋8 小时前
Tornado 6.5,全面支持 Python 3.14
数据库·python·tornado