--例1:基本类型
declare
--变量类型:number、varchar二、char、date、binary_integer(索引)
v_a number:=100;
v_b varchar2(100) ;
--字符串必须加长度
v_d date:=sysdate;
--动态追踪表内数据类型
v_ename emp.ename%type;
--动态追踪列类型
v_emp_row emp%rowtype;
--动态追踪行类型
begin
v_b := 'aaa';
--赋值语句
dbms_output.put_line(v_a||' '||v_b||' '||v_d);
--select into 语句 赋值语句 语法:必须保证结果只有一条
select e.ename into v_ename from emp e where e.empno=7369;
select sum(e.sal) into v_a from emp e;
dbms_output.put_line(v_ename||' '||v_a);
--使用行类型
select e.ename,e.hiredate,e.deptno into v_emp_row.ename,v_emp_row.hiredate,v_emp_row.deptno from emp e where e.empno=7369;
select e.* into v_emp_row from emp e where e.empno = 7499;
dbms_output.put_line(v_emp_row.ename||' '||v_emp_row.hiredate);
-- exception
end;
--例2:异常
declare
v_num number;
v_num2 number;
begin
select e.sal into v_num2 from emp e where e.empno=3333;
exception
/* when too_many_rows then
dbms_output.put_line('数据多啦');
when no_data_found then
dbms_output.put_line('数据没找到');*/
when others then
dbms_output.put_line('---------');
end;
--例3:if语句
declare
v_num1 number :=floor((dbms_random.value*6))+1;
v_num2 number :=floor((dbms_random.value*6))+1;
v_num3 number :=floor((dbms_random.value*6))+1;
v_sum number := v_num1+v_num2+v_num3;
begin
--摇色子 三个随机数 求和 if 条件 then 语句; elsif 条件1 and/or 条件2 then 语句;...else 语句; end if;
if v_sum >=12 then
dbms_output.put_line('手气不错');
elsif v_sum>=8 and v_sum <12 then
dbms_output.put_line('手气通常');
else
dbms_output.put_line('手气不好');
end if;
end;
--例4:for循环
declare
v_sum number:=0;
begin
--for 变量 in 集合 loop 循环体; end loop; 变量不须要声明 会动态匹配集合的单个元素的类型 v_r不能被赋值
for v_r in 1..100 loop
if mod(v_r,2)<>0 then
v_sum := v_sum+v_r;
end if;
end loop;
dbms_output.put_line(v_sum);
dbms_output.put_line('-----------------');
for v_r in reverse 1..10 loop
--reverse :逆序
dbms_output.put_line(v_r);
end loop;
end;
--例5:loop循环
declare
v_i number :=1;
v_sum number :=0;
begin
loop
v_sum := v_sum + v_i;
--循环体
exit when v_i>3;
--退出条件
v_i := v_i+1;
--循环体
end loop;
dbms_output.put_line(v_sum);
end;
--例6:while循环
declare
v_i number :=1;
v_sum number :=0;
begin
while v_i<=100 loop
--循环条件
v_sum := v_sum+v_i;
--循环体开始
v_i := v_i+1;
end loop;
dbms_output.put_line(v_sum);
end;
--例7:dml和ddl
declare
begin
-- dml 增删改 能够放结合事务处理, 不容许放查询语句 ddl create 语句 结合execute immediate 'ddl/dml';
insert into emp_copy ec select * from emp e;
commit;
execute immediate 'create table A(a_id number)';
--建立表语句加单引号
end;
--例8:Created on 2013-11-5 by ADMINISTRATOR
declare
--先定义类型 注意 内部多个变量 逗号隔开。
type record_type is record(
v_a number not null :=100,
--not null必须 初始化值
v_ename emp.ename%type,
--列类型
v_b varchar2(20)
);
--再绑定变量
v_r record_type;
begin
v_r.v_b :='aaa';
select e.ename into v_r.v_ename from emp e where e.empno=7499;
dbms_output.put_line(v_r.v_a||' '||v_r.v_b||' '||v_r.v_ename);
end;
--例9:table和复合类型
declare
--table相似于数组,使用步骤 :
--1:定义类型
type tab_type is table of varchar2(100) index by binary_integer;
--2: 变量对应类型
v_tab1 tab_type;
--集中赋值的table语法后不加 index by
type tab_type_2 is table of varchar2(100) ;
v_tab2 tab_type_2;
begin
-- 零散赋值 索引任意
v_tab1(0) :='aaa';
v_tab1(1) :='bbb';
dbms_output.put_line(v_tab1(0)||' '||v_tab1(1));
--集中赋值 索引只能从1开始
v_tab2 := tab_type_2('aaa','bbb','ccc');
dbms_output.put_line(v_tab2(1)||' '||v_tab2(2));
end;
--例10:简单了解权限
create user 用户名 identified by 密码
--必须是管理员(dba)身份才能够建立用户
grant create session to stu;
--建立新用户后须要 赋回话权限
grant create view to scott
grant select,insert on emp to hr;
--on后跟的是表名
--切换到hr用户,能够正常对emp表执行select和insert操做。
--以后,再在Scott用户下,收回hr对emp的权限
revoke all on emp from hr;
--赋予存储过程debug权限
grant debug connect session to scott;
--例11: 不带参数的存储过程
create or replace procedure p_emp
is
begin
insert into emp_copy(empno,ename) values(9999,'9999');
commit;
exception
when others then
rollback;
end;
例12:带参数的存储过程
--能够写参数 in 参数 out 参数 in 和out 能够有多个
create or replace procedure p_emp_job(
--工做环境下不要加or replace
l_empno in number,
-- in 能够省略 最好写上 不能被赋值
l_job in out varchar2,
-- 通常 in out 都分开写
l_sal out number
)
is
--此处声明或初始化变量
begin
select e.sal , e.job into l_sal , l_job from emp e where e.empno=l_empno and e.job=l_job;
l_job := '7499';
end;
--例13:调用参数存储过程
declare
v_job varchar2(20) :='CLERK';
v_sal number;
begin
p_emp_job(7369,v_job,v_sal);
--存储过程名加参数
dbms_output.put_line(v_job||' '||v_sal);
end;
--例14:显示游标
/**
显式游标:
静态游标: 声明 打开 遍历 (操做数据) 关闭; 推荐 for
动态游标:
弱类型游标:
强类型游标:
*/
declare
--声明静态游标 能够带参数,参数类型后不加长度
cursor c_emp1 is select * from emp e ;
cursor c_emp2(l_deptno number,l_job varchar2) is select * from emp e where e.deptno=l_deptno and e.job=l_job;
v_r c_emp2%rowtype;
--行类型
begin
--打开游标 若是有参数 open时传参 ,若是没参数,不用写。
open c_emp2(20,'CLERK');
--遍历
loop
fetch c_emp2 into v_r;
--fetch 语句:至关于 next
exit when c_emp2%notfound;
dbms_output.put_line(v_r.ename);
end loop;
--关闭游标
close c_emp2;
--静态游标推荐使用for 能够自动打开和关闭游标
dbms_output.put_line('======================');
for v_m in c_emp2(20,'CLERK') loop
dbms_output.put_line(v_m.ename);
end loop;
dbms_output.put_line('======================');
--while为啥很差使。
open c_emp2(20,'CLERK');
fetch c_emp2 into v_r;
while c_emp2%found loop
dbms_output.put_line(v_r.ename);
fetch c_emp2 into v_r;
end loop;
close c_emp2;
end;
--例14:
隐式游标
/*游标:
隐式游标: sql语句 就是游标 默认游标的名字sql (update/delete)事务提交后 游标自动关闭。
*/
declare
begin
-- Test statements here
update emp_copy ec set ec.ename='aaa' where ec.deptno = 20;
commit;
if sql%notfound then
dbms_output.put_line('notfound');
elsif sql%found then
dbms_output.put_line('found');
end if;
end;
--例15:
动态游标之强类型
declare
--强类型动态游标
type c_emp is ref cursor return emp%rowtype;
v_emp c_emp;
v_emp_row v_emp%rowtype;
begin
open v_emp for select * from emp e;
loop
fetch v_emp into v_emp_row;
exit when v_emp%notfound;
dbms_output.put_line(v_emp_row.ename);
end loop;
close v_emp;
end;
--例16:动态游标之弱类型
/*
动态游标
弱类型:
强类型:
*/
declare
--先定义游标类型
type c_emp is ref cursor;
--绑定变量 此变量是游标
v_emp c_emp;
--定义游标 行类型
v_emp_row emp%rowtype;
v_dept_row dept%rowtype;
begin
--打开游标
open v_emp for select * from emp e ;
--遍历游标
loop
fetch v_emp into v_emp_row ;
exit when v_emp%notfound;
dbms_output.put_line(v_emp_row.ename);
end loop;
--关闭游标
close v_emp;
--打开游标 装 dept的数据
dbms_output.put_line('===================');
open v_emp for select * from dept d;
loop
fetch v_emp into v_dept_row;
exit when v_emp%notfound;
dbms_output.put_line(v_dept_row.dname);
end loop;
close v_emp;
end;
--例17: 使用游标更新结果集
declare
--静态游标 select后加 for update 意味着结果集数据能够更新
cursor c_emp_copy is select * from emp_copy for update;
begin
for v_r in c_emp_copy loop
if v_r.deptno=20 then
update emp_copy ec set ec.ename='bbb' where current of c_emp_copy;
-- update emp_copy ec set ec.ename='bbb' where ec.empno = v_r.empno;
end if;
end loop;
commit;
exception
when others then
rollback;
end;
--例18:语句级触发器 记录信息时跟你操做多少条数据无关,只跟执行的语句有关。执行一次语句 触发一次.
create or replace trigger tr_emp_copy
after insert or delete or update on emp_copy
begin
if inserting then
insert into emp_copy_log values(seq_emp_copy_log.nextval,user,sysdate,'inserting');
elsif deleting then
insert into emp_copy_log values(seq_emp_copy_log.nextval,user,sysdate,'deleting');
elsif updating then
insert into emp_copy_log values(seq_emp_copy_log.nextval,user,sysdate,'updating');
end if;
--触发器事务不须要提交 或回滚,自动处理
end;
select * from emp_copy;
select * from emp_copy_log;
delete from emp_copy ec where ec.deptno=20;
commit;
--例19:行级触发器 (for each row) 用来维护数据完整性
select * from dept;
select * from emp ;
update dept d set d.deptno =10 where d.deptno=77;
commit;
--before after区别 :能否修改 :new 的值(before能够修改,after 不能够修改) 二者对:old的值都不可修改
create or replace trigger tr_emp_dept
before update on dept for each row
begin
update emp e set e.deptno= :new.deptno where e.deptno = :old.deptno;
end;
--例20:
instead of 触发器
select * from v$_emp;
update v$_emp e set e.ename='aaa' where e.empno=2222;
commit;
select * from v$_emp_dept;
--组成视图的表叫基表 一个视图只有一个基表 只读状况下,不能够修改。非只读状况下能够修改数据
--若是一个视图有多个基表,修改的字段牵扯到多个基表时,不能被修改,牵扯到1个基表,能够修改.
update v$_emp_dept e set e.ename='ccc',e.dname='mmm' where e.empno=2222;
commit;
--instead of 触发器
create or replace trigger tr_v$_emp_dept
instead of update on v$_emp_dept
begin
update emp e set e.ename=:new.ename where e.empno=:old.empno;
update dept d set d.dname=:new.dname where d.deptno = :old.deptno;
end;
--例21:写一个存储过程,能够完成对 dept_copy表的增删改
--debug步骤: 受权 sysdba下登录 而后执行 grant debug connect session to 用户名;
--回到用户,选中存储过程名 右键 选add debug ... 选 test
create or replace procedure p_dept_copy(
l_remark in number,
--0:add 1:update 2:delete
l_deptno in number,
l_dname in varchar2,
l_loc in varchar2,
l_result out number,
--0:失败 1:成功 2:传参错误
l_result2 out varchar2
)
is
begin
if l_remark=0 then--add
insert into dept_copy values(l_deptno,l_dname,l_loc);
elsif l_remark=1 then--update
update dept_copy dc
set
dc.dname=l_dname,
dc.loc=l_loc
where dc.deptno = l_deptno;
elsif l_remark=2 then
delete from dept_copy dc where dc.deptno = l_deptno;
else
l_result :=2;
l_result2 :='传参错误';
end if;
commit;
--处理返回标记
l_result:=1;
l_result2:='成功';
exception
when others then
rollback;
l_result:=0;
l_result2:='失败';
end;
--例22:函数
create or replace function f_str(
l_str1 varchar2,
l_str2 varchar2
)return varchar2
--此处不加分号 不加长度
is
begin
return l_str1 || l_str2;
end;
--例23:select a.fid,f_a(fid) from A group by fid;
create or replace function f_a(
l_fid number
)return varchar2
is
cursor c_a is select field1 from a where a.fid = l_fid;
l_str varchar2(100);
begin
for r in c_a loop
l_str := l_str||r.field1||',';
end loop;
return rtrim(l_str,',');
end;
sql
create or replace procedure test_pro(
cur_customers out my_pac.cur_type --包里定义游标
)
is
begin
open cur_customers for select * from customers;
end;