PLSQL一些常用的知识点

这篇具有很好参考价值的文章主要介绍了PLSQL一些常用的知识点。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、背景

此处简单的记录一下在 oracle中如何使用plsql语法,记录一些简单的例子,防止以后忘记。

2、变量的声明

declare
    -- 声明变量
    v_name varchar2(20);
    -- 此变量由 select into 赋值
    v_man_sex number;
    -- v_sex 变量的类型和 student表中的 sex 字段的类型一致
    v_sex student.sex%TYPE;
    -- v_row 中保存的是 student表中的一整行字段, 也可以是游标中的一整行
    v_row student%rowtype;
    -- 声明变量并赋值
    v_addr varchar2(100) := '湖北省';
    -- 声明日期变量
    v_date date := sysdate;
	
	-- 定义一个记录类型
    type STUDENT_INFO is record
     (
        student_id student.student_id%TYPE,
        student_name student.student_name%TYPE
     );
    -- 定义基于记录的嵌套表
    type nested_student_info is table of STUDENT_INFO;
    -- 声明变量
    student_list nested_student_info;

begin
    -- 直接赋值
    v_name := '直接赋值';
    v_date := to_date('2023-12-12', 'yyyy-mm-dd');
    -- 单个字段语句赋值
    select count(*) into v_man_sex from student where sex = 1;
    -- 多个字段赋值
    select student_name,sex into v_name,v_sex from student where student_id = 'S003';
    -- 获取一行数据 ( 此处需要查询出所有的字段,否则可能报错 )
    select student_id,student_name,sex,CREATE_TIME into v_row from student where student_id = 'S002';
    -- 打印输出
    DBMS_OUTPUT.PUT_LINE('日期:' || v_date || '姓名:' || v_name || ',' || v_row.STUDENT_NAME || ' 男生人数:' || v_man_sex || ' 地址:' || v_addr );
end;

3、if 判断

统计总共有多少个学生,并进行if判断。

declare
    -- 声明一个变量,记录有多少个学生
    v_student_count number;
begin
    -- 给 v_student_count 变量赋值
    select count(*) into v_student_count from student;

    -- 执行if判断

    if v_student_count > 3 then
        DBMS_OUTPUT.PUT_LINE('当前学生数为: [' || v_student_count || ']>3');
    elsif v_student_count >=2 then
        DBMS_OUTPUT.PUT_LINE('当前学生数为: [' || v_student_count || '] in [2,3]');
    else
        DBMS_OUTPUT.PUT_LINE('当前学生数为: [' || v_student_count || ']<2');
    end if;
end;

4、case

-- case
declare
    -- 声明一个变量,记录有多少个学生
    v_student_count number;
begin
    -- 给 v_student_count 变量赋值
    select count(*) into v_student_count from student;

    -- 执行if判断

    case when v_student_count > 3 then
        DBMS_OUTPUT.PUT_LINE('当前学生数为: [' || v_student_count || ']>3');
    when v_student_count >=2 then
        DBMS_OUTPUT.PUT_LINE('当前学生数为: [' || v_student_count || '] in [2,3]');
    else
        DBMS_OUTPUT.PUT_LINE('当前学生数为: [' || v_student_count || ']<2');
    end case;
end;

5、循环

输出1到100

1、loop 循环

declare
    -- 定义一个变量并赋值
    v_count number := 1;
begin
    loop
        -- 提出条件
        exit when v_count > 100;
        DBMS_OUTPUT.PUT_LINE('当前 count = ' || v_count);
        -- v_count 加1
        v_count := v_count + 1;
    end loop;
end;

2、while 循环

-- while 循环
declare
    -- 定义一个变量并赋值
    v_count number := 1;
begin
    while v_count <= 100 loop
        DBMS_OUTPUT.PUT_LINE('当前 count = ' || v_count);
        -- v_count 加1
        v_count := v_count + 1;
    end loop;
end;

3、for循环

-- for 循环
declare
    -- 定义一个变量
    v_count number;
begin
    for v_count in 1..100 loop
        DBMS_OUTPUT.PUT_LINE('当前 count = ' || v_count);
    end loop;
