PL/SQL练习
简单结构
set serveroutput on; DECLARE
v_name varchar2(20);
BEGIN
v_name := 'hello';
dbms_output.put_line(v_name);
END; /
异常处理:
declare
v_num number :=0;
begin
v_num := 2/v_num;
dbms_output.put_line('devide function...');
exception
when others then
dbms_output.put_line('error....devide by'||v_num);
end; /
引用类型
declare
v_empno number(4);
--v_ename变量使用emp表ename字段的类型
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
v_sal := 1000.123;
dbms_output.put_line(v_sal);
exception
when others then
dbms_output.put_line('error....');
end;
复合类型:
数组:table
declare
--声明一个table类型(看做数组),数组的值是emp表empno字段的类型,数组下标是binary——integer类型
type type_a is table of emp.empno%type index by binary_integer;
--声明一个type——a类型的数组
v_table_empno type_a;
begin --下标可以为负数 v_table_empno(-1) := 1000;
v_table_empno(0) := 0000;
v_table_empno(1) := 1000;
v_table_empno(2) := 2000;
dbms_output.put_line('打印数组第二个值:'||v_table_empno(2));
exception
when others then
dbms_output.put_line('error....');
end;
对象:record
declare
--声明一个对象record,各个成员变量引用dept表的类型
type type_record_dept is record(
deptno dept.deptno%type,
dname dept.dname%type,
loc dept.loc%type
);
--声明上述类对应的一个对象
v_temp type_record_dept;
begin
--给对象赋值:
v_temp.deptno := 50;
v_temp.dname := 'dname---';
v_temp.loc := 'beijing';
dbms_output.put_line('打印v_temp对象:'||v_temp.deptno||', '||v_temp.dname||', '||v_temp.loc );
exception
when others then
dbms_output.put_line('error....');
end;
使用rowtype声明一个record对象:
declare
--声明一个对象record,她的所有字段同emp所有字段
v_emp emp%rowtype;
begin
--给对象赋值:
v_emp.empno := 1111;
v_emp.ename := 'sansan';
dbms_output.put_line('打印v_temp对象:'||v_emp.empno||', '||v_emp.ename);
exception
when others then
dbms_output.put_line('error....');
end;
select into
declare
--声明
v_ename emp.ename%type;
v_deptno emp.deptno%type;
begin
--给对象赋值,不用游标时这个select语句只能返回一条,而且必须返回一条数据
select ename,deptno into v_ename,v_deptno from emp where empno = 7369;
dbms_output.put_line('打印v_temp对象:'||v_ename||', '||v_deptno);
end;
执行DDL语句:execute immediate
begin --引号中,两个单引号代替一个单引号
execute immediate 'create table ttt(id varchar2(20),name varchar2(10) default ''sansan'')';
end;
分支判定:薪水小于1000加倍,大于则减半
declare
--声明
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
--给对象赋值,不用游标时这个select语句只能返回一条,而且必须返回一条数据
select ename,sal into v_ename,v_sal from emp where empno = 1111;
if(v_sal < 1000) then
update emp set sal = sal*2 where empno=1111;
dbms_output.put_line('小于1000,加倍。。');
elsif(v_sal = 1000 )then
dbms_output.put_line('等于1000。。');
else
update emp set sal = sal/2 where empno=1111;
dbms_output.put_line('大于1000,减半。。');
end if;
commit;
end;
循环
--dowhile
declare
--声明
i binary_integer := 1;
begin
loop
dbms_output.put_line('第i='||i);
i := i+1;
exit when(i>=5);
end loop;
end;
--while
declare
--声明
i binary_integer := 1;
begin
while (i < 5) loop
dbms_output.put_line('第i='||i);
i := i+1;
end loop;
end;
--for 循环
declare
--声明
i binary_integer := 1;
begin
--顺序循环
for k in 1..5 loop
dbms_output.put_line('第k='||k);
end loop; --逆序循环
for k in reverse 1..5 loop
dbms_output.put_line('第k='||k);
end loop;
end;
异常处理:
declare
--声明
v_ename emp.ename%type;
v_deptno emp.deptno%type;
begin
--给对象赋值,不用游标时这个select语句只能返回一条,而且必须返回一条数据
select ename,deptno into v_ename,v_deptno from emp where deptno=10;
dbms_output.put_line('打印v_temp对象:'||v_ename||', '||v_deptno);
exception
--可以把这些异常记录在一张异常表中
when too_many_rows then
dbms_output.put_line('异常:记录数大于一条。。。'||SQLCODE||SQLERRM);
when no_data_found then
dbms_output.put_line('异常:没有记录。。。'||SQLCODE||SQLERRM);
when others then
dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
end;
游标
declare
--声明一个游标,不会真正取数据
cursor c is
select * from emp;
--声明一个record
v_each c%rowtype;
begin
--打开游标,执行语句。游标指向第一条记录
open c;
--把游标指向的数据拿到v_each中,游标自动向下移动一个
fetch c into v_each;
dbms_output.put_line(v_each.ename);
--关闭游标
close c;
exception
when others then
dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
end;
--带参数的游标
declare
--声明一个游标,不会真正取数据
cursor c(v_deptno emp.deptno%type, v_job emp.job%type) is
select * from emp where deptno=v_deptno and job=v_job;
--声明一个record
v_each c%rowtype;
begin
--for循环会自动打开游标,把游标指向的数据拿到v_each中,游标自动向下移动一个
for v_each in c(30,'SALESMAN') loop
dbms_output.put_line(v_each.ename);
end loop;
--for循环会自动关闭游标
exception
--可以把这些异常记录在一张异常表中
when others then
dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
end;
--循环遍历游标
--for循环
declare
--声明一个游标,不会真正取数据
cursor c is
select * from emp;
--声明一个record
v_each c%rowtype;
begin
--打开游标,执行语句。游标指向第一条记录
--for循环会自动打开游标
--open c;
--for循环自动把游标指向的数据拿到v_each中,游标自动向下移动一个
for v_each in c loop
dbms_output.put_line(v_each.ename);
end loop;
--for循环会自动关闭游标
--close c;
exception
--可以把这些异常记录在一张异常表中
when others then
dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
end;
--while循环
declare
--声明一个游标,不会真正取数据
cursor c is
select * from emp;
--声明一个record
v_each c%rowtype;
begin
--打开游标,执行语句。游标指向第一条记录
open c;
--把游标指向的数据拿到v_each中,游标自动向下移动一个
fetch c into v_each;
--如果找找记录,继续向下执行
while(c%found) loop
dbms_output.put_line(v_each.ename);
--游标向后移动
fetch c into v_each;
end loop;
--关闭游标
close c;
exception
--可以把这些异常记录在一张异常表中
when others then
dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
end;
--dowhile循环
declare --声明一个游标,不会真正取数据
cursor c is
select * from emp;
--声明一个record
--v_each c%rowtype;
begin
--打开游标,执行语句。游标指向第一条记录
open c;
--把游标指向的数据拿到v_each中,游标自动向下移动一个,自动声明v_each变量
loop
fetch c into v_each; --最近的一条记录没有返回记录,退出
exit when(c%notfound); dbms_output.put_line(v_each.ename);
end loop;
--关闭游标
close c;
exception
--可以把这些异常记录在一张异常表中
when others then
dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
end;
存储过程:
create or replace procedure ppp is替代declare,其他的一样。
执行用exec ppp;
或者:
begin
ppp;
end;
/
简单存储过程
--带参数的游标演示存储过程
create or replace procedure ppp is
--声明一个游标,不会真正取数据
cursor c(v_deptno emp.deptno%type, v_job emp.job%type) is
select * from emp where deptno=v_deptno and job=v_job;
--声明一个record
v_each c%rowtype;
begin
--for循环会自动打开游标,把游标指向的数据拿到v_each中,游标自动向下移动一个
for v_each in c(30,'SALESMAN') loop
dbms_output.put_line(v_each.ename);
end loop;
--for循环会自动关闭游标
exception
--可以把这些异常记录在一张异常表中
when others then
dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
end;
带参数的存储过程:
create or replace procedure ppp2(v_a in number, v_b number, v_c out number,v_d in out number) is
--三个参数,传入、传出、传入/传出三种类型。存储过程没有返回值。没有写默认是in
v_temp number := 5;
begin
if(v_a > v_b)then
v_c := v_a;
v_d := v_c*100;
elsif(v_a < v_b)then
v_c := v_b;
v_d := v_c*10;
end if;
exception
--可以把这些异常记录在一张异常表中
when others then
dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
end;
调用带参数的存储过程:
declare
c number;
d number := 10;
begin
ppp2(v_a => 2,v_b => 1,v_c => c,v_d => d);
dbms_output.put_line('c:'||c||'d:'||d);
end;
--函数有返回值,存储过程没有返回值
create or replace function sal_tax(v_sal number) return number is
begin
if(v_sal < 3000) then
return 0;
elsif(v_sal < 5000) then
return v_sal*0.1;
else
return v_sal*0.2;
end if;
end;
调用:
select sal, sal_tax(sal) from emp;
综合使用的例子:
create table departments(
DEPARTMENT_ID NUMBER(4) primary key,
DEPARTMENT_NAME VARCHAR2(30),
MANAGER_ID NUMBER(6),
LOCATION_ID NUMBER(4)
); insert into departments values(1,'技术部',1,1);
insert into departments values(2,'人事部',2,2);
insert into departments values(3,'市场部',3,3);
insert into departments values(4,'财务部',4,4);
create table employees(
EMPLOYEE_ID NUMBER(6) primary key,
FIRST_NAME VARCHAR2(20),
LAST_NAME VARCHAR2(25),
EMAIL VARCHAR2(25),
PHONE_NUMBER VARCHAR2(20),
HIRE_DATE DATE,
JOB_ID VARCHAR2(10),
SALARY NUMBER(8,2),
COMMISSION_PCT NUMBER(2,2),
DEPARTMENT_ID NUMBER(4) references departments(DEPARTMENT_ID)
); insert into employees(EMPLOYEE_ID,FIRST_NAME,LAST_NAME,SALARY,DEPARTMENT_ID) values(1,'JIA','JENNY',3000,1);
insert into employees(EMPLOYEE_ID,FIRST_NAME,LAST_NAME,SALARY,DEPARTMENT_ID) values(2,'guan','rose',4000,3);
insert into employees(EMPLOYEE_ID,FIRST_NAME,LAST_NAME,SALARY,DEPARTMENT_ID) values(3,'xu','mike',2000,2);
insert into employees(EMPLOYEE_ID,FIRST_NAME,LAST_NAME,SALARY,DEPARTMENT_ID) values(4,'zhang','billy',1000,2);
insert into employees(EMPLOYEE_ID,FIRST_NAME,LAST_NAME,SALARY,DEPARTMENT_ID) values(5,'jin','dede',5000,1);
声明一个存储过程,输入工资数sal,小于sal则+1,小于sal+1000则不变,大于则-1.
CREATE OR REPLACE PROCEDURE changeSal(sal in number,cnt out number)IS
--定义一个EMPLOYEES表对应的类型
eachOne EMPLOYEES%ROWTYPE;
--定义一个record
TYPE type_record IS RECORD(
ename varchar2(45),
sal EMPLOYEES.SALARY%type
);
--定义一个上述record类型的对象
temp type_record;
--定义一个数字
total NUMBER := 0;
--定义一个游标
CURSOR c IS select * from employees;
BEGIN
OPEN c;
--读取游标第一个值,游标向后移动
fetch c into eachOne;
dbms_output.put_line('存储过程正在执行,小于'||sal||'的薪水+1,小于'||(sal+1000)||'的薪水不变,大于的-1...');
while(c%found)loop
--拼接名字全称
temp.ename := eachOne.first_name||eachOne.last_name;
--变化薪水
if (eachOne.salary < sal)then
--变化了,计数
total := total+1;
temp.sal := eachOne.salary + 1;
elsif(eachOne.salary < sal+1000)then
temp.sal := eachOne.salary;
else
--变化了,计数
total := total+1;
temp.sal := eachOne.salary -1;
end if;
dbms_output.put_line('名字全称:'||temp.ename||', 变化后的薪水:'||temp.sal);
--游标向后移动
fetch c into eachOne;
end loop;
CLOSE c;
cnt := total;
END;--END PROCEDURE
调用:
declare
cnt1 number;
begin
changeSal(sal => 2000,cnt=>cnt1);
dbms_output.put_line('变化的结果:'||cnt1);
end;
结果:
SQL> declare
2 cnt1 number;
3 begin
4 changeSal(sal => 2000,cnt=>cnt1);
5 dbms_output.put_line('变化的结果:'||cnt1);
6 end;
7 /
存储过程正在执行,小于2000的薪水+1,小于3000的薪水不变,大于的-1...
名字全称:JIAJENNY, 变化后的薪水:2999
名字全称:guanrose, 变化后的薪水:3999
名字全称:xumike, 变化后的薪水:2000
名字全称:zhangbilly, 变化后的薪水:1001
名字全称:jindede, 变化后的薪水:4999
变化的结果:4
PL/SQL procedure successfully completed
PL/SQL练习的更多相关文章
- Oracle PL/SQL随堂笔记总结
1.pl/sql编程 2.存储过程 3.函数 4.触发器 5.包 6.pl/sql基础 -定义并使用变量 7.pl/sql的进阶 8.oracle的视图 1.pl/sql编程 1.理解oracle的p ...
- Oracle学习笔记十 使用PL/SQL
PL/SQL 简介 PL/SQL 是过程语言(Procedural Language)与结构化查询语言(SQL)结合而成的编程语言,是对 SQL 的扩展,它支持多种数据类型,如大对象和集合类型,可使用 ...
- PL/SQL连接错误:ora-12705:cannot access NLS data files or invalid environment specified
适合自己的解决方法: 排查问题: 1. 你没有安装Oracle Client软件.这是使用PL/SQL Developer的必须条件.安装Oracle Client后再重试.2. 你安装了多个Orac ...
- PL/SQL循环
1.if循环做判断 SET SERVEROUTPUT ON accept num prompt 'qinshuu'; DECLARE pnum NUMBER :=& num ; BEGIN T ...
- PL/SQL存储过程编程
PL/SQL存储过程编程 /**author huangchaobiao *Email:huangchaobiao111@163.com */ PL/SQL存储过程编程(上) 1. Oracle应用编 ...
- PL/SQL连接Oracle数据库,中文乱码,显示问号
问题描述: 登陆PL/SQL,执行SQL语句后,输出的中文标题显示成问号????:条件包含中文,则无数据. 如果不是中文,需要修改注册表值,方法如下: 进入注册表:Win+r,输入re ...
- PL/SQL客户端中执行insert语句,插入中文乱码
问题描述:在PL/SQL客户端中执行insert语句,插入中文乱码 解决方案: 1.执行脚本 select userenv('language') from dual; 结果为AMERICAN_ ...
- PL/SQL Developer如何连接64位的Oracle图解
在64位Win7系统上安装64位的Oracle数据库,但是没有对应的64位PL/SQL Developer,此时就不能使用PL/SQL Developer来进行直接连接的,所以要想实现连接还得需要其他 ...
- 每周一书《Oracle 12 c PL(SQL)程序设计终极指南》
本周为大家送出的书是<Oracle 12 c PL(SQL)程序设计终极指南>,此书由机械工业出版社出版, 孙风栋,王澜,郭晓惠 著. 内容简介: <Oracle 12c PL/SQ ...
- pl/sql里的exists和in的差别
项目中有个需要需要如下pl/sql(数据库是MariaDB) ) AS small FROM cmp_ent_main a WHERE createTime<'2016-9-21' ,,) ) ...
随机推荐
- iframe 的基本操作
要在服务器环境下才行 1.iframe 下操作父页面window.parent.document.getElementById //全部支持window.top //最顶层ie 下的iframe的on ...
- MarkDown教程
MarkDown笔记 在线编辑器其他教程 [1.标题] 标题1 标题1=== 标题2 标题2--- 标题3 1 2 3 4 5 6 7 7 #1 ##2 ###3 ####4 #####5 ##### ...
- linux基础之Shell Script入门介绍
本文介绍下,学习shell script编程的入门知识,通过几个入门实例,带领大家走进shell script的神圣殿堂,呵呵,有需要的朋友参考下. 本文转自:http://www.jbxue.com ...
- 发测试邮件或垃圾邮件node脚本
npm install nodemailer 执行后,指定目录下会出现node_modules模块,再相同目录下,创建main.js,js代码如下: var nodemailer = require( ...
- JBPM4中常用概念总结
1. 流程定义(Process Definition) 流程定义是记录在xml文件中的对流程的描述,它包含唯一的流程开始节点和多个流程功能节点,每个节点之间使用transition进行连接. P ...
- 关于Java(JDBC介绍)
JDBC API 允许用户访问任何形式的表格数据,尤其是存储在关系数据库中的. JDBC 简单功能 连接数据源,如数据库 传给数据库查询和更新指令 获取并处理数据库返回结果(对查询等的响应) 示例代码 ...
- CTSC && APIO 总结
先说CTSC吧,第一试其实不难但是下意识觉得CTSC不就只能骗分吗,然后就全上暴力了.然而第二题再一次看漏了条件,即答案总和小于等于1e6.第三题现在回想起来要不然就是没有思考,要不然就是没学过数学, ...
- HttpWebRequest提高效率之连接数,代理,自动跳转,gzip请求等设置问题
先设置4个: [csharp] webrequest.ServicePoint.Expect100Continue = false; //是否使用 Nagle 不使用 提高效率 webrequest. ...
- maven 根据不同的环境打war包-->资源文件的处理方式
发现犯的错误: 1. 指定了testResource 文件夹与resource 为同一个文件夹.导致不论在resource 里面如何过滤文件,都不起作用.资源文件本来就是共享的.不必这样指定. 2. ...
- 【BZOJ 2154】Crash的数字表格 (莫比乌斯+分块)
2154: Crash的数字表格 Description 今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple).对于两个正整数a和b,LCM(a, b)表示能 ...