PL/SQL概述

[复制链接]
发表于 2025-10-22 04:25:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一. 什么是PL/SQL?

PL/SQL(Procedure  Language/SQL)是 Oracle对 sql 语言的过程化扩展,指在 SQL 下令语言中增长了过程处置处罚语句(如分支、循环等),使 SQL 语言具有过程处置处罚本领。把SQL语言的数据利用本领与过程语言的数据处置处罚本领团结起来,使得 PLSQL 面向过程但比过程语言简单、高效、机动和实用。
根本语法布局:
  1. [declare] -- 声明变量
  2. begin
  3. [exception] -- 异常处理
  4. end;
复制代码
案例:
  1. declare
  2.     age number default 10; -- 定义一个age变量,默认值为10;
  3. begin
  4.     age := 11; -- 将age变量的值变为11;
  5.     DBMS_OUTPUT.put_line('年龄:' || age); -- 打印括号里的值
  6. end;
复制代码
二. 变量

一个变量只不外是在步调中可以利用的存储地域的名称。 PL/SQL中的每个变量都有一个指定的数据范例,它决定了变量内存的巨细和布局.
PL/SQL变量的名称由可选的字母,数字,美元($)符号,下划线和数字符号构成,不能凌驾30个字符。 默认情况下,变量名不区分巨细写。不能将生存的PL/SQL关键字用作变量名称。
根本语法格式:
  1. -- 声明变量
  2. 变量名 类型(长度);
  3. -- 变量赋值
  4. 变量名 := 变量值;
  5. -- select into 变量赋值
  6. select 列名 into 变量名 from 表名 where 条件;
  7. select  列名1,列名2 into 变量1,变量2 from 表名 where 条件 -- 列名要和变量名一一对应
复制代码
案例:
  1. declare
  2.     v_num0     T_ACCOUNT.NUM0%type;-- 定义变量
  3.     v_num1     T_ACCOUNT.NUM1%type;
  4.     v_usenum   T_ACCOUNT.USENUM%type;
  5.     v_usernum2 number(10, 2);
  6.     v_money    number(10, 2);
  7. begin
  8.     select USENUM, NUM0, NUM1
  9.     INTO v_usenum, -- 对变量进行赋值
  10.         v_num0,
  11.         v_num1
  12.     from T_ACCOUNT
  13.     where YEAR = '2012'
  14.       and MONTH = '12'
  15.       and OWNERUUID = 1;
  16.     v_usernum2 := round(v_usenum / 1000, 2);
  17.     V_MONEY := ROUND(v_usernum2 * 2.45, 2);
  18.     DBMS_OUTPUT.PUT_LINE('单价:' || 2.45 || ',吨数:' || v_usernum2 || ',应付金额' || v_money);
  19. end;
复制代码
三. 记载型变量

3.1 列变量

记载表中的一列存放在变量中
根本语法格式:
  1. -- 定义列变量
  2. 列变量名 表名.列名%type;
复制代码
案例:
  1. declare
  2.     v_num0     T_ACCOUNT.NUM0%type; -- 定义列变量
  3.     v_num1     T_ACCOUNT.NUM1%type;
  4.     v_usenum   T_ACCOUNT.USENUM%type;
  5.     v_usernum2 number(10, 2);
  6.     v_money    number(10, 2);
  7. begin
  8.     select USENUM, NUM0, NUM1
  9.     INTO v_usenum,
  10.         v_num0, -- 将值赋值给列变量
  11.         v_num1
  12.     from T_ACCOUNT
  13.     where YEAR = '2012'
  14.       and MONTH = '12'
  15.       and OWNERUUID = 1;
  16.     v_usernum2 := round(v_usenum / 1000, 2);
  17.     V_MONEY := ROUND(v_usernum2 * 2.45, 2);
  18.     DBMS_OUTPUT.PUT_LINE('单价:' || 2.45 || ',吨数:' || v_usernum2 || ',应付金额' || v_money);
  19. end;
复制代码
3.2 行变量