end;

6、游标

1、无参数的游标

-- 游标
declare
    -- 声明一个游标
    cursor cur_student is select student_id,student_name,sex from student;
    -- 声明变量
    row_cur_student cur_student%rowtype;
begin
    -- 打开游标
    open cur_student;

    -- 遍历数据
    loop
        -- 获取一行数据
        fetch cur_student into row_cur_student;
        -- 退出
        exit when cur_student%NOTFOUND;
        -- 执行业务逻辑(此句如果移动到exit when上方,则可能会多打印一句)
        DBMS_OUTPUT.PUT_LINE('studentId:' || row_cur_student.STUDENT_ID || ' studentName:' || row_cur_student.STUDENT_NAME);

    end loop;

    -- 关闭游标
    close cur_student;
end;

2、带参数的游标

declare
    -- 声明一个游标, 需要传递v_student_id参数
    cursor cur_student(v_student_id student.student_id%TYPE) is
        select student_id,student_name,sex from student where student_id = v_student_id;
    -- 声明变量
    row_cur_student cur_student%rowtype;
    -- 此变量通过查询获取值,然后带到游标中
    v_query_student_id student.student_id%TYPE;
begin
    -- 打开游标
    --参数传递方式一: open cur_student('S001');

    -- 参数传递方式二:
    select 'S001' into v_query_student_id from dual;
    open cur_student(v_query_student_id);

    -- 遍历数据
    loop
        -- 获取一行数据
        fetch cur_student into row_cur_student;
        -- 退出
        exit when cur_student%NOTFOUND;
        -- 执行业务逻辑(此句如果移动到exit when上方,则可能会多打印一句)
        DBMS_OUTPUT.PUT_LINE('studentId:' || row_cur_student.STUDENT_ID || ' studentName:' || row_cur_student.STUDENT_NAME);

    end loop;

    -- 关闭游标
    close cur_student;
end;

7、执行ddl dml

需要放到 execute immediate中执行,否则会报错。

declare
    v_table_name varchar2(20) := 'student_bak';
    -- 拼接一个动态SQL
    v_sql varchar2(100);
begin
    execute immediate 'create table student_bak as select * from student';
    execute immediate 'alter table student_bak add new_cloumn varchar2(20)';

    -- 带变量的执行
    v_sql := 'drop table ' || v_table_name;
    execute immediate v_sql;

end;

8、存储过程

1、无参数的存储过程

-- 无参数的存储过程
create or replace procedure sp_print_all_student
is
    -- 声明一个游标
    cursor c_all_student is select student_id,student_name from student;
    -- 声明一个变量
    row_student c_all_student%rowtype;
begin
    -- 循环游标
    for row_student in c_all_student loop
        DBMS_OUTPUT.PUT_LINE(row_student.STUDENT_ID || ' ' || row_student.STUDENT_NAME);
    end loop;
end;
-- 调用
begin
    SP_PRINT_ALL_STUDENT();
end;

2、有输入输出参数的存储过程

-- 有参数的存储过程
create or replace procedure sp_find_student(/** 输入参数 */ i_student_id in student.student_id%TYPE,
                                           /** 输出参数 */ o_student_name out student.student_name%TYPE)
IS
    -- 定义变量并赋值
    v_student_id varchar2(64) := i_student_id;
begin
    DBMS_OUTPUT.PUT_LINE('v_student_id:' || v_student_id);
    -- 将查询到的 student_name 赋值到 o_student_name
    select student_name into o_student_name from student where student_id = i_student_id;
end;

declare
    -- 定义一个变量用于接收存储过程的返回值
    output_student_name student.student_name%TYPE;
begin
    sp_find_student('S001', output_student_name);
    -- 输出存储过程的返回值
    DBMS_OUTPUT.PUT_LINE(output_student_name);
end;

3、merge into 的使用

存在更新,不存在插入。

