当前位置: 首页 > article >正文

滚雪球学Oracle[4.1讲]:PL/SQL编程

全文目录:

    • 前言
    • 0. 上期回顾
    • 1. PL/SQL简介与环境设置
      • 1.1 PL/SQL编程语言的设计哲学
      • 1.2 使用Oracle SQL Developer进行PL/SQL开发
      • 1.3 调试PL/SQL代码的最佳实践
    • 2. PL/SQL基础语法
      • 2.1 记录类型与集合类型的使用
      • 2.2 PL/SQL表与关联数组
      • 2.3 集合操作:BULK COLLECT与FORALL
    • 3. 控制结构与循环
      • 3.1 嵌套条件语句的优化
      • 3.2 PL/SQL中的复杂循环与性能调优
      • 3.3 PL/SQL中的递归调用与深度优化
    • 4. 游标管理
      • 4.1 使用参数化游标实现动态查询
      • 4.2 游标的性能调优与内存管理
      • 4.3 多游标场景下的事务管理
    • 5. 异常处理机制
      • 5.1 系统异常与用户定义异常的高级处理
      • 5.2 重试逻辑与异常日志的实现
      • 5.3 分布式事务中的异常管理
    • 6. 存储过程与函数
      • 6.1 复杂存储过程的设计与调优
      • 6.2 函数的递归调用与性能问题
      • 6.3 存储过程与函数的版本管理
    • 7. 触发器与包的使用
      • 7.1 复杂触发器的创建与调试
      • 7.2 包的分层设计与模块化
      • 7.3 包与触发器的依赖关系管理
    • 8. 动态SQL与PL/SQL
      • 8.1 执行动态SQL的安全性问题
      • 8.2 DBMS_SQL包的使用与动态SQL优化
      • 8.3 动态PL/SQL块的执行与调试
    • 9. 下期预告

前言

在Oracle数据库中,PL/SQL(Procedural Language/SQL)是用于编写复杂业务逻辑的重要工具。PL/SQL不仅扩展了SQL的功能,使其具备了流程控制、异常处理和复杂数据结构的能力,还能够与SQL无缝集成,支持数据库级的编程。掌握PL/SQL编程对于提升Oracle数据库的开发与管理能力至关重要。

在上一章中,我们深入探讨了Oracle SQL的基础知识。我们从SQL的基本语法开始,逐步深入到复杂查询的优化、数据定义语言(DDL)的使用、事务控制与锁管理,以及Oracle特有的SQL功能。通过这些内容的学习,您已经掌握了在Oracle数据库中高效编写和优化SQL语句的能力,这为您理解和应用PL/SQL打下了坚实的基础。

本章将引领您进入PL/SQL编程的世界。我们将从PL/SQL的基础语法入手,逐步探讨控制结构与循环、游标管理、异常处理机制,以及存储过程、函数、触发器和包的使用。通过实际的SQL示例,您将更好地理解PL/SQL编程的核心概念,并学会如何编写高效、健壮的PL/SQL代码。

0. 上期回顾

在第三章中,我们讨论了以下关键内容:

  • SQL语法的全面解析: 我们详细介绍了SQL的基本语法、子查询与嵌套查询的优化策略,并探讨了SQL语句的执行计划与调优分析。
  • 查询与数据操作基础: 我们重点讲解了复杂查询的优化、DML操作中的锁定机制与并发控制,以及批量数据处理的最佳实践。
  • 数据定义语言(DDL): 我们深入分析了约束的高级使用、视图、同义词和序列的管理,以及表分区的设计与实施。
  • 事务控制与锁管理: 我们探讨了事务隔离级别、锁的种类与死锁问题解决,以及多版本并发控制(MVCC)的实现原理。
  • Oracle特有的SQL功能: 我们介绍了分析函数的高级应用、模型子句的使用以及Oracle中的层次查询与递归查询。