记载表中的一行存放在变量中
根本语法格式:
  1. -- 定义行变量
  2. 行变量名 表名%rowtype;
  3. -- 引用行变量
  4. 行变量名.列名;
复制代码
案例:
  1. declare
  2.     v_account  T_ACCOUNT%rowtype; -- 定义行变量
  3.     v_usernum2 number(10, 2);
  4.     v_money    number(10, 2);
  5. begin
  6.     select *
  7.     into v_account -- 赋值给行变量一行的值
  8.     from T_ACCOUNT
  9.     where YEAR = '2012'
  10.       and MONTH = '12'
  11.       and OWNERUUID = 1;
  12.     v_usernum2 := round(v_account.USENUM / 1000, 2); -- 引用行变量的值
  13.     V_MONEY := ROUND(v_usernum2 * 2.45, 2);
  14.     DBMS_OUTPUT.PUT_LINE('单价:' || 2.45 || ',吨数:' || v_usernum2 || ',应付金额' || v_money);
  15. end;
复制代码
四. 非常

非常是指PL/SQL步调在实行时出现的错误,在PL/SQL中的一个告诫或错误的情况都被称为非常。提示:编译错误(重要指语法错误)不包罗在内。
非常处置处罚通常写在实行体的最下面,在全部实行语句之后以exception关键字开始非常处置处罚
在运行步调时出现的错误叫做非常
发生非常后,语句将制止实行,控制权转移到  PL/SQL 块的非常处置处罚部分
非常有两种范例:

  • 预界说非常     -   当  PL/SQL  步调违背  Oracle  规则或逾越体系限定时隐式引发
  • 用户界说非常   -    用户可以在  PL/SQL  块的声明部分界说非常,自界说的非常通过  RAISE 语句显式引发
4.1 预界说非常

Oracle预界说非常21个
定名的体系非常产生缘故原由ACCESS_INTO_NULL未界说对象CASE_NOT_FOUNDCASE  中若未包罗相应的  WHEN  ,而且没有设置  ELSE  时COLLECTION_IS_NULL聚集元素未初始化CURSER_ALREADY_OPEN游标已经打开DUP_VAL_ON_INDEX唯一索引对应的列上有重复的值INVALID_CURSOR在不合法的游标上举行利用INVALID_NUMBER内嵌的  SQL  语句不能将字符转换为数字NO_DATA_FOUND利用  select into  未返回行TOO_MANY_ROWS实行  select into  时,结果集凌驾一行ZERO_DIVIDE除数为  0SUBSCRIPT_BEYOND_COUNT元素下标凌驾嵌套表或  VARRAY  的最大值SUBSCRIPT_OUTSIDE_LIMIT利用嵌套表或  VARRAY  时,将下标指定为负数VALUE_ERROR赋值时,变量长度不敷以容纳实际数据LOGIN_DENIEDPL/SQL  应用步调毗连到  oracle  数据库时,提供了不准确的用户名或暗码NOT_LOGGED_ONPL/SQL  应用步调在没有毗连  oralce  数据库的情况下访问数据PROGRAM_ERRORPL/SQL  内部题目,大概须要重装数据字典&  pl./SQL  体系包ROWTYPE_MISMATCH宿主游标变量与  PL/SQL  游标变量的返回范例不兼容SELF_IS_NULL利用对象范例时,在  null  对象上调用对象方法STORAGE_ERROR运行  PL/SQL  时,超出内存空间SYS_INVALID_ID无效的  ROWID  字符串TIMEOUT_ON_RESOURCEOracle  在等待资源时超时根本语法布局:
  1. exception
  2. when 异常类型   then
  3. 异常处理逻辑