create or replace procedure sp_merge_into(i_student_id in varchar2)
IS
begin
    -- 如果 using 中查询出来的数据,通过 on 条件匹配的话,则更新 student_bak表,否则插入student_bak表
    merge into STUDENT_BAK t
    using (select * from student where student_id = i_student_id) s
    on ( t.student_id = s.student_id )
    when matched then update set
                                 -- t.STUDENT_ID = s.STUDENT_ID, on中的条件不可更新
                                 t.STUDENT_NAME = s.STUDENT_NAME,
                                 t.SEX = s.SEX,
                                 t.CREATE_TIME = s.CREATE_TIME
    when not matched then insert(student_id, student_name, create_time) values (
                                         s.STUDENT_ID,
                                         s.STUDENT_NAME,
                                         s.CREATE_TIME
                                        );
    commit ;
end;

4、测试异常

create or replace procedure sp_error
IS
    v_num number;
begin
    DBMS_OUTPUT.PUT_LINE('测试异常');

    -- 产生异常
    v_num := 1 / 0;

    exception -- 存储过程异常
        when too_many_rows then
                dbms_output.put_line('返回值多于1行');
	    when others then
	   	   -- 异常处理方法,可以是打印错误,然后进行回滚等操作,下面操作一样,看自己情况决定
	   	   rollback;
	   	   dbms_output.put_line('错误码:' ||sqlcode);
	   	   dbms_output.put_line('异常信息:' || substr(sqlerrm, 1, 512));
end;

begin
    sp_error();
end;

5、bulk into & record

1、select into 中使用 bulk into & record

create or replace procedure sp_bulk_collect_01
IS
    -- 定义一个记录类型
    type STUDENT_INFO is record
     (
        student_id student.student_id%TYPE,
        student_name student.student_name%TYPE
     );

    -- 定义基于记录的嵌套表
    type nested_student_info is table of STUDENT_INFO;
    -- 声明变量
    student_list nested_student_info;
begin
    -- 使用 bulk collect into 将所获取的结果集一次性绑定到记录变量 student_list 中
    select student_id,student_name bulk collect into student_list from student;

	-- 遍历
    for i in student_list.first .. student_list.last loop
        DBMS_OUTPUT.PUT_LINE('studentId:' || student_list(i).student_id || ' studentName:' || student_list(i).student_name);
    end loop;
end;

begin
    sp_bulk_collect_01;
end;

2、fetch into 中使用 bulk into & forall


-- bulk collect
create or replace procedure sp_bulk_collect_02
IS
    -- 定义一个游标
    cursor cur_student is select student_id,student_name,sex,create_time from student;
    -- 定义基于游标的嵌套表
    type nested_student_info is table of cur_student%rowtype;
    -- 声明变量
    student_list nested_student_info;
begin
    -- 打开游标
    open cur_student;
        loop
            -- 一次获取2条数据插入到 student_list 中
            fetch cur_student bulk collect into student_list limit 2;
            -- 退出
            --exit when student_list%notfound; 不可使用这种方式
            exit when student_list.count = 0;

            -- 输出
            for i in student_list.first .. student_list.last loop
                DBMS_OUTPUT.PUT_LINE('studentId:' || student_list(i).student_id || ' studentName:' || student_list(i).student_name);
            end loop;

            -- 使用 forall 更新数据, 可以将多个dml语句批量发送给SQL引擎,提高执行效率。
            forall i in student_list.first .. student_list.last
                update student set student_name = student_list(i).STUDENT_NAME || '_update' where student_id = student_list(i).STUDENT_ID;
            commit ;
        end loop;

    -- 关闭游标
    close cur_student;
end;

begin
    sp_bulk_collect_02;
end;

6、接收数组参数

-- 创建StudentIdList数组的长度是4,每一项最多存20个字符
create or replace type StudentIdList as varray(4) of varchar2(20);

-- 创建存储过程,接收数组参数
create or replace procedure sp_param_list(studentIdList in StudentIdList)
is
begin
    for i in 1..studentIdList.COUNT loop
        DBMS_OUTPUT.PUT_LINE('studentId:' || studentIdList(i));
    end loop;