这些内容为您理解和使用SQL打下了坚实的基础,使您能够在实际工作中编写高效的SQL查询和操作。接下来,我们将深入探讨PL/SQL编程,进一步扩展您在Oracle数据库中的开发能力。

1. PL/SQL简介与环境设置

PL/SQL是Oracle数据库的一种专有编程语言,设计用于扩展SQL的功能。通过PL/SQL,开发人员可以编写更复杂的逻辑操作,处理事务和异常,并实现存储过程和触发器等数据库对象。

1.1 PL/SQL编程语言的设计哲学

  • 紧密集成的设计: PL/SQL与SQL紧密集成,允许在PL/SQL代码中直接嵌入SQL语句,这种无缝集成简化了数据库操作,使得复杂的业务逻辑可以直接在数据库中执行。
  • 块结构语言: PL/SQL采用块结构设计,每个程序块由声明部分、执行部分和异常处理部分组成,这种结构有助于逻辑的清晰表达和代码的维护。

1.2 使用Oracle SQL Developer进行PL/SQL开发

  • 开发环境设置: Oracle SQL Developer是一个免费的集成开发环境(IDE),专门用于Oracle数据库的开发和管理。它支持PL/SQL开发、调试和优化,提供了丰富的工具来帮助开发人员编写高效的PL/SQL代码。

  • 编写与执行PL/SQL代码: 在SQL Developer中,您可以创建并执行PL/SQL块、存储过程、函数和触发器。以下是一个简单的PL/SQL匿名块示例:

    BEGIN
        DBMS_OUTPUT.PUT_LINE('Hello, PL/SQL!');
    END;
    

    执行这个块后,您将在输出窗口中看到“Hello, PL/SQL!”的消息。

1.3 调试PL/SQL代码的最佳实践

  • 调试工具使用: SQL Developer提供了强大的调试功能,允许您设置断点、逐步执行代码,并检查变量的值。这对于排查复杂的逻辑错误和性能问题非常有用。

  • 日志与输出: 使用DBMS_OUTPUT包可以在调试时输出调试信息,这有助于在代码执行过程中监控变量的状态和程序的执行流。例如:

    BEGIN
        DBMS_OUTPUT.PUT_LINE('Start of block');
        -- Some PL/SQL code
        DBMS_OUTPUT.PUT_LINE('End of block');
    END;
    

2. PL/SQL基础语法

PL/SQL提供了强大的数据处理能力,支持复杂的数据结构和集合操作。掌握PL/SQL的基础语法是编写有效代码的关键。

2.1 记录类型与集合类型的使用

  • 记录类型: PL/SQL中的记录类型允许将多个相关的数据字段组合在一起,类似于结构体。例如,创建一个员工记录类型:

    DECLARE
        TYPE EmployeeRec IS RECORD (
            employee_id   employees.employee_id%TYPE,
            employee_name employees.employee_name%TYPE,
            salary        employees.salary%TYPE
        );
        employee EmployeeRec;
    BEGIN
        SELECT employee_id, employee_name, salary
        INTO employee
        FROM employees
        WHERE employee_id = 101;
        DBMS_OUTPUT.PUT_LINE('Name: ' || employee.employee_name);
    END;
    
  • 集合类型: PL/SQL支持集合类型,如嵌套表和关联数组,用于存储和操作多个元素。以下是一个嵌套表的示例:

    DECLARE
        TYPE NumberTable IS TABLE OF NUMBER;
        salaries NumberTable;
    BEGIN
        SELECT salary BULK COLLECT INTO salaries FROM employees WHERE department_id = 10;
        FOR i IN 1..salaries.COUNT LOOP
            DBMS_OUTPUT.PUT_LINE('Salary: ' || salaries(i));
        END LOOP;
    END;
    

2.2 PL/SQL表与关联数组

  • PL/SQL表: PL/SQL表(即嵌套表)是类似于数据库表的集合,允许动态存储和处理一组相同类型的数据。

    DECLARE
        TYPE EmployeeNames IS TABLE OF VARCHAR2(50);
        names EmployeeNames;
    BEGIN
        names := EmployeeNames('John', 'Jane', 'Alice');
        FOR i IN 1..names.COUNT LOOP
            DBMS_OUTPUT.PUT_LINE('Employee: ' || names(i));
        END LOOP;
    END;
    
  • 关联数组: 关联数组(即索引表)使用字符串或数值作为索引,可以通过动态分配大小来存储大量数据:

    DECLARE
        TYPE EmployeeArray IS TABLE OF employees.salary%TYPE INDEX BY employees.employee_id%TYPE;
        salaries EmployeeArray;
    BEGIN
        salaries(101) := 5000;
        salaries(102) := 6000;
        DBMS_OUTPUT.PUT_LINE('Salary of Employee 101: ' || salaries(101));
    END;
    

2.3 集合操作:BULK COLLECT与FORALL

  • BULK COLLECT: BULK COLLECT是一种高效的集合操作,允许在一次查询中将多个行的数据批量收集到集合中:

    DECLARE
        TYPE SalaryList IS TABLE OF employees.salary%TYPE;
        salaries SalaryList;
    BEGIN
        SELECT salary BULK COLLECT INTO salaries FROM employees WHERE department_id = 10;
        FOR i IN 1..salaries.COUNT LOOP
            DBMS_OUTPUT.PUT_LINE('Salary: ' || salaries(i));
        END LOOP;
    END;
    
  • FORALL: FORALL语句用于在PL/SQL块中批量执行DML操作(如INSERT、UPDATE、DELETE),提高操作效率:

    DECLARE
        TYPE EmpIDArray IS TABLE OF employees.employee_id%TYPE;
        emp_ids EmpIDArray := EmpIDArray(101, 102, 103);
    BEGIN
        FORALL i IN 1..emp_ids.COUNT
            DELETE FROM employees WHERE employee_id = emp_ids(i);
        COMMIT;
    END;
    

3. 控制结构与循环

PL/SQL支持各种控制结构和循环机制,使得编写复杂的逻辑变得更加灵活。

3.1 嵌套条件语句的优化

  • 嵌套IF语句: 使用IF-THEN-ELSE语句可以实现多级条件判断。通过优化嵌套条件语句,可以提高代码的可读性和执行效率:

    DECLARE
        salary NUMBER := 3000;
    BEGIN
        IF salary < 1000 THEN
    
    
            DBMS_OUTPUT.PUT_LINE('Low salary');
        ELSIF salary < 5000 THEN
            DBMS_OUTPUT.PUT_LINE('Average salary');
        ELSE
            DBMS_OUTPUT.PUT_LINE('High salary');
        END IF;
    END;
    

3.2 PL/SQL中的复杂循环与性能调优

  • 循环结构: PL/SQL支持多种循环结构,包括简单循环、WHILE循环和FOR循环。合理选择和优化循环结构,可以避免不必要的性能开销。例如:

    DECLARE
        counter NUMBER := 0;
    BEGIN
        FOR i IN 1..10 LOOP
            counter := counter + i;
            DBMS_OUTPUT.PUT_LINE('Counter: ' || counter);
        END LOOP;
    END;
    
  • 循环调优: 在处理大数据集时,应避免使用嵌套循环,通过使用BULK COLLECT和FORALL语句,可以显著提高批量处理的性能。

3.3 PL/SQL中的递归调用与深度优化

  • 递归调用: PL/SQL允许在过程和函数中实现递归调用,用于处理层次结构的数据或复杂的计算。例如,计算阶乘:

    DECLARE
        FUNCTION factorial(n NUMBER) RETURN NUMBER IS
        BEGIN
            IF n = 1 THEN
                RETURN 1;
            ELSE
                RETURN n * factorial(n - 1);
            END IF;
        END;
    BEGIN
        DBMS_OUTPUT.PUT_LINE('Factorial of 5: ' || factorial(5));
    END;
    
  • 深度优化: 在递归调用中,避免过深的递归层次,并通过尾递归优化(如果可能)来提高性能。

