--例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;