end;
declare
 begin
    sp_param_list(STUDENTIDLIST('d','c','S001','S0021222222222233'));
end;

7、接收数组对象,并将数组对象转换成表使用

-- 创建数据库对象
create or replace type StudentInfo is object(
    studentId varchar2(64),
    studentName varchar2(64)
);
-- 创建数组对象
create or replace type StudentInfoArr as table of StudentInfo;

-- 创建存储过程
create or replace procedure sp_param_list_02(arr in StudentInfoArr)
is
    -- 声明一个变量,记录传递进来的arr的数量
    v_student_count number := 0;
begin
    -- 传递进来的数组转换成使用
    select count(*) into v_student_count from table(cast(arr AS StudentInfoArr))
    where studentId like 'S%';
    DBMS_OUTPUT.PUT_LINE('传递进来学生学号以S开头的学生有: ' || v_student_count || '个');

    -- 输出列表参数
    for i in 1..arr.COUNT loop
        DBMS_OUTPUT.PUT_LINE('studentId:' || arr(i).studentId || ' studentName:' || arr(i).studentName);
    end loop;
end;

declare
begin
    sp_param_list_02(arr => StudentInfoArr(StudentInfo('S001','张三'),StudentInfo('S002','李四')));
end;

8、返回多个参数

create or replace procedure sp_return_value(stuInfoList out Sys_Refcursor)
IS
begin
    open stuInfoList for select STUDENT_ID,STUDENT_NAME,SEX from STUDENT;
end;

declare
    stu Sys_Refcursor;
    v_student_id STUDENT.STUDENT_ID%TYPE;
    v_student_name STUDENT.STUDENT_NAME%TYPE;
    v_sex STUDENT.SEX%TYPE;
begin
    SP_RETURN_VALUE(  stu);
    loop
        fetch stu into v_student_id,v_student_name,v_sex;
        exit when stu%notfound;
        DBMS_OUTPUT.PUT_LINE('studentId:' || v_student_id || ' studentName: ' || v_student_name);
    end loop;
 end;

9、程序包 package

1、定义包头

包头可以简单的理解java中的接口。

create or replace package pkg_huan as
    v_pkg_name varchar2(30) := 'pkg_huan';
    function add(param1 in number, param2 in number) return number;
    procedure sp_pkg_01;
    procedure sp_pkg_02(param1 in varchar2);
end pkg_huan;

2、实现包体

包体可以简单的理解java中的实现接口的类。

create or replace package body  pkg_huan as
    -- 实现function
    function add(param1 in number, param2 in number) return number IS
    begin
        return param1 + param2;
    end;
    -- 实现无参数的存储过程
    procedure sp_pkg_01 as
    begin
        DBMS_OUTPUT.PUT_LINE('package name:' || v_pkg_name || 'procedure name: sp_pkg_01');
    end;
    -- 实现有参数的存储过程
    procedure sp_pkg_02(param1 in varchar2) as
    begin
        DBMS_OUTPUT.PUT_LINE('param1:' || param1);
    end;
end;

3、调用包中的方法或存储过程

begin
    -- 调用方法
    DBMS_OUTPUT.PUT_LINE('1+2=' || PKG_HUAN.add(1,2));
    -- 调用无参数的存储过程
    PKG_HUAN.sp_pkg_01();
    -- 调用有参数的存储过程
    PKG_HUAN.sp_pkg_02(12);
end;

10、参考链接

1、http://www.cis.famu.edu/support/10g/Oracle_Database_10g/doc/appdev.102/b14261/objects.htm文章来源地址https://www.toymoban.com/news/detail-442254.html