4. 游标管理

游标是PL/SQL中处理查询结果集的关键工具,掌握游标管理对于高效的数据库编程至关重要。

4.1 使用参数化游标实现动态查询

  • 参数化游标: 游标可以使用参数来动态控制查询条件,这使得游标更具灵活性。例如:

    DECLARE
        CURSOR emp_cursor(dept_id NUMBER) IS
            SELECT employee_name, salary FROM employees WHERE department_id = dept_id;
        employee_name employees.employee_name%TYPE;
        salary employees.salary%TYPE;
    BEGIN
        OPEN emp_cursor(10);
        LOOP
            FETCH emp_cursor INTO employee_name, salary;
            EXIT WHEN emp_cursor%NOTFOUND;
            DBMS_OUTPUT.PUT_LINE('Name: ' || employee_name || ', Salary: ' || salary);
        END LOOP;
        CLOSE emp_cursor;
    END;
    

4.2 游标的性能调优与内存管理

  • 性能调优: 在使用游标时,应尽量减少游标的生命周期,及时关闭游标以释放资源。此外,避免在循环中频繁打开和关闭游标,可以通过缓存查询结果集来提高性能。

  • 内存管理: 通过合理设置游标的批量获取行数,可以优化内存使用。例如,使用BULK COLLECT结合LIMIT子句:

    DECLARE
        CURSOR emp_cursor IS SELECT employee_name FROM employees;
        TYPE emp_table IS TABLE OF employees.employee_name%TYPE;
        employee_names emp_table;
    BEGIN
        OPEN emp_cursor;
        LOOP
            FETCH emp_cursor BULK COLLECT INTO employee_names LIMIT 100;
            EXIT WHEN employee_names.COUNT = 0;
            FOR i IN 1..employee_names.COUNT LOOP
                DBMS_OUTPUT.PUT_LINE('Employee: ' || employee_names(i));
            END LOOP;
        END LOOP;
        CLOSE emp_cursor;
    END;
    

4.3 多游标场景下的事务管理

  • 多游标事务管理: 在处理多个游标时,确保事务的一致性非常重要。应在合适的时间点提交或回滚事务,以防止数据的不一致。例如:

    DECLARE
        CURSOR cursor1 IS SELECT employee_id FROM employees WHERE department_id = 10;
        CURSOR cursor2 IS SELECT department_id FROM departments WHERE location_id = 1700;
    BEGIN
        OPEN cursor1;
        OPEN cursor2;
    
        -- Perform operations with cursor1 and cursor2
        -- Commit or rollback transactions as needed
    
        CLOSE cursor1;
        CLOSE cursor2;
    END;
    

5. 异常处理机制

在PL/SQL编程中,处理异常是保障程序健壮性的重要环节。Oracle提供了丰富的异常处理机制,以应对各种可能的运行时错误。

5.1 系统异常与用户定义异常的高级处理

  • 系统异常: Oracle预定义了一些系统异常,例如NO_DATA_FOUND、TOO_MANY_ROWS等。可以在PL/SQL代码中使用这些异常处理块捕获并处理这些错误。例如:

    BEGIN
        SELECT salary INTO v_salary FROM employees WHERE employee_id = 999;
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            DBMS_OUTPUT.PUT_LINE('No data found for the specified employee.');
    END;
    
  • 用户定义异常: 开发人员可以自定义异常,并在程序逻辑中根据需要抛出和捕获这些异常。例如:

    DECLARE
        ex_salary_limit EXCEPTION;
        salary NUMBER := 6000;
    BEGIN
        IF salary > 5000 THEN
            RAISE ex_salary_limit;
        END IF;
    EXCEPTION
        WHEN ex_salary_limit THEN
            DBMS_OUTPUT.PUT_LINE('Salary exceeds the limit.');
    END;
    

5.2 重试逻辑与异常日志的实现

  • 重试逻辑: 在处理可能失败的操作(如网络通信或资源争用)时,重试逻辑是一种常见的容错机制。可以通过在异常处理块中实现重试。例如:

    DECLARE
        RETRY_COUNT CONSTANT NUMBER := 3;
        attempt NUMBER := 0;
    BEGIN
        LOOP
            BEGIN
                attempt := attempt + 1;
                -- Attempt some operation
                EXIT; -- Exit loop on success
            EXCEPTION
                WHEN OTHERS THEN
                    IF attempt < RETRY_COUNT THEN
                        DBMS_OUTPUT.PUT_LINE('Retrying operation...');
                    ELSE
                        RAISE;
                    END IF;
            END;
        END LOOP;
    END;
    
  • 异常日志: 在捕获异常时,将异常信息记录到日志中,有助于后续分析和调试。例如:

    EXCEPTION
        WHEN OTHERS THEN
            DBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM);
            -- Insert error details into a log table
            INSERT INTO error_log (error_message, error_time) VALUES (SQLERRM, SYSDATE);
            RAISE;
    

5.3 分布式事务中的异常管理

  • 分布式事务异常处理: 在分布式数据库环境中,事务可能跨越多个数据库,处理异常变得更加复杂。使用Oracle的分布式事务管理功能,可以确保在多个节点上的操作要么全部提交,要么全部回滚:

    BEGIN
        EXECUTE IMMEDIATE 'SET TRANSACTION USE ROLLBACK SEGMENT rbs1';
        -- Perform distributed transaction
    EXCEPTION
        WHEN OTHERS THEN
            ROLLBACK;
            DBMS_OUTPUT.PUT_LINE('Distributed transaction failed and was rolled back.');
    END;
    

6. 存储过程与函数

存储过程和函数是PL/SQL中重要的编程结构,广泛应用于封装业务逻辑、提高代码重用性和执行效率。

6.1 复杂存储过程的设计与调优

  • 存储过程设计: 存储过程用于封装一系列操作,并可以接受参数。通过设计存储过程,您可以将复杂的业务逻辑放在数据库中执行。例如:

    CREATE OR REPLACE PROCEDURE update_salary (
        p_employee_id IN employees.employee_id%TYPE,
        p_new_salary  IN employees.salary%TYPE
    ) IS
    BEGIN
        UPDATE employees
        SET salary = p_new_salary
        WHERE employee_id = p_employee_id;
        COMMIT;
    END;
    
  • 存储过程调优: 为了提高存储过程的执行效率,可以通过优化SQL查询、减少游标的使用、避免嵌套循环等方式进行调优。此外,使用PRAGMA指令可以告知编译器进行进一步优化。

6.2 函数的递归调用与性能问题

  • 函数的使用: 函数用于执行计算并返回结果。与存储过程不同,函数可以在SQL语句中使用。例如:

    CREATE OR REPLACE FUNCTION calculate_bonus (
        p_salary IN employees.salary%TYPE
    ) RETURN NUMBER IS
    BEGIN
        RETURN p_salary * 0.1;
    END;
    
  • 递归调用与性能优化: 在处理层次数据或复杂计算时,函数可以调用自身形成递归。然而,递归调用需要谨慎使用,以防止栈溢出和性能问题。可以通过尾递归优化和限制递

归深度来避免这些问题。

