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' ,,) ) ...
随机推荐
- 【原创】QT编程 多线程
请先保证已安装QT,没有请参考 http://www.cnblogs.com/kavs/p/4608926.html 安装QT. 新建threads文件夹存放项目:mkdir threads sud ...
- HTTP协议-标签简介
这个系列的文章要讨论的是如何通过ASP.net服务器端技术来优化客户端缓存策略,而且让这种策略变得可配置和可扩展.我们要了解的知识从HTTP协议中相关属性对客户端缓存的影响,到ASP.NET如何控制这 ...
- 移动端开发(使用webuploader上传图片,客户端交互,修改alert弹窗等)
之前实习做的一个移动端的页面 需要的功能有图片上传 点击客户端的返回按钮 有提示(即与客户端有交互) 遇到不少的坑 总结一下问题 1.图片上传功能 使用工具 百度的webuploader 暂时遇到的 ...
- tomcat配置虚拟目录的步骤
1.在tomcat中.....\conf\Catalina\localhost中创建一个test.xml文件 2.然后在\conf的server.xml中的 <Host > 元素里面 添加 ...
- wamp的mysql密码修改
==方法1== 通过WAMP打开mysql控制台,提示输入密码,因为现在是空,所以直接按回车. 输入“use mysql”,意思是使用mysql这个数据库教程,提示“Database changed” ...
- IEnumerable,ICollection,IList,List区别
做C#的同学们,都知道,一类只能有一个继承类,但可以实现多个接口.这句话就告诉我们:IEnumerable,ICollection,IList,List区别了 首先我看看 IEnumerable: / ...
- 查看sqlserver数据库的端口号
最近正在用sqlserver作为java的数据库进行开发,在写连接字符串的时候,想起一个问题,怎么查找sqlserver的端口号呢?有两种方法 1,用存储过程 --查询端口号exec sys.sp_r ...
- iOS开发者计划(转)
苹果对软件和开发者的管理十分严格,你只有加入了Apple Developer计划之后,才能将你的软件放到真机上运行或者发布到App Store上去.这种方法看似麻烦,但是却有效的解决了盗版和劣质软件充 ...
- spirng MVC乱码过滤器
<filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>or ...
- 【LA3523】 Knights of the Round Table (点双连通分量+染色问题?)
Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress ...