SQL Server 2019入门学习教程,从入门到精通,SQL Server 2019 游标 — 语法知识点及使用方法详解(14)

SQL Server 2019 游标 --- 语法知识点及使用方法详解


一、认识游标

1. 游标的概念

游标(Cursor) 是数据库中用于逐行处理结果集的一种机制。它允许应用程序对查询返回的多行数据进行逐行遍历、定位、修改或删除,弥补了标准SQL语句一次操作整个结果集的局限性。

⚠️ 注意:游标是逐行处理,性能通常低于基于集合的操作,应谨慎使用。


2. 游标的优点

  • 逐行控制:可对结果集中每一行执行不同逻辑。
  • 灵活定位:支持向前、向后、跳转到指定行(取决于游标类型)。
  • 支持修改 :可结合 WHERE CURRENT OF 子句更新或删除当前行。
  • 兼容性好:适用于需要逐行处理的复杂业务逻辑(如报表、审计、数据迁移)。

3. 游标的分类

分类维度 类型 说明
作用域 LOCAL(局部) 仅在声明它的批处理、存储过程或触发器中有效
GLOBAL(全局) 在连接级别有效,多个批处理可共享(不推荐)
滚动方向 FORWARD_ONLY(默认) 只能从第一行滚动到最后一行(FETCH NEXT
SCROLL 支持任意方向滚动(NEXT, PRIOR, FIRST, LAST, ABSOLUTE n, RELATIVE n
数据敏感性 STATIC 静态快照,不反映后续修改
KEYSET 键集驱动,键值固定,非键列值可变
DYNAMIC 动态反映所有修改(性能开销大)
FAST_FORWARD FORWARD_ONLY + READ_ONLY 的优化组合,性能最佳
修改能力 READ_ONLY 不允许修改
SCROLL_LOCKS 保证可更新(通过锁)
OPTIMISTIC 乐观并发控制(通过时间戳或比较值)

二、游标的基本操作

游标操作五步曲:

  1. 声明游标DECLARE CURSOR
  2. 打开游标OPEN
  3. 读取数据FETCH
  4. 关闭游标CLOSE
  5. 释放游标DEALLOCATE

案例1:基本游标操作 --- 遍历员工表并打印信息

sql 复制代码
-- 创建测试表
CREATE TABLE dbo.Employees (
    EmployeeID INT PRIMARY KEY,
    FirstName NVARCHAR(50),
    LastName NVARCHAR(50),
    Salary DECIMAL(10,2)
);
GO

INSERT INTO dbo.Employees VALUES
(1, '张', '三', 8000.00),
(2, '李', '四', 9500.00),
(3, '王', '五', 7200.00);
GO

-- 声明变量用于接收游标数据
DECLARE @EmpID INT, @FirstName NVARCHAR(50), @LastName NVARCHAR(50), @Salary DECIMAL(10,2);

-- 1. 声明游标
-- 使用 FAST_FORWARD(只读、只向前)提高性能
DECLARE emp_cursor CURSOR FAST_FORWARD FOR
SELECT EmployeeID, FirstName, LastName, Salary
FROM dbo.Employees
ORDER BY Salary DESC; -- 按薪资降序排列

-- 2. 打开游标
OPEN emp_cursor;

-- 3. 读取第一行数据
FETCH NEXT FROM emp_cursor INTO @EmpID, @FirstName, @LastName, @Salary;

-- 循环读取所有行
WHILE @@FETCH_STATUS = 0 -- 0=成功, -1=失败或行不存在, -2=行已删除
BEGIN
    -- 打印员工信息
    PRINT '员工ID: ' + CAST(@EmpID AS NVARCHAR) + 
          ', 姓名: ' + @FirstName + @LastName + 
          ', 薪资: ' + CAST(@Salary AS NVARCHAR);

    -- 读取下一行
    FETCH NEXT FROM emp_cursor INTO @EmpID, @FirstName, @LastName, @Salary;
END

-- 4. 关闭游标
CLOSE emp_cursor;

-- 5. 释放游标资源
DEALLOCATE emp_cursor;
GO

注释

  • FAST_FORWARD 是性能最优的只读、只向前游标。
  • @@FETCH_STATUS 是全局变量,指示上一次 FETCH 操作状态。
  • FETCH NEXT 读取下一行(对于 FORWARD_ONLY 是唯一选项)。
  • 必须显式 CLOSEDEALLOCATE,否则会占用资源。

三、游标的运用

1. 使用游标变量

游标可以声明为变量类型 CURSOR,用于动态传递或作为存储过程参数。

sql 复制代码
-- 声明游标变量
DECLARE @MyCursor CURSOR;

-- 将游标赋值给变量
SET @MyCursor = CURSOR FAST_FORWARD FOR
SELECT EmployeeID, FirstName, LastName
FROM dbo.Employees
WHERE Salary > 8000;

-- 打开游标变量
OPEN @MyCursor;

DECLARE @ID INT, @FN NVARCHAR(50), @LN NVARCHAR(50);
FETCH NEXT FROM @MyCursor INTO @ID, @FN, @LN;

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT '高薪员工: ' + @FN + @LN + ' (ID: ' + CAST(@ID AS NVARCHAR) + ')';
    FETCH NEXT FROM @MyCursor INTO @ID, @FN, @LN;
END

CLOSE @MyCursor;
DEALLOCATE @MyCursor; -- 释放变量游标
GO

注释

  • 游标变量需用 SETSELECT 赋值。
  • 使用方式与普通游标相同。
  • 适用于模块化编程或动态SQL场景。

2. 使用游标为变量赋值(多行转单值处理)

sql 复制代码
-- 场景:获取薪资最高的3名员工姓名拼接成字符串
DECLARE @TopEmployees NVARCHAR(MAX) = '';
DECLARE @Name NVARCHAR(100);

DECLARE top_emp_cursor CURSOR FAST_FORWARD FOR
SELECT TOP 3 FirstName + ' ' + LastName AS FullName
FROM dbo.Employees
ORDER BY Salary DESC;

OPEN top_emp_cursor;
FETCH NEXT FROM top_emp_cursor INTO @Name;

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @TopEmployees = @TopEmployees + @Name + '; ';
    FETCH NEXT FROM top_emp_cursor INTO @Name;
END

CLOSE top_emp_cursor;
DEALLOCATE top_emp_cursor;

-- 输出结果
PRINT '薪资最高的员工: ' + LEFT(@TopEmployees, LEN(@TopEmployees) - 2); -- 去掉末尾分号
GO

注释

  • 游标常用于聚合字符串等集合函数无法直接实现的操作。
  • 替代方案:SQL Server 2017+ 可用 STRING_AGG() 函数。

3. 使用 ORDER BY 子句改变游标中行的顺序

sql 复制代码
-- 声明游标时使用 ORDER BY 控制遍历顺序
DECLARE emp_by_name_cursor CURSOR SCROLL FOR -- SCROLL允许任意滚动
SELECT EmployeeID, FirstName, LastName, Salary
FROM dbo.Employees
ORDER BY LastName ASC, FirstName ASC; -- 按姓氏、名字升序

OPEN emp_by_name_cursor;

-- 读取第一行
FETCH FIRST FROM emp_by_name_cursor INTO @EmpID, @FirstName, @LastName, @Salary;
PRINT '第一行: ' + @LastName + @FirstName;

-- 读取最后一行
FETCH LAST FROM emp_by_name_cursor INTO @EmpID, @FirstName, @LastName, @Salary;
PRINT '最后一行: ' + @LastName + @FirstName;

-- 读取前一行(从最后一行往前)
FETCH PRIOR FROM emp_by_name_cursor INTO @EmpID, @FirstName, @LastName, @Salary;
PRINT '倒数第二行: ' + @LastName + @FirstName;

-- 跳转到绝对位置(第2行)
FETCH ABSOLUTE 2 FROM emp_by_name_cursor INTO @EmpID, @FirstName, @LastName, @Salary;
PRINT '第2行: ' + @LastName + @FirstName;

-- 相对当前位置移动(+1 下一行)
FETCH RELATIVE 1 FROM emp_by_name_cursor INTO @EmpID, @FirstName, @LastName, @Salary;
PRINT '第3行: ' + @LastName + @FirstName;

CLOSE emp_by_name_cursor;
DEALLOCATE emp_by_name_cursor;
GO

注释

  • SCROLL 游标支持 FIRST, LAST, PRIOR, ABSOLUTE n, RELATIVE n
  • ABSOLUTE n:n>0 从第一行开始,n<0 从最后一行开始。
  • RELATIVE n:n>0 向后,n<0 向前。
  • 性能低于 FAST_FORWARD,仅在需要时使用。

4. 使用游标修改数据(UPDATE ... WHERE CURRENT OF)

sql 复制代码
-- 为薪资低于8000的员工加薪10%
DECLARE @CurrentSalary DECIMAL(10,2);

-- 声明可更新游标(必须包含主键或唯一索引列)
DECLARE update_cursor CURSOR FOR
SELECT EmployeeID, Salary -- 包含主键EmployeeID用于定位
FROM dbo.Employees
WHERE Salary < 8000
FOR UPDATE OF Salary; -- 指定可更新的列

OPEN update_cursor;
FETCH NEXT FROM update_cursor INTO @EmpID, @CurrentSalary;

WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE @NewSalary DECIMAL(10,2) = @CurrentSalary * 1.10;
    
    -- 更新当前行
    UPDATE dbo.Employees 
    SET Salary = @NewSalary
    WHERE CURRENT OF update_cursor; -- 关键:WHERE CURRENT OF

    PRINT '员工ID ' + CAST(@EmpID AS NVARCHAR) + 
          ' 薪资从 ' + CAST(@CurrentSalary AS NVARCHAR) + 
          ' 更新为 ' + CAST(@NewSalary AS NVARCHAR);

    FETCH NEXT FROM update_cursor INTO @EmpID, @CurrentSalary;
END

CLOSE update_cursor;
DEALLOCATE update_cursor;

-- 查看更新结果
SELECT * FROM dbo.Employees;
GO

注释

  • FOR UPDATE [OF column_list] 声明游标可更新。
  • WHERE CURRENT OF cursor_name 定位到当前游标行进行更新。
  • 游标查询必须包含足够信息定位行(如主键)。

5. 使用游标删除数据(DELETE ... WHERE CURRENT OF)

sql 复制代码
-- 删除薪资低于7500的员工(谨慎操作!)
DECLARE delete_cursor CURSOR FOR
SELECT EmployeeID, FirstName, LastName, Salary
FROM dbo.Employees
WHERE Salary < 7500
FOR UPDATE; -- 可省略列,表示所有列可更新(含删除)

OPEN delete_cursor;
FETCH NEXT FROM delete_cursor INTO @EmpID, @FirstName, @LastName, @Salary;

WHILE @@FETCH_STATUS = 0
BEGIN
    -- 删除当前行
    DELETE FROM dbo.Employees 
    WHERE CURRENT OF delete_cursor;

    PRINT '已删除员工: ' + @FirstName + @LastName + ' (原薪资: ' + CAST(@Salary AS NVARCHAR) + ')';

    -- 注意:删除后@@FETCH_STATUS可能为-2,需重新FETCH
    FETCH NEXT FROM delete_cursor INTO @EmpID, @FirstName, @LastName, @Salary;
END

CLOSE delete_cursor;
DEALLOCATE delete_cursor;

-- 查看剩余员工
SELECT * FROM dbo.Employees;
GO

注释

  • DELETE ... WHERE CURRENT OF 删除当前游标行。
  • 删除后当前行消失,下次 FETCH 可能失败(@@FETCH_STATUS = -2)。
  • 生产环境慎用,建议先备份或使用逻辑删除。

四、使用系统存储过程管理游标

SQL Server 提供系统存储过程用于查看游标元数据:

1. sp_cursor_list --- 列出当前连接的游标

sql 复制代码
-- 声明一个游标(不打开)
DECLARE test_cursor CURSOR FOR SELECT * FROM dbo.Employees;

-- 列出当前连接的所有游标
-- @cursor_scope: 1=本地游标, 2=全局游标, 3=全部
EXEC sp_cursor_list @cursor_return = 0 OUTPUT, @cursor_scope = 3;
GO

输出列cursor_handle, cursor_name, cursor_scope, status, model, concurrency, scrollable, open_status 等。


2. sp_describe_cursor --- 描述游标属性

sql 复制代码
-- 声明并打开游标
DECLARE emp_desc_cursor CURSOR SCROLL FOR 
SELECT EmployeeID, FirstName, LastName FROM dbo.Employees;
OPEN emp_desc_cursor;

-- 描述游标属性
EXEC sp_describe_cursor 
    @cursor_return = 0 OUTPUT, 
    @cursor_source = N'local',  -- 'local', 'global', 'variable'
    @cursor_identity = N'emp_desc_cursor';

-- 关闭释放
CLOSE emp_desc_cursor;
DEALLOCATE emp_desc_cursor;
GO

输出:游标的声明方式、滚动性、可更新性、状态等详细信息。


3. sp_describe_cursor_columns --- 描述游标结果集列

sql 复制代码
DECLARE col_cursor CURSOR FOR 
SELECT EmployeeID, FirstName + ' ' + LastName AS FullName, Salary 
FROM dbo.Employees;

OPEN col_cursor;

-- 描述游标结果集的列信息
EXEC sp_describe_cursor_columns 
    @cursor_return = 0 OUTPUT, 
    @cursor_source = N'local', 
    @cursor_identity = N'col_cursor';

CLOSE col_cursor;
DEALLOCATE col_cursor;
GO

输出列column_name, ordinal_position, data_type, max_length, precision, scale 等。


4. sp_describe_cursor_tables --- 描述游标引用的表

sql 复制代码
DECLARE table_cursor CURSOR FOR 
SELECT e.EmployeeID, e.FirstName, d.DepartmentName
FROM dbo.Employees e
JOIN dbo.Departments d ON e.DeptID = d.DeptID; -- 假设有部门表

-- 创建部门表(如果不存在)
IF OBJECT_ID('dbo.Departments') IS NULL
BEGIN
    CREATE TABLE dbo.Departments (
        DeptID INT PRIMARY KEY,
        DepartmentName NVARCHAR(50)
    );
    INSERT INTO dbo.Departments VALUES (1, 'IT'), (2, 'HR');
    ALTER TABLE dbo.Employees ADD DeptID INT DEFAULT 1;
    UPDATE dbo.Employees SET DeptID = 1;
END
GO

OPEN table_cursor;

-- 描述游标引用的基表
EXEC sp_describe_cursor_tables 
    @cursor_return = 0 OUTPUT, 
    @cursor_source = N'local', 
    @cursor_identity = N'table_cursor';

CLOSE table_cursor;
DEALLOCATE table_cursor;
GO

输出:游标查询涉及的基表名称、所有者、更新能力等。


五、综合性案例

综合案例1:使用游标生成员工薪资调整报告(含历史记录)

sql 复制代码
-- 创建薪资历史表
CREATE TABLE dbo.SalaryHistory (
    HistoryID INT IDENTITY(1,1) PRIMARY KEY,
    EmployeeID INT,
    OldSalary DECIMAL(10,2),
    NewSalary DECIMAL(10,2),
    AdjustmentDate DATETIME2 DEFAULT GETDATE(),
    Reason NVARCHAR(100)
);
GO

-- 创建存储过程:根据绩效调整薪资
CREATE PROCEDURE dbo.usp_AdjustSalaryByPerformance
    @PerformanceLevel NVARCHAR(10), -- 'High', 'Medium', 'Low'
    @AdjustmentRate DECIMAL(3,2)   -- 调整比率,如 0.1 表示10%
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @EmpID INT, @CurrentSalary DECIMAL(10,2), @NewSalary DECIMAL(10,2);
    DECLARE @AdjustmentReason NVARCHAR(100) = '年度绩效调整 - ' + @PerformanceLevel;

    -- 声明可更新游标
    DECLARE salary_cursor CURSOR FOR
    SELECT EmployeeID, Salary
    FROM dbo.Employees
    WHERE Performance = @PerformanceLevel -- 假设有Performance列
    FOR UPDATE OF Salary;

    -- 添加Performance列(如果不存在)
    IF COL_LENGTH('dbo.Employees', 'Performance') IS NULL
    BEGIN
        ALTER TABLE dbo.Employees ADD Performance NVARCHAR(10) DEFAULT 'Medium';
        UPDATE dbo.Employees SET Performance = 
            CASE WHEN Salary > 9000 THEN 'High' 
                 WHEN Salary > 7500 THEN 'Medium' 
                 ELSE 'Low' END;
    END

    OPEN salary_cursor;
    FETCH NEXT FROM salary_cursor INTO @EmpID, @CurrentSalary;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @NewSalary = @CurrentSalary * (1 + @AdjustmentRate);

        -- 更新当前员工薪资
        UPDATE dbo.Employees 
        SET Salary = @NewSalary
        WHERE CURRENT OF salary_cursor;

        -- 记录薪资调整历史
        INSERT INTO dbo.SalaryHistory (EmployeeID, OldSalary, NewSalary, Reason)
        VALUES (@EmpID, @CurrentSalary, @NewSalary, @AdjustmentReason);

        PRINT '员工ID ' + CAST(@EmpID AS NVARCHAR) + 
              ' 薪资从 ' + CAST(@CurrentSalary AS NVARCHAR) + 
              ' 调整为 ' + CAST(@NewSalary AS NVARCHAR);

        FETCH NEXT FROM salary_cursor INTO @EmpID, @CurrentSalary;
    END

    CLOSE salary_cursor;
    DEALLOCATE salary_cursor;

    PRINT '薪资调整完成。';
END
GO

-- 执行薪资调整
EXEC dbo.usp_AdjustSalaryByPerformance @PerformanceLevel = 'Low', @AdjustmentRate = 0.15;
EXEC dbo.usp_AdjustSalaryByPerformance @PerformanceLevel = 'High', @AdjustmentRate = 0.05;

-- 查看结果
SELECT * FROM dbo.Employees;
SELECT * FROM dbo.SalaryHistory;
GO

注释

  • 结合游标实现复杂业务逻辑(绩效分级调整)。
  • 使用 WHERE CURRENT OF 精确更新。
  • 记录历史便于审计。

综合案例2:游标用于数据清洗与标准化

sql 复制代码
-- 场景:清洗客户表中的姓名字段(去除空格、统一大小写)
CREATE TABLE dbo.Customers (
    CustomerID INT IDENTITY(1,1) PRIMARY KEY,
    FirstName NVARCHAR(50),
    LastName NVARCHAR(50),
    Email NVARCHAR(100)
);
GO

INSERT INTO dbo.Customers (FirstName, LastName, Email) VALUES
('  john  ', '  doe  ', 'JOHN.DOE@EXAMPLE.COM  '),
('  Jane ', ' Smith ', '  jane.smith@example.com'),
('  Bob  ', '  Johnson  ', 'BOB.JOHNSON@EXAMPLE.COM');

-- 声明游标进行数据清洗
DECLARE clean_cursor CURSOR FOR
SELECT CustomerID, FirstName, LastName, Email
FROM dbo.Customers
FOR UPDATE OF FirstName, LastName, Email;

DECLARE @CID INT, @FName NVARCHAR(50), @LName NVARCHAR(50), @Email NVARCHAR(100);

OPEN clean_cursor;
FETCH NEXT FROM clean_cursor INTO @CID, @FName, @LName, @Email;

WHILE @@FETCH_STATUS = 0
BEGIN
    -- 清洗逻辑
    DECLARE @NewFName NVARCHAR(50) = LTRIM(RTRIM(@FName));
    DECLARE @NewLName NVARCHAR(50) = LTRIM(RTRIM(@LName));
    DECLARE @NewEmail NVARCHAR(100) = LOWER(LTRIM(RTRIM(@Email)));

    -- 如果有变化则更新
    IF @FName <> @NewFName OR @LName <> @NewLName OR @Email <> @NewEmail
    BEGIN
        UPDATE dbo.Customers 
        SET 
            FirstName = @NewFName,
            LastName = @NewLName,
            Email = @NewEmail
        WHERE CURRENT OF clean_cursor;

        PRINT '客户ID ' + CAST(@CID AS NVARCHAR) + ' 数据已清洗。';
    END

    FETCH NEXT FROM clean_cursor INTO @CID, @FName, @LName, @Email;
END

CLOSE clean_cursor;
DEALLOCATE clean_cursor;

-- 查看清洗后数据
SELECT * FROM dbo.Customers;
GO

注释

  • 游标用于逐行数据清洗和标准化。
  • 仅在数据实际变化时更新,减少日志和锁开销。
  • 替代方案:可使用单条 UPDATE 语句,但游标提供更精细控制。

综合案例3:使用 SCROLL 游标实现分页浏览功能

sql 复制代码
-- 创建存储过程:模拟分页浏览员工数据
CREATE PROCEDURE dbo.usp_BrowseEmployees
    @PageSize INT = 5,      -- 每页行数
    @PageNumber INT = 1     -- 页码(从1开始)
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @EmpID INT, @FirstName NVARCHAR(50), @LastName NVARCHAR(50), @Salary DECIMAL(10,2);
    DECLARE @Counter INT = 0;
    DECLARE @StartRow INT = (@PageNumber - 1) * @PageSize + 1;
    DECLARE @EndRow INT = @PageNumber * @PageSize;

    -- 声明 SCROLL 游标
    DECLARE browse_cursor SCROLL CURSOR FOR
    SELECT EmployeeID, FirstName, LastName, Salary
    FROM dbo.Employees
    ORDER BY EmployeeID;

    OPEN browse_cursor;

    -- 定位到起始行
    FETCH ABSOLUTE @StartRow FROM browse_cursor INTO @EmpID, @FirstName, @LastName, @Salary;

    PRINT '第 ' + CAST(@PageNumber AS NVARCHAR) + ' 页数据(每页 ' + CAST(@PageSize AS NVARCHAR) + ' 行):';
    PRINT REPLICATE('-', 50);

    WHILE @@FETCH_STATUS = 0 AND @Counter < @PageSize
    BEGIN
        PRINT 'ID: ' + CAST(@EmpID AS NVARCHAR) + 
              ', 姓名: ' + @FirstName + ' ' + @LastName + 
              ', 薪资: ' + CAST(@Salary AS NVARCHAR);

        SET @Counter = @Counter + 1;
        FETCH NEXT FROM browse_cursor INTO @EmpID, @FirstName, @LastName, @Salary;
    END

    CLOSE browse_cursor;
    DEALLOCATE browse_cursor;
END
GO

-- 测试分页
EXEC dbo.usp_BrowseEmployees @PageSize = 2, @PageNumber = 1;
EXEC dbo.usp_BrowseEmployees @PageSize = 2, @PageNumber = 2;
GO

注释

  • SCROLL 游标支持 FETCH ABSOLUTE 直接跳转到指定行。
  • 模拟分页功能,适用于需要逐页浏览的场景。
  • 实际应用中,大数据量分页推荐使用 OFFSET FETCH

六、最佳实践与注意事项

  1. 优先使用集合操作 :99% 的场景可用 UPDATE/DELETE + WHEREJOIN 替代游标。
  2. 选择合适游标类型FAST_FORWARD 性能最佳,仅在需要时使用 SCROLL
  3. 及时释放资源 :务必 CLOSEDEALLOCATE,避免内存泄漏。
  4. 避免在事务中长时间持有游标:减少锁争用。
  5. 监控性能:游标可能导致表扫描和阻塞。
  6. 考虑替代方案
    • 字符串聚合 → STRING_AGG()
    • 分页 → OFFSET FETCH
    • 逐行计算 → 窗口函数或递归CTE
  7. 测试大数据量:确保游标在生产数据规模下性能可接受。

✅ 以上内容涵盖 SQL Server 2019 游标的核心语法、管理操作及实战案例,可直接用于学习、开发与调优。游标虽强大,但请牢记:"能用集合操作解决的问题,不要用游标!"

相关推荐
强子感冒了2 小时前
JavaScript学习笔记:函数、方法与继承(原型与class)
javascript·笔记·学习
寒秋花开曾相惜2 小时前
(学习笔记)第2章 信息的表示和处理
笔记·学习
青春:一叶知秋2 小时前
【Redis存储】Redis客户端
java·数据库·redis
独泪了无痕2 小时前
通过Homebrew安装Redis指南
数据库·redis·缓存
数据知道2 小时前
PostgreSQL:如何把PostgreSQL变成时序数据库(TimescaleDB)
数据库·postgresql·时序数据库
崎岖Qiu2 小时前
【MySQL | 第11篇】一条SQL查询语句的执行全流程简析
数据库·后端·sql·mysql
w***29853 小时前
Knife4j文档请求异常(基于SpringBoot3,查找原因并解决)
java·服务器·数据库
砚边数影10 小时前
运营商网管系统重构:如何解决海量投诉数据下的“查询延迟”与“写入瓶颈”?
网络·数据库·时序数据库·kingbase·kingbasees·数据库平替用金仓·金仓数据库
shsh20010 小时前
mybatis plus打印sql日志
数据库·sql·mybatis