6.3 存储过程与函数的版本管理

  • 版本管理: 在开发过程中,存储过程和函数可能需要多次修改和优化。通过维护版本号和注释,您可以有效管理代码的版本。例如:

    CREATE OR REPLACE PROCEDURE update_salary_v2 (
        p_employee_id IN employees.employee_id%TYPE,
        p_new_salary  IN employees.salary%TYPE
    ) IS
    -- Version 2: Added validation check
    BEGIN
        IF p_new_salary < 0 THEN
            RAISE_APPLICATION_ERROR(-20001, 'Salary cannot be negative.');
        END IF;
        UPDATE employees
        SET salary = p_new_salary
        WHERE employee_id = p_employee_id;
        COMMIT;
    END;
    

7. 触发器与包的使用

触发器和包是PL/SQL中的高级编程结构,用于自动化任务和组织PL/SQL代码。

7.1 复杂触发器的创建与调试

  • 触发器的使用: 触发器是在表或视图上的DML操作发生时自动执行的PL/SQL块。复杂触发器可以处理多表操作、审计记录等任务。例如,创建一个记录修改日志的触发器:

    CREATE OR REPLACE TRIGGER audit_employee_changes
    AFTER UPDATE ON employees
    FOR EACH ROW
    BEGIN
        INSERT INTO employee_audit_log (employee_id, old_salary, new_salary, modified_date)
        VALUES (:OLD.employee_id, :OLD.salary, :NEW.salary, SYSDATE);
    END;
    

7.2 包的分层设计与模块化

  • 包的概念: 包是PL/SQL中的一种结构化编程工具,用于将相关的过程、函数、变量和游标组织在一起。包的分层设计和模块化有助于提高代码的可读性和重用性。例如:

    CREATE OR REPLACE PACKAGE employee_pkg AS
        PROCEDURE update_salary(p_employee_id IN employees.employee_id%TYPE, p_new_salary IN employees.salary%TYPE);
        FUNCTION calculate_bonus(p_salary IN employees.salary%TYPE) RETURN NUMBER;
    END employee_pkg;
    
    CREATE OR REPLACE PACKAGE BODY employee_pkg AS
        PROCEDURE update_salary(p_employee_id IN employees.employee_id%TYPE, p_new_salary IN employees.salary%TYPE) IS
        BEGIN
            UPDATE employees SET salary = p_new_salary WHERE employee_id = p_employee_id;
            COMMIT;
        END;
    
        FUNCTION calculate_bonus(p_salary IN employees.salary%TYPE) RETURN NUMBER IS
        BEGIN
            RETURN p_salary * 0.1;
        END;
    END employee_pkg;
    

7.3 包与触发器的依赖关系管理

  • 依赖关系管理: 在开发和维护中,确保包与触发器之间的依赖关系正确是至关重要的。使用Oracle的数据字典视图(如ALL_DEPENDENCIES),可以跟踪依赖关系并在代码修改时及时更新触发器和包。

    SELECT name, type, referenced_name, referenced_type
    FROM ALL_DEPENDENCIES
    WHERE name = 'EMPLOYEE_PKG';
    

8. 动态SQL与PL/SQL

动态SQL允许在运行时构建和执行SQL语句,这在处理复杂查询和数据库结构时非常有用。

8.1 执行动态SQL的安全性问题

  • SQL注入风险: 动态SQL存在SQL注入的风险,尤其是在直接使用用户输入构建SQL语句时。通过使用绑定变量,可以有效防止SQL注入。例如:

    DECLARE
        sql_stmt VARCHAR2(200);
        emp_id  NUMBER := 101;
    BEGIN
        sql_stmt := 'SELECT salary FROM employees WHERE employee_id = :emp_id';
        EXECUTE IMMEDIATE sql_stmt INTO v_salary USING emp_id;
    END;
    

