Oracle数据库数据编程SQL<3.5 PL/SQL 存储过程(Procedure)>

存储过程(Stored Procedure)是 Oracle 数据库中一组预编译的 PL/SQL 语句集合,存储在数据库中并可通过名称调用执行。它们是企业级数据库应用开发的核心组件。

目录

一、存储过程基础

[1. 存储过程特点](#1. 存储过程特点)

[2. 创建基本语法](#2. 创建基本语法)

[3. 存储过程优点](#3. 存储过程优点)

[4. 简单示例](#4. 简单示例)

二、没有参数的存储过程

[1. 简单示例](#1. 简单示例)

三、有参数的存储过程

[1. 参数模式](#1. 参数模式)

[2. 有输入值 IN](#2. 有输入值 IN)

[3. 有输出值 OUT](#3. 有输出值 OUT)

[4. 有输入输出值IN OUT](#4. 有输入输出值IN OUT)

(1)编译:

(2)调用​编辑

(3)宏&输入名称​编辑

(4)查看输出结果

四、存储过程的调用总结

五、存储过程中的DML操作

[1. 基本DML示例](#1. 基本DML示例)

[2. 使用RETURNING子句](#2. 使用RETURNING子句)

六、异常处理

[1. 预定义异常](#1. 预定义异常)

[2. 自定义异常](#2. 自定义异常)

七、游标处理

[1. 显式游标](#1. 显式游标)

[2. REF游标(动态游标)](#2. REF游标(动态游标))

八、高级特性

[1. 自治事务](#1. 自治事务)

[2. 批量处理(FORALL)](#2. 批量处理(FORALL))

[3. 条件编译](#3. 条件编译)

九、存储过程管理

[1. 查看存储过程](#1. 查看存储过程)

右键查看

[2. 重新编译](#2. 重新编译)

右键重新编译

右键编辑--执行

[3. 权限控制](#3. 权限控制)

[4. 删除存储过程](#4. 删除存储过程)

十、最佳实践

十一、存储过程和函数的区别


一、存储过程基础

1. 存储过程特点

  • 预编译执行:提高性能,减少解析开销

  • 模块化设计:促进代码重用和维护

  • 增强安全性:通过权限控制保护数据

  • 减少网络流量:客户端只需调用过程名而非发送多句SQL

  • 事务控制:可在过程中管理完整事务

2. 创建基本语法

sql 复制代码
CREATE [OR REPLACE] PROCEDURE procedure_name
    [(parameter1 [IN|OUT|IN OUT] datatype [DEFAULT|:= value],
     parameter2 [IN|OUT|IN OUT] datatype [DEFAULT|:= value],
     ...)]
[IS|AS]
    [declaration_section]
BEGIN
    executable_section
[EXCEPTION
    exception_section]
END [procedure_name];
/

create {or replace} procedure pro_name(v1 in/out/in out 类型)
as/is
{声明变量}
begin
要执行的语句;
end;
/

(1)创建 creat or replace procedure
(2)声明变量
(3)开始 begin
(4)DML操作
(5)异常处理 exception
(6)结束 end

3. 存储过程优点

(1)存储过程只在创建时进行编译,以后每次执行都不需要重新编译,而一般的SQL语句每执行一次就编译一次,所以使用存储过程可以提高数据库的执行速度。

(2)当对数据库进行复杂操作时(比如对多个表进行查询、修改操作),可以将此复杂的事务处理结合一起使用这些操作。如果用SQL需要多次连接数据库,如果用存储过程,只需要连接一次数据库。

(3)存储过程可以重复使用,可以减少数据库开发人员的工作量。

4. 简单示例

sql 复制代码
CREATE OR REPLACE PROCEDURE update_employee_salary(       --创建--存过主题结构
---------------------------------------------------------------------------------
    p_emp_id IN employees.employee_id%TYPE,
    p_percent IN NUMBER DEFAULT 10
) AS
    v_old_salary employees.salary%TYPE;                   --声明变量--存过主题结构
---------------------------------------------------------------------------------
BEGIN                                                     --开始--存过主题结构
---------------------------------------------------------------------------------
    -- 获取当前薪资
    SELECT salary INTO v_old_salary
    FROM employees
    WHERE employee_id = p_emp_id;
    
    -- 更新薪资
    UPDATE employees
    SET salary = salary * (1 + p_percent/100)
    WHERE employee_id = p_emp_id;
    
    -- 输出结果
    DBMS_OUTPUT.PUT_LINE('员工ID ' || p_emp_id || 
                        ' 薪资从 ' || v_old_salary || 
                        ' 调整为 ' || (v_old_salary * (1 + p_percent/100)));
    
    COMMIT;                                               --DML操作--存过主题结构
---------------------------------------------------------------------------------
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('错误: 未找到员工ID ' || p_emp_id);
        ROLLBACK;
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('错误: ' || SQLERRM);
        ROLLBACK;                                         --异常处理--存过主题结构
---------------------------------------------------------------------------------
END update_employee_salary;                               --结束--存过主题结构
---------------------------------------------------------------------------------
/

二、没有参数的存储过程

1. 简单示例

sql 复制代码
--编写一个存储过程,将emp表中和编号7788相同部门的员工信息插入到
--emp3中,将工作为CLERK的工资加300后插入到emp4中。
-- 创建
create or replace procedure pro2 as   --创建--存过主题结构
begin                                 --开始--存过主题结构
------------------------------------------------------------------
  --DML操作
  insert into emp3
    select *
      from emp
     where deptno = (select deptno from emp where empno = 7788);
  --DML操作
  insert into emp4
    select e.empno,
           e.ename,
           e.job,
           e.mgr,
           e.hiredate,
           e.sal + 300,
           e.comm,
           e.deptno
      from emp e
     where job = 'CLERK';
------------------------------------------------------------------
end;                                   --结束--存过主题结构
/
-- 调用:
call pro2();
-- 查询、验证
select * from emp3;
select * from emp4;

三、有参数的存储过程

1. 参数模式

|------------|-------------|-------------------------|
| 模式 | 描述 | 示例 |
| IN | 只读参数(默认) | p_id IN NUMBER |
| OUT | 只写参数,返回给调用者 | p_result OUT VARCHAR2 |
| IN OUT | 可读写参数 | p_counter IN OUT NUMBER |

2. 有输入值 IN

sql 复制代码
--输入员工编号,输出姓名和薪资。
-- 创建
create or replace procedure pro1(v_empno number) as
  v_name varchar2(20);
  v_sal  emp.sal%type;
begin
  select ename, sal into v_name, v_sal from emp where empno = v_empno;
  dbms_output.put_line(v_name || v_sal);
end;
-- 调用:
call pro1(7788);

【调用方法】
在sql窗口  call pro_name(参数); --sql窗口括号不能省
在命令窗口 exec pro_name(参数);



/*===============================================================================*/
【练习1】
--创建一张emp3数据同emp
--更改emp3的sal列的长度为number(20,2)
--编写一个存储过程
--输入一个数字和一个部门编号
--要求数字是0-9的整数(如果不是,抛出异常,并打印'请输入0-9的整数')
--当部门人数小于该数字,将该部门的员工信息插入到emp1
                       --显示插入了多少行
--当部门人数大于该数字,将该部门的员工姓名,编号删除
                     --并显示删除了多少人
--当部门人数等于该数字,不该部门的全部员工工资变成原工资的二次方
                    --并显示增加了多少人的工资
-- 准备:
CREAT TABLE EMP3 AS SELECT * FORM EMP;
ALTER TABLE EMP3 MODIFY SAL NUMBER(20,2);
-- 创建:
CREATE OR REPLACE PROCEDURE PRO_3(V1 NUMBER,V_DEPTNO NUMBER) AS
ERR EXCEPTION;
V3 NUMBER;
BEGIN
  IF v1 NOT IN (0,1,2,3,4,5,6,7,8,9)THEN
    RAISE ERR;
    END IF;
   SELECT COUNT(*) INTO V3 FROM EMP3 WHERE DEPTNO=V_DEPTNO;
   IF V3<V1 THEN INSERT INTO EMP1 SELECT * FROM EMP3 WHERE DEPTNO=V_DEPTNO;
     dbms_output.put_line('插入了'||sql%rowcount||'行');
   ELSIF v3>v1 THEN UPDATE emp3 SET ename=NULL,empno=null WHERE deptno=v_deptno;
        dbms_output.put_line('删了'||sql%rowcount||'人');
   ELSE UPDATE emp3 SET sal=POWER(sal,2) WHERE deptno=v_deptno;
    dbms_output.put_line(sql%rowcount||'人的工资增加了');
   END IF; 
EXCEPTION 
  WHEN ERR THEN DBMS_output.put_line('请输入0-9的整数');
  END;
-- 调用:
CALL pro_3(2,10)
-- 验证:
SELECT * FROM emp3

/*===============================================================================*/
【练习2】
--新建一张表emp2和emp数据相同。
--编写一个存储过程,输入一个数字和一个部门编号。
--要求数字是0-9的整数
--当该部门人数小于该数字将该部门员工信息插入到emp3中;
--当该部门人数大于该数字将该部门的员工姓名编号删除;
--当该部门人数等于该数字则该部门全部员工工资加666。
-- 创建
create or replace procedure pro4(v_num number, v_deptno number) as exception;
begin
  select count(*) into v_count from emp where deptno = v_deptno;
  if v_num not in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) then
    raise err;
  elsif v_count < v_num then
    insert into emp3
      select * from emp2 where deptno = v_deptno;
    dbms_output.put_line(v_deptno||'部门人数' || v_count || '<' || v_num);
  elsif v_count > v_num then
    update emp2 set ename = null, empno = null where deptno = v_deptno;
    dbms_output.put_line(v_deptno||'部门人数' || v_count || '>' || v_num);
  else
    update emp2 set sal = sal + 666 where deptno = v_deptno;
    dbms_output.put_line(v_deptno||'部门人数' || v_count || '=' || v_num);
  end if;
exception
  when err then
    dbms_output.put_line('请输入0-9的整数');
    raise;
end;
-- 调用:
call pro4(3,10);

3. 有输出值 OUT

sql 复制代码
/*===============================================================================*/
【练习1】
--输入:姓名
--输出:如果工资比MILLER高,输出高,比MILLER低输出低,一样的话巧了
-- 创建
create or replace procedure pro3(v1 varchar2, v2 out varchar2) as
  v_3 number;
  v_4 number;
begin
  select sal into v_sal_m from emp where ename = 'MILLER';
  select sal into v_sal_t from emp where ename = v1;
  if v_sal_t > v_sal_m then
    v2:='高';
  elsif v_sal_t < v_sal_m then
    v2:='低';
  else v2:='巧了';
  end if;
end;
/
-- 调用:
declare
  v2 varchar2(4);
begin
  pro3(&a, v2);
  dbms_output.put_line(v2);
end;
/
/*===============================================================================*/
【练习2】
--输入:姓名
--输出: 如果部门和MILLER一样,输出一样,不一样输出不一样
-- 创建
create or replace procedure pro4(v1 varchar2, v2 out varchar2) as
  v_deptno_m number;
  v_deptno   number;
begin
  select deptno into v_deptno_m from emp where ename = 'MILLER';
  select deptno into v_deptno from emp where ename = v1;
  if v_deptno = v_deptno_m then
    v2 := '一样';
  else
    v2 := '不一样';
  end if;
  dbms_output.put_line(v2);
end;
/
-- 调用:
declare
  v2 varchar2(6);
begin
  pro4('&a', v2);
end;
/
/*===============================================================================*/
【练习3】存过名称不建议使用中文
--输入:姓名
--输出:如果部门和MILLER一样,输出一样,不一样输出不一样
-- 创建
create or replace procedure 判断是否和MILLER信息一样(v1 varchar2, v2 out varchar2) as
  v_d_m number;
  v_d_t number;
begin
  select deptno into v_d_m from emp where ename = 'MILLER';
  select deptno into v_d_t from emp where ename = v1;
  if v_d_t = v_d_m then
    v2 := '一样';
  else
    v2 := 'MMP不一样,滚';
  end if;
end;
/
-- 调用:
declare
  v2 varchar2(20);
begin
  判断是否和MILLER信息一样(&a, v2);
  dbms_output.put_line(v2);
end;
/

4. 有输入输出值IN OUT

sql 复制代码
--输入两个名字,把两个人的名字的首字母大写并拼接
--输出更新后的名字
-- 创建
CREATE OR REPLACE PROCEDURE pro_5(v1 IN OUT VARCHAR2,v2 IN OUT VARCHAR2) AS
BEGIN 
  v1:=INITCAP(v1);
  v2:=INITCAP(v2);
END;
-- 调用
DECLARE
  v1 VARCHAR2(20):='&A';
  v2 VARCHAR2(20):='&B';
BEGIN
    pro_5(v1,v2);
    dbms_output.put_line(v1||v2);
END;

(1)编译:

(2)调用

(3)宏&输入名称

(4)查看输出结果

四、存储过程的调用总结

|--------------|-------------------------------------|
| 存过不同类型创建 | 调用方式 |
| 没有参数 | call pro_name()/exec pro_name |
| 只有输入值 | call pro_name(参数)/exec pro_name(参数) |
| 有输出值 | pl/sql调用 |
| 有输入输出 | pl/sql调用 |

五、存储过程中的DML操作

1. 基本DML示例

sql 复制代码
CREATE OR REPLACE PROCEDURE transfer_employee(
    p_emp_id IN NUMBER,
    p_new_dept_id IN NUMBER,
    p_salary_adjustment IN NUMBER DEFAULT 0
) AS
    v_old_dept_id NUMBER;
    v_new_dept_name VARCHAR2(100);
BEGIN
    -- 获取原部门ID
    SELECT department_id INTO v_old_dept_id
    FROM employees
    WHERE employee_id = p_emp_id;
    
    -- 获取新部门名称
    SELECT department_name INTO v_new_dept_name
    FROM departments
    WHERE department_id = p_new_dept_id;
    
    -- 更新员工记录
    UPDATE employees
    SET department_id = p_new_dept_id,
        salary = salary + p_salary_adjustment
    WHERE employee_id = p_emp_id;
    
    -- 记录调动历史
    INSERT INTO transfer_history (
        transfer_id, employee_id, 
        from_dept_id, to_dept_id, 
        transfer_date
    ) VALUES (
        transfer_seq.NEXTVAL, p_emp_id,
        v_old_dept_id, p_new_dept_id,
        SYSDATE
    );
    
    COMMIT;
    DBMS_OUTPUT.PUT_LINE('成功将员工 ' || p_emp_id || 
                        ' 从部门 ' || v_old_dept_id || 
                        ' 调至 ' || v_new_dept_name);
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('调动失败: ' || SQLERRM);
        ROLLBACK;
END transfer_employee;
/

2. 使用RETURNING子句

sql 复制代码
CREATE OR REPLACE PROCEDURE promote_employee(
    p_emp_id IN NUMBER,
    p_new_job_id IN VARCHAR2,
    p_salary_increase IN NUMBER,
    p_new_salary OUT NUMBER
) AS
BEGIN
    UPDATE employees
    SET job_id = p_new_job_id,
        salary = salary + p_salary_increase
    WHERE employee_id = p_emp_id
    RETURNING salary INTO p_new_salary;
    
    COMMIT;
END promote_employee;
/

六、异常处理

1. 预定义异常

异常 触发条件
NO_DATA_FOUND SELECT INTO未返回行
TOO_MANY_ROWS SELECT INTO返回多行
DUP_VAL_ON_INDEX 违反唯一约束
INVALID_CURSOR 非法游标操作
ZERO_DIVIDE 除零错误
LOGIN_DENIED 无效的用户名/密码
PROGRAM_ERROR PL/SQL内部错误

2. 自定义异常

sql 复制代码
CREATE OR REPLACE PROCEDURE process_order(
    p_order_id IN NUMBER,
    p_discount IN NUMBER DEFAULT 0
) AS
    e_invalid_discount EXCEPTION;
    PRAGMA EXCEPTION_INIT(e_invalid_discount, -20001);
    
    v_order_total NUMBER;
BEGIN
    -- 验证折扣率
    IF p_discount < 0 OR p_discount > 0.5 THEN
        RAISE e_invalid_discount;
    END IF;
    
    -- 计算订单总额
    SELECT SUM(unit_price * quantity) * (1 - p_discount)
    INTO v_order_total
    FROM order_items
    WHERE order_id = p_order_id;
    
    -- 更新订单总额
    UPDATE orders
    SET order_total = v_order_total
    WHERE order_id = p_order_id;
    
    COMMIT;
EXCEPTION
    WHEN e_invalid_discount THEN
        DBMS_OUTPUT.PUT_LINE('错误: 折扣率必须在0到0.5之间');
        ROLLBACK;
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('错误: 未找到订单 ' || p_order_id);
        ROLLBACK;
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('错误代码: ' || SQLCODE);
        DBMS_OUTPUT.PUT_LINE('错误信息: ' || SQLERRM);
        ROLLBACK;
END process_order;
/

七、游标处理

1. 显式游标

sql 复制代码
CREATE OR REPLACE PROCEDURE generate_department_report(
    p_dept_id IN NUMBER DEFAULT NULL
) AS
    CURSOR dept_cur IS
        SELECT department_id, department_name
        FROM departments
        WHERE department_id = NVL(p_dept_id, department_id);
        
    CURSOR emp_cur(p_dept NUMBER) IS
        SELECT employee_id, last_name, salary
        FROM employees
        WHERE department_id = p_dept
        ORDER BY salary DESC;
        
    v_total_salary NUMBER;
BEGIN
    FOR dept_rec IN dept_cur LOOP
        DBMS_OUTPUT.PUT_LINE('部门: ' || dept_rec.department_name);
        DBMS_OUTPUT.PUT_LINE('--------------------------------');
        
        v_total_salary := 0;
        FOR emp_rec IN emp_cur(dept_rec.department_id) LOOP
            DBMS_OUTPUT.PUT_LINE(
                RPAD(emp_rec.employee_id, 10) ||
                RPAD(emp_rec.last_name, 20) ||
                TO_CHAR(emp_rec.salary, '$999,999.00'));
                
            v_total_salary := v_total_salary + emp_rec.salary;
        END LOOP;
        
        DBMS_OUTPUT.PUT_LINE('--------------------------------');
        DBMS_OUTPUT.PUT_LINE('部门总薪资: ' || 
                            TO_CHAR(v_total_salary, '$999,999.00'));
        DBMS_OUTPUT.PUT_LINE(CHR(10));  -- 空行
    END LOOP;
END generate_department_report;
/

2. REF游标(动态游标)

sql 复制代码
CREATE OR REPLACE PROCEDURE get_employee_data(
    p_query_type IN VARCHAR2,
    p_result_set OUT SYS_REFCURSOR
) AS
BEGIN
    IF p_query_type = 'HIGH_SALARY' THEN
        OPEN p_result_set FOR
            SELECT employee_id, last_name, salary
            FROM employees
            WHERE salary > 10000
            ORDER BY salary DESC;
    ELSIF p_query_type = 'BY_DEPARTMENT' THEN
        OPEN p_result_set FOR
            SELECT e.employee_id, e.last_name, d.department_name
            FROM employees e
            JOIN departments d ON e.department_id = d.department_id
            ORDER BY d.department_name, e.last_name;
    ELSE
        OPEN p_result_set FOR
            SELECT employee_id, last_name, hire_date
            FROM employees
            ORDER BY hire_date DESC;
    END IF;
END get_employee_data;
/

八、高级特性

1. 自治事务

允许在过程中创建独立的事务:

sql 复制代码
CREATE OR REPLACE PROCEDURE log_activity(
    p_action IN VARCHAR2,
    p_user IN VARCHAR2 DEFAULT USER
) AS
    PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
    INSERT INTO activity_log (
        log_id, action_name, 
        user_name, log_time
    ) VALUES (
        log_seq.NEXTVAL, p_action,
        p_user, SYSTIMESTAMP
    );
    COMMIT;
EXCEPTION
    WHEN OTHERS THEN
        ROLLBACK;
        RAISE;
END log_activity;
/

2. 批量处理(FORALL)

sql 复制代码
CREATE OR REPLACE PROCEDURE update_multiple_salaries(
    p_emp_ids IN SYS.ODCINUMBERLIST,
    p_percent IN NUMBER
) AS
BEGIN
    FORALL i IN 1..p_emp_ids.COUNT
        UPDATE employees
        SET salary = salary * (1 + p_percent/100)
        WHERE employee_id = p_emp_ids(i);
        
    log_activity('批量更新薪资', USER);
    COMMIT;
    
    DBMS_OUTPUT.PUT_LINE('成功更新 ' || SQL%ROWCOUNT || ' 条记录');
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('批量更新失败: ' || SQLERRM);
        ROLLBACK;
END update_multiple_salaries;
/

3. 条件编译

sql 复制代码
CREATE OR REPLACE PROCEDURE debug_procedure AS
    v_debug BOOLEAN := TRUE;
BEGIN
    $IF $$DEBUG $THEN
        DBMS_OUTPUT.PUT_LINE('调试信息: 开始执行过程');
    $END
    
    -- 主要处理逻辑
    
    $IF $$DEBUG $THEN
        DBMS_OUTPUT.PUT_LINE('调试信息: 过程执行完成');
    $END
END debug_procedure;
/

-- 编译时设置条件
ALTER PROCEDURE debug_procedure COMPILE PLSQL_CCFLAGS = 'debug:true';

九、存储过程管理

1. 查看存储过程

sql 复制代码
-- 查看源代码
SELECT text FROM user_source 
WHERE name = 'UPDATE_EMPLOYEE_SALARY' 
AND type = 'PROCEDURE'
ORDER BY line;

-- 查看依赖关系
SELECT * FROM user_dependencies
WHERE name = 'UPDATE_EMPLOYEE_SALARY';

-- 查看参数信息
SELECT argument_name, data_type, in_out
FROM user_arguments
WHERE object_name = 'UPDATE_EMPLOYEE_SALARY';

右键查看

2. 重新编译

sql 复制代码
ALTER PROCEDURE procedure_name COMPILE;

右键重新编译

右键编辑--执行

3. 权限控制

sql 复制代码
-- 授予执行权限
GRANT EXECUTE ON procedure_name TO user_name;

-- 创建公有同义词
CREATE PUBLIC SYNONYM proc_synonym FOR schema.procedure_name;

4. 删除存储过程

sql 复制代码
DROP PROCEDURE procedure_name;

十、最佳实践

  1. 命名规范 :使用动词+名词形式,如calculate_tax, generate_report

  2. 参数设计:限制参数数量(通常不超过10个),使用默认参数

  3. 错误处理:捕获预期异常,记录错误日志

  4. 事务管理:保持事务简短,避免长时间锁定

  5. 性能优化:使用批量操作(FORALL, BULK COLLECT)

  6. 文档注释:为过程添加清晰注释

  7. 模块化:将复杂逻辑分解为多个小过程

  8. 避免硬编码:使用参数和常量代替字面值

十一、存储过程和函数的区别

  • 1.调用方式不一样。
  • 2.DML操作一般不用函数。
  • 3.函数有return返回值,存储过程没有。
  • 4.如果返回值超过一个,一般用存储过程。
  • 5.存储过程可以调用函数,函数不能调用存储过程。
  • 6.存储过程用来实现某些操作或者业务,函数用来实现某种功能。

|-----------------------------|-------------------------------------------------|
| 存储过程 | 函数 |
| 用于在数据库中完成特定的操作或者任务(如插入、删除等) | 用于特定的数据(如选择) |
| 程序头部声明用procedure | 程序头部声明用function |
| 程序头部声明不需描述返回类型 | 程序头部声明时要描述返回类型,而且PL/SQL块中至少要包括一个有效的return语句 |
| 可以使用in/out/in out三种模式的参数 | 可以使用in/out/in out三种模式的参数 |
| 可作为一个独立的PL/SQL语句来执行 | 不能独立执行,必须作为表达式的一部分调用 |
| 可以通过out/in out返回零个或多个值 | 通过return语句返回一个值,且改值要与声明部分一致,也可以是通过out类型的参数带出的变量 |
| SQL语句(DML或SELECT)中不可调用存储过程 | SQL语句(DML或SELECT)中可以调用函数 |

存储过程是Oracle数据库编程的核心组件,合理设计和使用的存储过程可以显著提高应用性能、安全性和可维护性。通过掌握上述技术,您可以构建高效、可靠的企业级数据库应用。

相关推荐
我有医保我先冲2 小时前
SQL复杂查询与性能优化:医药行业ERP系统实战指南
数据库·sql·性能优化
阳光_你好3 小时前
详细说明Qt 中共享内存方法: QSharedMemory 对象
开发语言·数据库·qt
喝醉酒的小白4 小时前
MySQL响应慢是否由堵塞或死锁引起?
数据库
Pasregret4 小时前
04-深入解析 Spring 事务管理原理及源码
java·数据库·后端·spring·oracle
jnrjian4 小时前
归档重做日志archived log (明显) 比redo log重做日志文件小
数据库·oracle
TDengine (老段)5 小时前
TDengine 中的命名与边界
大数据·数据库·物联网·oracle·时序数据库·tdengine·iotdb
谁家有个大人5 小时前
MYSQL中对行与列的操作
数据库·mysql
0000ysl6 小时前
数据库基础-函数&约束
数据库
JavaPub-rodert6 小时前
Etcd用的是Raft算法
数据库·github·etcd·raft
编程乐趣6 小时前
FlexLabs.Upsert:EF Core插件推荐,支持多数据库的Upsert功能
数据库