尚学堂Oracle笔记(2)

时间:2022-10-24 18:00:45

-----------------------------pl/sql中的sql语句----------------------
1、select语句
有且只有一条返回值,且必须加into
例子:
declare
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
select ename,sal into v_ename,v_sal from emp where empno=7369; --有且只有一条返回值, --且必须加into
dbms_output.put_line(v_ename||' '||v_sal);
end;
2、update 、delete、insert语句和sql中相同,可能和变量混用;

declare
v_deptno emp2.deptnpo%type:=10;
v_count number;
begin
update emp2 set sal =sal/2 where deptno =v_deptno;
dbms_output.put_line(sql%rowcount||'条记录被修改'); --sal%rowcount 返回记录数
commit;
end;

3、执行ddl语句--(记住有execute immediate)
begin
execute immediate 'create table t(nn varchar(2) default ''a'')';
end;
4、if语句
declare
v_sal emp.sal%type;
begin
select sal into v_sal from emp where empno =7839;
if v_sal <= 800 then
dbms_output.put_line('low') ;
elsif v_sal >= 2800 then --不是elseif
dbms_output.put_line('high');
else
dbms_output.put_line('middle');
end if; --注意有这条语句
end;
5、while语句
declare
k binary_integer:=1;
begin
while ( k <11 ) loop
dbms_output.put_line(k) ;
k:=k+1;
end loop;
end;
6、do ..while语句
declare
k binary_integer:=1;
begin
loop
dbms_output.put_line(k) ;
k:=k+1;
exit when(k>=11);
end loop;
end;
7、for循环
declare
k binary_integer:=1;
begin
for k in 1..10 loop
dbms_output.put_line(k) ;
end loop;
end;

declare
k binary_integer:=1;
begin
for k in reverse 1..10 loop --加上reverse为逆序打印
dbms_output.put_line(k) ;
end loop;
end;

-------------------游标(pl/sql重点)-----------------
1、plsql中select语句只能返回一条语句,要想返回多条语句,用游标。
2、简单循环
declare
cursor c is
select * from emp;
v_emp c%rowtype;
begin
open c;
loop
fetch c into v_emp;--fetch完后自动定位到下条记录
exit when(c%notfound);
dbms_output.put_line(v_emp.ename) ; --不能放在exit前,否则最后一条记录打印两次
end loop;
close c;
end;
3、while循环
declare
cursor c is
select * from emp;
v_emp c%rowtype;
begin
open c;
fetch c into v_emp;
while(c%found)loop
dbms_output.put_line(v_emp.ename) ;
fetch c into v_emp;
end loop;
close c;
end;
4、for循环 (循环时最简单)
declare
cursor c is
select * from emp;
begin
for v_emp in c loop --不用定义v_emp,不用打开关闭游标了
dbms_output.put_line(v_emp.ename) ;
end loop;
end;

5、带参数的游标
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;
begin
for v_emp in c(30,'CLERK') loop
dbms_output.put_line(v_emp.ename) ;
end loop;
end;
6、可更新的游标
游标一般是作为记录集读取数据用的,但有时候用游标修改记录,这就是可更新游标;
declare
cursor c is
select * from emp2 for update;
begin
for v_emp in c loop
if(v_emp.sal <2000) then
update emp2 set sal =sal+1 where current of c ; --修改定位到的当前记录,注意形式
elsif(v_emp.sal>=2000) then
delete from emp2 where current of c;
end if;
end loop;
commit; --提交
end;
-------------------------存储过程--------------------
1、把过程的declare变成 create or Replace produce p is 就行。

--declare
create or replace procedure p
is
cursor c is
select * from emp2 for update;
begin
for v_emp in c loop
if(v_emp.sal <2000) then
update emp2 set sal =sal+1 where current of c ;
elsif(v_emp.sal>=2000) then
delete from emp2 where current of c;
end if;
end loop;
commit;
end;

创建了存储过程不代表运行了存储过程;
运行此存储过程 :
方式一 exec p;
方式二
begin
p;
end;
2、带参数的存储过程
in 相当于程序里的参数,供传入用,在存储过程不能改变其值;
out 相当于程序里的返回值,在存储过程中可以为其赋值传出;
in out 既可以当参数又可以当返回值用;
不带上述说明符默认为in类型;

下例中v_a v_b 为in类型
v_c 为out类型
v_d 为in out 类型

create or replace procedure p(v_a in number,v_b number,v_c out number,v_d in out number)
is
begin
if(v_a > v_b) then
v_c := v_a;
else
v_c := v_b;
end if;
v_d := v_d+1;
end;

---> 调试时:
可以在命令窗口调试,出错时 用show errors 显示出错信息;
可以在plDv中调试;

---> 运行时:
可以在命令窗口运行:
declare
v_a number:=3;
v_b number:=4;
v_c number;
v_d number:=5;
begin
p(v_a,v_b,v_c,v_d);
dbms_output.put_line(v_c);
dbms_output.put_line(v_d);
end;
可以在plDv中调试;

------------------函数-------------------
1、它有返回值
create or replace function tax_tag(sal number)return number --计算税率
is
begin
if(sal > 1000)then
return 0.1;
elsif(sal>=2000)then
return 0.15;
else
return 0.2;
end if;
end;

select ename, tax_tag(sal) from emp ;-- 直接用函数tax_tag

-------------------------recursion 通过递归写树--------------------
-----》创建表并插入记录
create table article (
id number primary key,
cont varchar2(4000),--文章内容
pid number, --父类id
isleaf number(1),--0代表非叶子节点,1代表叶子节点
alevel number(2) --等级
)
insert into article values(1,'蚂蚁大战大象',0,0,0);
insert into article values(2,'大象被打趴下',1,0,1);
insert into article values(3,'蚂蚁也不好过',2,1,2);
insert into article values(4,'瞎说',2,0,2);
insert into article values(5,'没有瞎说',4,1,3);
insert into article values(6,'怎么可能',1,0,1);
insert into article values(7,'怎么没有可能',6,1,2);
insert into article values(8,'可能行很大的',6,1,2);
insert into article values(9,'大象进医院了',2,0,2);
insert into article values(10,'蚂蚁是护士',9,1,3);

----------》存储过程
create or replace procedure p (v_pid article.pid%type,v_level binary_integer) is
cursor c is select * from article where pid = v_pid;
v_perStr varchar2(2000):=' ';
begin
for i in 1..v_level loop
v_perStr := v_perStr||'***';
end loop;
for v_article in c loop
dbms_output.put_line(v_perStr||v_article.cont);
if (v_article.isleaf = 0)then
p(v_article.id,v_level + 1);
end if;
end loop;
end;

----------》输出结果
蚂蚁大战大象
***大象被打趴下
******蚂蚁也不好过
******瞎说
*********没有瞎说
******大象进医院了
*********蚂蚁是护士
***怎么可能
******怎么没有可能
******可能行很大的