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

PLSQL一些常用的知识点的更多相关文章

  1. JS中常用开发知识点

     JS中常用开发知识点 1.获取指定范围内的随机数 2.随机获取数组中的元素 3.生成从0到指定值的数字数组 等同于: 4.打乱数字数组的顺序 5.对象转换为数组 //注意对象必须是以下格式的才可以通 ...

  2. PLSQL Developer常用设置及快捷键

    CSDN日报20170314--<40岁程序员真的要被淘汰了么?> 程序员2月书讯 [直播]用面向协议的思想简化网络请求 博客一键搬家活动开始啦 PLSQL Developer常用设置及快 ...

  3. PLSQL Developer 常用设置及快捷键

    1.登录后自动选中My Objects(已验证可用) 默认情况下,PLSQL Developer登录后,Brower里会选择all Objects,如果你登录的用户是DBA, 要展开tables目录, ...

  4. php 常用的知识点归集(下)

    24.静态属性与静态方法在类中的使用 需求:在玩CS的时候不停有伙伴加入,那么现在想知道共有多少人在玩,这个时候就可能用静态变量的方法来处理 利用原有的全局变量的方法来解决以上的问题 <?php ...

  5. Groovy常用编程知识点简明教程

    概述 Groovy 是一门基于JVM的动态类型语言,可以与 Java 平台几乎无缝融合(与Java代码一样编译成字节码). 使用 Groovy ,可以增强 Java 应用的灵活性和可扩展性,提升开发效 ...

  6. unity常用小知识点

    感觉自己抑郁变得更严重了,超级敏感,经常想崩溃大哭,睡眠超差,实在不想药物治疗,多看看书,多约约朋友,多出去走走. 来几句鸡汤吧,人一定要活得明白一点,任何关系都不要不清不楚,说不定最后受伤的就是自个 ...

  7. 常用ES6-ES10知识点总结

    在工作中我们会常用到的一些es6-es10的一些特性还记得多少,今天就让我们重新复习一遍 ES6语法 1.Let 1.let声明的变量具有块级作用域, { let a = 1 } console.lo ...

  8. iOS中多线程常用的知识点

        1.pThread 跨平台的多线程技术 , 是IEEE制定的POSIX 表示可移植性操作系统接口的多线程计数,UNIX内核平台 Unix,Linux,Mac(小红帽) (windows上有可移 ...

  9. rails 常用的知识点

    按惯例先上网址:  http://guides.ruby-china.org/    适合初学者很好的文章 ===========================知识点================ ...

  10. java常用基础知识点 (持续追加)

    作为一个Java编程人,会经常用上JDK中的大量的API类库,常用的有字符串操作.集合操作.文本操作.输入输出操作.以及网络操作, 常用的包: 1. java.lang Java程序的基础类,字符串, ...

随机推荐

  1. SQL中获取多条记录拼接成字符串

    declare @aa nvarchar(200) set @aa=(select STUFF((select ','+LTRIM(list.TempName1) from (select TempN ...

  2. fatal: unable to access 'https://github.com/github-eliviate/papers.git/': Failed to connect to github.com port 443 after 21107 ms: Timed out

    fatal: unable to access 'https://github.com/github-eliviate/papers.git/': Failed to connect to githu ...

  3. Linux高并发服务器之Linux多线程开发

    本文源自C++高薪面试项目的学习笔记,主要记录Liunx多线程的学习,主要知识点是线程概述等基础概念以外,还有线程相关Liunx系统函数以及对应练手代码,除此之外还有线程同步问题的讲解以及实战多线程买 ...

  4. 页面录制服务上线:RESTful API 调用实现,所见所录即所得

    我们为很多实时互动场景提供了服务.在一些场景中,用户不仅需要实时互动,还需要把互动的过程录下来.那么一个好的录制解决方案究竟需要具备哪些特征呢? 在回答这个问题之前,先聊一下客户使用录制的原因.一般来 ...

  5. SpringBoot——模板引擎及原理

    更多内容,前往IT-BLOG 一.模板引擎的思想 模板是为了将显示与数据分离,模板技术多种多样,但其本质都是将模板文件和数据通过模板引擎生成最终的 HTML代码. 二.SpringBoot模板引擎 S ...

  6. 记一次 .NET 某传感器采集系统 线程爆高分析

    一:背景 1. 讲故事 前段时间有位朋友微信找到我,说他的程序使用 hsl 库之后,采集 plc 时内存溢出,让我帮忙看一下怎么回事,哈哈,貌似是分析之旅中的第二次和 hsl 打交道,既然找到我,那就 ...

  7. 关于 IDP 的五大认知误解

    内部开发者平台(IDP)是近年来在希望加快软件交付和改善开发者体验的企业中得到普及的一个概念.然而,大众对于什么是 IDP 以及它能为开发者和企业带来什么也有很多困惑和误解.在这篇文章中,我们将尝试解 ...

  8. 【Spring专题】「技术原理」从源码角度去深入分析关于Spring的异常处理ExceptionHandler的实现原理

    ExceptionHandler的作用 ExceptionHandler是Spring框架提供的一个注解,用于处理应用程序中的异常.当应用程序中发生异常时,ExceptionHandler将优先地拦截 ...

  9. 【Note】贪心

    感谢 $ \text{orzws/chy} $ 倾情授课. 目录 -1. 证明方式 0. 朴素贪心 AT2557 [ARC073C] Ball Coloring P2587 [ZJOI2008]泡泡堂 ...

  10. 关键字——static

    static 关键字具有共享属性,放在方法区中