8.2 DBMS_SQL包的使用与动态SQL优化

  • DBMS_SQL包: DBMS_SQL包是Oracle提供的用于动态SQL处理的高级工具,支持动态游标的打开、绑定变量的处理和执行计划的优化。例如:

    DECLARE
        cursor_name INTEGER;
        emp_name    VARCHAR2(50);
    BEGIN
        cursor_name := DBMS_SQL.OPEN_CURSOR;
        DBMS_SQL.PARSE(cursor_name, 'SELECT employee_name FROM employees WHERE employee_id = :id', DBMS_SQL.NATIVE);
        DBMS_SQL.BIND_VARIABLE(cursor_name, ':id', 101);
        DBMS_SQL.DEFINE_COLUMN(cursor_name, 1, emp_name);
        DBMS_SQL.EXECUTE(cursor_name);
        DBMS_SQL.FETCH_ROWS(cursor_name);
        DBMS_SQL.COLUMN_VALUE(cursor_name, 1, emp_name);
        DBMS_OUTPUT.PUT_LINE('Employee Name: ' || emp_name);
        DBMS_SQL.CLOSE_CURSOR(cursor_name);
    END;
    

8.3 动态PL/SQL块的执行与调试

  • 动态PL/SQL块: 动态SQL不仅可以执行查询,还可以动态执行PL/SQL块,这对于动态控制逻辑和自动化任务非常有用。例如:

    DECLARE
        plsql_block VARCHAR2(500);
    BEGIN
        plsql_block := 'BEGIN DBMS_OUTPUT.PUT_LINE(''Dynamic PL/SQL execution''); END;';
        EXECUTE IMMEDIATE plsql_block;
    END;
    
  • 调试动态PL/SQL: 通过结合DBMS_SQL包和日志输出,可以有效调试和优化动态PL/SQL块的执行。

9. 下期预告

在本章中,我们深入探讨了PL/SQL编程的核心内容,从基础语法到复杂的控制结构、游标管理、异常处理机制、存储过程与函数的使用,再到动态SQL的执行与优化。通过这些内容的学习,您已经掌握了在Oracle数据库中编写高效、健壮的PL/SQL代码的能力,这将大大提升您的数据库开发和管理水平。

在下一章中,我们将进入Oracle数据库管理与维护的领域。这一章将重点讨论用户与权限管理、数据库备份与恢复、性能监控与优化等内容。通过这些内容的学习,您将学会如何确保数据库的安全性、可用性和高性能,为企业的数据资产保驾护航。请继续关注我们的Oracle数据库学习专栏,下一期我们将带您深入探讨数据库管理与维护的关键技术,帮助您成为一名全面的数据库专家。


http://www.kler.cn/a/328341.html

相关文章:

  • 内容占位符:Kinetic Loader HTML+CSS 使用CSS制作三角形原理
  • Leetcode 3355 Zero Array Transformation
  • 大学作业参考:网页设计作业 - 工作计划-Java SQL HTML源码下载
  • Spring Boot中集成Redis与MySQL
  • Siglus引擎 Unpack | 未完待续
  • Java-异步方法@Async+自定义分布式锁注解Redission例子
  • 【开源免费】基于SpringBoot+Vue.JS美容院管理系统(JAVA毕业设计)
  • C0008.Clion利用C++开发Qt界面,使用OpenCV时,配置OpenCV方法
  • Sharding-JDBC笔记03-分库分表代码示例
  • redis01
  • 高级java每日一道面试题-2024年9月27日-数据库篇-性别是否适合做索引?
  • Leetcode45. 跳跃游戏 II
  • 「安装」 Windows下安装CUDA和Pytorch
  • linux如何与网络时间对齐(雪花算法ID重复)
  • 【AAOS】CarService -- Android汽车服务
  • 【Web】Electron:第一个桌面程序
  • Python与C#关于switch的使用区别
  • [python][pipenv]pipenv的使用
  • 输出 / 目录下所有目录文件的大小并排序
  • 如何改变音频声音大小?关于改变音频大小的方法介绍
  • NLP任务之文本分类(情感分析)
  • 简单vue指令实现 el-table 可拖拽表格功能
  • Qt C++设计模式->享元模式
  • Windows远程Kylin系统-xrdp
  • CTF中文件包含
  • 【优选算法】(第三篇)