到了这里,关于PLSQL一些常用的知识点的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • mysql innodb一些知识点

    1、事务和锁的关系; 在MySQL事务中,只要开始了一次事务,就会自动加上一个共享锁(Shared Lock)。这个锁会在事务结束时自动释放。如果在事务中需要更新某个数据对象,那么MySQL会将该数据对象的共享锁升级为排他锁(Exclusive Lock),这可以确保在其他事务中对该数据对象

    2024年02月14日
    浏览(28)
  • 关于BGP的一些知识点;(1)

    BGP路由属性中:     公认必遵属性有:Origin, AS_PATH,Next_hop      公认任意有:Local_Pref, Atomic_aggregate,        其中MED为可选非过渡不属于公认属性  Local-Preference是公认任意属性,且只能在一个AS内传播,默认值为100 BGP的Cluster_List 属性用来标识路由器反射组,是可选非过

    2024年02月07日
    浏览(39)
  • 一些关于c++的琐碎知识点

    目录 bool强转 const构成重载:const修饰*p  移动构造 new int (10)所做的四件事 this指针---为什么函数里面需要this指针? .和-的区别 new创建对象 仿函数 new和malloc的区别 c++系统自动给出的函数有 delete和delete[ ]区别何在 检查有没有析构函数 explict外部 内存泄漏的本质:丢失了内存地

    2024年02月07日
    浏览(38)
  • 关于set变更通知涉及的一些知识点

    在这个示例中,我们声明了一个私有字段  _name  作为存储名称的后端字段,并将其封装在公共属性  Name  中。在 setter 方法中,我们首先检查新值是否与旧值相同。如果不同,我们才更新存储字段,并调用  OnNameChanged()  方法来引发  NameChanged  事件。 注意, OnNameChanged  方

    2024年02月08日
    浏览(36)
  • 分享刷题的一些小知识点--4.9日

    1.string库提供了 、、==、=、=、!= 等比较运算符,比如两个字符串s和t,直接(s==t)是正确的。 2.unordered_map 容器,直译过来就是\\\"无序 map 容器\\\"的意思。所谓“无序”,指的是 unordered_map 容器不会像 map 容器那样对存储的数据进行排序。换句话说,unordered_map 容器和 map 容器仅有

    2023年04月11日
    浏览(34)
  • 使用es必须要知道的一些知识点:索引篇

    在当今数据驱动的世界中,Elasticsearch(简称ES)成为了一个强大而广泛应用的搜索和分析引擎。ES提供了快速、可扩展且高度可靠的数据存储和检索解决方案。然而,要真正掌握ES的各种功能和最佳实践,需要通过实践才能获得真正的知识。 在Elasticsearch(ES)中,index操作和

    2024年02月08日
    浏览(29)
  • 网络层中一些零碎且易忘的知识点

    异构网络:指传输介质、数据编码方式、链路控制协议以及数据单元格式和转发机制不同,异构即物理层和数据链路层均不同 虚电路:网络层可以向传输层提供两种类型的服务,面向连接的服务称为虚电路服务,而无连接的服务称为数据报服务。虚电路的想法是避免为发送的

    2024年02月15日
    浏览(29)
  • 数据结构中一些零碎且易忘的知识点

    第一章 绪论 数据结构包含三个方面的内容: 数据的逻辑结构:描述数据之间逻辑关系的、与数据的存储无关的数学模型。相同的逻辑结构可使用不同的存储结构存储,如线性表既可顺序存储,也可链式存储 线性结构:一个线性表是n个具有相同特性的数据元素的有限序列 一

    2024年02月14日
    浏览(30)
  • 传输层中一些零碎且易忘的知识点

    端口号:共两个字节 不同类型的端口号: 服务端端口号 熟知端口号:0~1023 登记端口号:1024~49151 客户端使用端口号(短暂/临时端口号):49152~65535 要记得常见应用程序的熟知端口号 FTP:21 TELNET:23 SMTP:25 DNS:53 TFTP:69 HTTP:80 SNMP:161 首部与伪首部: 伪首部中协议字

    2024年02月15日
    浏览(26)
  • 网络编程中关于UDP套接字的一些知识点

    关于UDP的介绍: UDP(User Datagram Protocol,用户数据报协议)是一种面向无连接的、不可靠的传输协议,它在网络编程中也起着重要的作用。 1. 低延迟:相比于TCP,UDP没有建立连接和拥塞控制的开销,因此传输延迟较低。这使得UDP适用于实时通信应用,如音视频传输和在线游戏

    2024年02月06日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包