复制代码
案例:
  1. declare
  2.     v_account  T_ACCOUNT%rowtype;
  3.     v_usernum2 number(10, 2);
  4.     v_money    number(10, 2);
  5. begin
  6.     select *
  7.     into v_account
  8.     from T_ACCOUNT
  9.     where YEAR = '2012'
  10.       and MONTH = '12'
  11.       and OWNERUUID = 10000;
  12.     v_usernum2 := round(v_account.USENUM / 1000, 2);
  13.     V_MONEY := ROUND(v_usernum2 * 2.45, 2);
  14.     DBMS_OUTPUT.PUT_LINE('单价:' || 2.45 || ',吨数:' || v_usernum2 || ',应付金额' || v_money);
  15. exception
  16.     when NO_DATA_FOUND THEN -- 当捕获到NO_DATA_FOUND类型的错误时,打印下方语句
  17.         DBMS_OUTPUT.PUT_LINE('未找到任何数据');
  18. end;
复制代码
4.2 用户自界说非常

根本语法布局:
  1. declare
  2.     自定义异常名 EXCEPTION;
  3.     PRAGMA EXCEPTION_INIT (自定义异常名,错误码(-01403));
  4. begin
  5. ...
  6. exception
  7.     when 自定义异常名 THEN
  8.        subquery;
  9. end;
复制代码
案例:
  1. declare
  2.     NO_DATA EXCEPTION; -- 定义自定义异常NO_DATA,错误码为-01403
  3.     PRAGMA EXCEPTION_INIT (NO_DATA,-01403);
  4.     v_account  T_ACCOUNT%rowtype;
  5.     v_usernum2 number(10, 2);
  6.     v_money    number(10, 2);
  7. begin
  8.     select *
  9.     into v_account
  10.     from T_ACCOUNT
  11.     where YEAR = '2012'
  12.       and MONTH = '12'
  13.       and OWNERUUID = 10000;
  14.     v_usernum2 := round(v_account.USENUM / 1000, 2);
  15.     V_MONEY := ROUND(v_usernum2 * 2.45, 2);
  16.     DBMS_OUTPUT.PUT_LINE('单价:' || 2.45 || ',吨数:' || v_usernum2 || ',应付金额' || v_money);
  17. exception
  18.     when NO_DATA THEN -- 捕获自定义异常,捕获成功则打印下方语句
  19.         DBMS_OUTPUT.PUT_LINE('未找到任何数据');
  20. end;
复制代码
五.条件判定(if)

5.1 单分支条件判定

根本语法:
  1. if 条件 then
  2.   业务逻辑
  3. end if;
复制代码
案例:
  1. declare
  2.     age number default 18;
  3. begin
  4.     if age >= 18 then -- 判断条件
  5.         DBMS_OUTPUT.put_line('成年'); -- 判断成功则打印语句
  6.     end if;
  7. end;
复制代码
5.2 双分支条件判定
  1. if 条件 then
  2.   业务逻辑
  3. else
  4.   业务逻辑
  5. end if;
复制代码
案例:
  1. declare
  2.     age number default 16;
  3. begin
  4.     if age >= 18 then -- 判断条件
  5.         DBMS_OUTPUT.put_line('成年'); -- 如果满足条件则打印
  6.     else
  7.         DBMS_OUTPUT.put_line('未成年');-- 不满足条件则打印
  8.     end if;
  9. end;
复制代码
5.3 多分支条件判定
  1. if 条件1 then
  2.   业务逻辑
  3. elsif 条件2 then
  4.   业务逻辑
  5. else
  6.   业务逻辑
  7. end if;
复制代码
案例:
  1. declare
  2.     month number default 6;
  3. begin
  4.     if month in (1, 2, 3) then -- 判断条件
  5.         DBMS_OUTPUT.put_line('第一季度');-- 满足条件1则打印
  6.     elsif month in (4, 5, 6) then
  7.         DBMS_OUTPUT.put_line('第二季度');-- 满足条件2则打印
  8.     elsif month in (7, 8, 9) then
  9.         DBMS_OUTPUT.put_line('第三季度');-- 满足条件3则打印
  10.     elsif month in (10, 11, 12) then
  11.         DBMS_OUTPUT.put_line('第四季度');-- 满足条件4则打印
  12.     else
  13.         DBMS_OUTPUT.put_line('错误'); -- 以上条件都不满足则打印
  14.     end if;
  15. end;
复制代码
六. 循环

