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. SpringBoot笔记--文件配置加载顺序+整合其他框架

    内部文件配置加载顺序 外部文件配置加载顺序 jar包配置 整合Junit 若是业务管理类和测试类在同一个包下面,那么这句话, 可以不加括号,只写注解名称 否则,就必须指定到包下面,不然会报错 整合Re ...

  2. 布局管理器wx.BoxSizer

    b = wx.BoxSizer( wx.VERTICAL ) b.Add(self.notebook1, 1, wx.EXPAND) self.parent.SetSizer(b) 解析以上代码原理, ...

  3. Python3.10 的开发环境的搭建

    安装 下载 Python3.10 或者其他版本:Download Python | Python.org 如果 Windows 操作系统下载,默认是下载 64 位操作系统的 exe 安装包:pytho ...

  4. ChannelInboundHandlerAdapter 与 SimpleChannelInboundHandler 功能详解

    SimpleChannelInboundHandler [类的关系]:如下就是两个类的声明,SimpleChannelInboundHandler是继承 ChannelInboundHandlerAd ...

  5. 股票数据Scrapy爬虫实例(亲测有效)

    步骤: 步骤1:建立工程和Spider模板 scrapy startproject BaiduStocks cd BaiduStocks scrapy genspider stocks baidu.c ...

  6. 8.XSS和CSRF漏洞

    XSS和CSRF漏洞 目录 XSS和CSRF漏洞 XSS漏洞介绍 XSS分类 利用XSS漏洞如何实行攻击 利用XSS盗取用户的Cookie 利用XSS实行钓鱼 利用XSS进行键盘监控 CSRF漏洞介绍 ...

  7. active

    rabbitMQ与activeMQ区别 之前的项目中都用到了这两个消息队列 ActiveMq,传统的消息队列,使用Java语言编写.基于JMS(Java Message Service),采用多线程并 ...

  8. 基于列存储的开源分布式NoSQL数据库Apache Cassandra入门分享

    @ 目录 概述 定义 特性 与Hbase对比 Cassandra使用场景 术语 架构 概览 Dynamo 数据集分区使用令牌环的一致性哈希 存储引擎 部署 单实例部署 集群部署 CQL 概述 数据模型 ...

  9. Java中使用List的add方法后元素相同问题

    在写JavaWeb时,我在后端通过JDBC读取了数据后逐个使用List.add()方法添加元素并通过request方法传给jsp页面解析,但是添加以后出现了在列表里有n个(假设添加了n个元素)最后一个 ...

  10. 图与网络分析—R实现(三)

    最小生成树 (Minimum Spanning Tree) 应该大家都不陌生,Spanning 有跨越的意思,生成树一般来说每个节点都能访问到别的节点,是一个连通树.所以,一般考虑无向图里去造生成树. ...