在Oracle数据库中,循环是一种根本的控制布局,用于重复实行一段代码直到满意特定条件。Oracle提供了几种差别范例的循环语句,以顺应差别的编程需求。
6.1 无条件循环loop

Loop循环是Oracle中最根本的循环布局,它会无穷循环直到碰到EXIT语句。在下面的例子中,Loop循环用于实现与Exit When循环类似的功能
根本语法:
  1. loop
  2. --循环语句
  3. end loop;
复制代码
案例:
  1. declare
  2.     i number default 1; -- 定义一个计数器i
  3. begin
  4.     loop
  5.         DBMS_OUTPUT.put_line('loop循环了:' || i || '次');-- 每循环一次则打印
  6.         exit when i >= 10;-- 判断条件 当i大于等于10时循环结束
  7.         i := i + 1; -- 每循环一次计数器就加一
  8.     end loop;
  9. end;
复制代码
6.2 条件循环while

While循环在每次迭代开始前查抄条件,假如条件为真,则实行循环体。
根本语法:
  1. while 条件 -- 条件为真则执行循环
  2. loop
  3.   ...
  4. end loop;
复制代码
案例:
  1. declare
  2.     i number default 1; -- 定义一个计数器
  3. begin
  4.     while i <= 10-- 判断条件,条件为真则执行循环
  5.         loop
  6.             DBMS_OUTPUT.put_line('whileloop循环了:' || i || '次');-- 满足条件则打印
  7.             i := i + 1; -- 每循环一次计数器就加一
  8.         end loop;
  9. end;
复制代码
6.3 for循环

For循环是一种预界说迭代次数的循环,它会主动递增计数器并在到达指定次数后制止。
根本语法:
  1. for 变量  in 起始值..终止值
  2. loop
  3.         ...
  4. end loop;
复制代码
案例:
  1. declare
  2.     i number default 1; -- 定义一个计数器
  3. begin
  4.     for i in 1..10 -- 如果i迭代的次数满足序列里的值,则执行循环
  5.         loop
  6.             DBMS_OUTPUT.put_line('for循环了:' || i || '次');-- 满足条件则打印
  7.         end loop;
  8. end;
复制代码
七. 游标

游标是体系为用户开设的一个数据缓冲区,存放 SQL 语句的实行结果。
我们可以把游标明白为 PL/SQL 中的结果集。
这么说实在是不严谨的,准确来说游标(Cursor)是一种用于查询结果集的指针,它答应你逐行处置处罚查询结果。
语法格式:
  1. -- 定义游标
  2. cursor  游标名称  is  SQL语句;
  3. open 游标名称 -- 打开游标
  4. loop
  5. fetch 游标名称  into 变量 -- 对游标内的值进行抓取
  6. exit   when   游标名称%notfound -- 当游标内的值被抓取完则退出循环
  7. end loop;
  8. close 游标名称 -- 关闭游标
复制代码
案例:
  1. declare
  2.     cursor c_area is select * -- 定义游标,游标里的内容为sql语句的结果集
  3.                      from T_AREA;
  4.     v_area T_AREA%rowtype;
  5. begin
  6.     open c_area;-- 打开游标
  7.     loop
  8.         fetch c_area into v_area; -- 抓取游标里的内容
  9.         exit when c_area%notfound; -- 当游标内没有值可以被抓取时,退出循环
  10.         DBMS_OUTPUT.put_line('编号为:' || v_area.ID || '地址为:' || v_area.NAME);
  11.     end loop;
  12. end;
复制代码
7.1 游标参数

语法格式:
  1. -- 创建带有参数的游标
  2. cursor 游标名称(参数名  参数类型)  is  subquery;
  3. -- 使用带参数的游标
  4. open 游标名称(value);
复制代码
案例:
  1. declare
  2. -- 定义游标,将T_AREA表里name列里包含v_name的内容作为游标的结果集
  3.     cursor c_area(v_name varchar2) is select *
  4.                                       from T_AREA
  5.                                       where name like '%' || v_name || '%';
  6.     v_area T_AREA%rowtype; -- 定义一个行变量
  7. begin
  8.     open c_area('城');-- 对v_name进行赋值
  9.     loop
  10.         fetch c_area into v_area;-- 将游标里的内容赋值给行变量
  11.         exit when c_area%notfound;-- 当游标内没有值可以被抓取时,退出循环
  12.         DBMS_OUTPUT.put_line('编号为:' || v_area.ID || '地址为:' || v_area.NAME);
  13.         -- 打印行变量里的内容
  14.     end loop;
  15. end;
复制代码
7.2 for 循环提取游标值

我们每次提取游标,须要打开游标   关闭游标  循环游标  提取游标   控制循环的 退出等等,好贫困,可以用 for 循环齐备都变的简单 ,
上例的代码可以改造为下列情势:
  1. declare
  2.     -- todo 1 声明带参数游标 cur_pricetable 根据参数值获取指定类型的价格表
  3.     cursor 游标名(参数名 参数类型) is
  4.        subquery;
  5. begin
  6.     -- todo 2 使用 for 循环遍历
  7.     for v_pricetable in cur_pricetable(1) loop
  8.         ...
  9.     end loop;
  10. end;
复制代码
案例:
  1. declare
  2. -- 定义游标c_area和参数type_id,类型为number
  3.     cursor c_area(type_id number) is select *
  4.                                      from T_PRICETABLE
  5.                                      where OWNERTYPEID = type_id;
  6.                                      -- T_PRICETABLE表中OWNERTYPEID = type_id的结果集作为游标的内容
  7. begin
  8.     for v_row in c_area(1)-- 对游标的参数赋值
  9.         loop -- 进行循环
  10.             DBMS_OUTPUT.put_line('价格:' || v_row.PRICE || ',吨位:' || v_row.MINNUM || '-' || v_row.MAXNUM);
  11.         end loop;
  12. end;
复制代码
八.总结

8.1 PLSQL简介

PL/SQL编程语言是Oracle公司在1980年代后期开发的,它是SQL和Oracle关系数据库的过程扩展语言。以下是关于PL/SQL的某些值得留意的毕竟-

  • PL/SQL是一种完全可移植的高性能事件处置处罚语言。
  • PL/SQL提供了内置的,表明的且与OS无关的编程情况。
  • 也可以从下令行SQL * Plus接口直接调用PL/SQL 。
  • 也可以从外部编程语言调用直接调用数据库。
  • PL/SQL的通用语法基于ADA和Pascal编程语言。
  • 除了Oracle,PL/SQL还可以在TimesTen内存数据库和IBM DB2中利用。
8.2 PL/SQL的功能

PL/SQL具有以下功能:

  • PL/SQL与SQL精麋集成。
  • 它提供了广泛的错误查抄。
  • 它提供了许多数据范例。
  • 它提供了多种编程布局。
  • 它通过功能和过程支持布局化编程。
  • 它支持面向对象的编程。
  • 它支持Web应用步调和服务器页面的开发。
8.3 PL/SQL的优点

PL/SQL具有以下优点:

  • SQL是标准的数据库语言,而PL/SQL与SQL精麋集成在一起。PL/SQL支持静态和动态SQL。静态SQL支持来自PL/SQL块的DML利用和事件控制。在Dynamic SQL中,SQL答应将DDL语句嵌入PL/SQL块中。
  • PL/SQL答应一次将整个语句块发送到数据库。如允许以镌汰网络流量,并为应用步调提供高性能
  • PL/SQL可以查询,转换和更新数据库中的数据,因此可以进步步调员的生产率。
  • PL/SQL通过强大的功能(比方非常处置处罚,封装,数据隐蔽和面向对象的数据范例)节流了操持和调试时间。
    用PL/SQL编写的应用步调是完全可移植的。
  • PL/SQL提供高安全性级别。
  • PL/SQL提供对预界说SQL包的访问。
  • PL/SQL提供了对面向对象编程的支持。
  • PL/SQL为开发Web应用步调和服务器页面提供支持。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表