#1.PL/SQL
#PL/SQL是Oracle內部使用的編程語言, Procedure Language過程語言,其語言格式比較固定
begin
dbms_output.put_line('HelloWorld');
end;
/ #/表示執行
set serveroutput on; #執行輸出命令,默認是off(關閉)
declare #聲明變量
v_name varchar2(20);
begin
v_name := 'myname'; #給變量賦值
dbms_output.putline(v_name);
end;
/
#打印:myname, 輸出myname
#PL/SQL過程已成功完成
declare
v_name number:= 0;
begin
v_name := 2/v_name;
dbms_output.put_line(v_name);
exception
when others then
dbms_output.put_line('error');
end;
/
#去掉exception語句塊
declare
v_name number:= 0;
begin
v_name := 2/v_name;
dbms_output.put_line(v_name);
end;
/
#則會出現如下錯誤:除數爲 0 在 line 4
#2.變量聲明
#變量名不能使用保留字,如from, select等
#第一個字符必須是字母
#變量名最多包含30個字符
#不要與數據庫的表或者列同名
#每一行只能聲明一個變量
#3.常用變量類型
#binary_integer: 整數,主要用來計數而不是用來表示字段類型
#number : 數字類型
#char: 定長字符串
#varchar2: 變長字符串
#date: 日期
#long: 長字符串, 最長2GB
#boolean :布爾類型, 可以取值爲true, false和null值.
declare
v_temp number(1);
v_count binary_integer := 0; --binary_integer 是用來記數的,效率比較高一點.
v_sal number(7,2) := 4000.00;
v_date date := sysdate;
v_pi constant number(3,2) := 3.14;
v_valid boolean := false;
v_name varchar2(20) not null := 'MyName';
begin
dbms_output.put_line('v_temp value: ' || v_date);
end;
#4.變量聲明,使用%type屬性
declare
v_empno number(4);
v_empno2 emp.empno%type; --表示emp表中empno的類型
v_empno3 v_empno2%type;
begin
dbms_output.put_line('Test');
end;
--Table 變量類型
declare
type type_table_emp_empno is table of emp.empno%type index by binary_integer;
v_empnos type_table_emp_empno;
begin
v_empnos(0):=7369;
v_empnos(2):=7839;
v_empnos(-1):= 9999;
dbms_output.put_line(v_empnos(-1));
end;
--Record變量類型 (相當於java中的類(class))
declare
type type_record_dept is record
(
deptno dept.deptno%type,
dname dept.dname%type,
loc dept.loc%type
) ;
v_temp type_record_dept; --聲明變量是type_record_dept類型
begin
v_temp.deptno :=50; --引用類型的屬性
v_temp.dname := 'aaaa';
v_temp.loc := 'bj';
dbms_output.put_line(v_temp.deptno||' '|| v_temp.dname);
end;
/
--record類型是指定義了一個類,然後引用類中的屬性.
--使用%rowtype聲明record變量
declare
v_temp dept%rowtype;
begin
v_temp.deptno := 50;
v_temp.dname := 'aaa';
v_temp.loc := 'bj';
dbms_output.put_line(v_temp.deptno ||' ' ||v_temp.dname);
end;
/
--可以保留原來的類型
--PL/SQL語句,必須返回一條記錄,只能返回一條記錄.
--SQL語句的運用
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; --把ename中的記錄賦值給v_ename,sal賦值給v_sal.
dbms_output.put_line(v_ename ||' '||v_sal);
end;
/
--結果: SMITH 800
declare
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
select ename, sal into v_ename, v_sal from emp where empno = 9999;
dbms_output.put_line(v_ename ||' '||v_sal);
end;
/
--如果未找到數據
declare
v_sal emp.sal%type;
begin
select sal into v_sal from emp
where empno = 7369;
if(v_sal<1200) then
dbms_output.put_line('low');
elsif(v_sal<2000) then
dbms_output.put_line('middle');
else
dbms_output.put_line('high');
end if;
end;
set serveroutput on;
declare
v_sal2 emp.sal%type;
begin
select sal into v_sal2 from emp where empno = 7839;
if(v_sal2>2500) then
v_sal2 := v_sal2 / 2;
elsif(v_sal2<2500) then
v_sal2 := v_sal2 * 2;
else
v_sal2 := 2500;
end if;
end;
--循環
--loop循環
declare
i binary_integer:=1;
begin
loop
dbms_output.put_line(i);
i := i+1;
exit when(i>=11);
end loop;
end;
--while循環
declare
j binary_integer :=1;
begin
while (j<11) loop
dbms_output.put_line(j);
j := j +1;
end loop;
end;
--for 循環
begin
for k in 1..10 loop
dbms_output.put_line(k);
end loop;
for k in reverse 1..10 loop
dbms_output.put_line(k);
end loop;
end;
--錯誤處理
declare
v_temp number(4);
begin
select empno into v_temp from emp where deptno = 10;
exception
when too_many_rows then
dbms_output.put_line('太多記錄');
when others then
dbms_output.put_line('error');
end;
declare
v_temp number(4);
begin
select empno into v_temp from emp where empno = 2222;
exception
when no_data_found then
dbms_output.put_line('沒數據');
end;
--記錄錯誤的做法
create table errorlog
(
id number primary key,
errcode number,
errmsg varchar2(1024),
errdate date
);
create sequence seq_errorlog_id start with 1 increment by 1;
declare
v_deptno dept.deptno%type := 10;
v_errcode number;
v_errmsg varchar2(1024);
begin
delete from dept where deptno = v_deptno;
commit;
exception
when others then
rollback;
v_errcode := SQLCODE;
v_errmsg := SQLERRM;
insert into errorlog values(seq_errorlog_id.nextval, v_errcode, v_errmsg, sysdate);
commit;
end;
select to_char(errdate, 'YYYY_MM_DD HH24:MI:SS') from errorlog;
--循環定義一個遊標
--遊標是系統爲用戶開設的一個數據緩衝區,存放SQL語句的執行結果.每個遊標區都有一個名字.
--用戶可以用SQL語句逐一從遊標中獲取記錄,並賦給主變量,交由主語言進一步處理。主語言是面向記錄的,一組主變量一次只能存放一條記錄。
declare
cursor c is
select * from emp;
v_emp c%rowtype;
begin
open c;
loop
fetch c into v_emp;
exit when(c%notfound);
dbms_output.put_line(v_emp.ename);
end loop;
close c;
end;
declare
cursor c is
select * from emp;
v_emp emp%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;
--帶參數的遊標
declare
cursor c (v_deptno emp.deptno%type, v_job emp.job%type) is
select ename, sal from emp where deptno=v_deptno and job= v_job;
--v_temp(%rowtype)
begin
for v_temp in c(30,'CLEAK') loop
dbms_output.put_line(v_temp.ename);
end loop;
end;
--可更新的遊標
declare
cursor c is
select * from emp2 for update;
begin
for v_temp in c loop
if(v_temp.sal<2000)then
update emp2 set sal= sal*2 where current of c; --更新當前遊標,遊標到哪條記錄,更新哪條.
elsif(v_temp.sal = 5000) then
delete from emp2 where current of c;
end if;
end loop;
commit;
end;
--存儲過程
--(帶有名字的PL/SQL的程序塊)
create or replace procedure p
is
cursor c is
select * from emp2 for update;
begin
for v_emp in c loop
if(v_emp.deptno = 10) then
update emp2 set sal= sal+10 where current of c;
elsif(v_emp.deptno =20) then
update emp2 set sal=sal+20 where current of c;
else
update emp2 set sal=sal+30 where current of c ;
end if;
end loop;
end;
--執行存儲過程
exec p;
--查看結果集
select sal from emp2;
--或者
begin p;
end;
--再執行了一次
--查看結果集
select sal from emp2;
--帶參數的存儲過程
create or replace procedure p1
(v_a in number, v_b number, v_ret out number, v_temp in out number)
is
begin
if(v_a>v_b) then
v_ret :=v_a;
else
v_ret :=v_b;
end if;
v_temp:=v_temp+1;
end;
--調用過程
declare
v_a number :=3;
v_b number :=4;
v_ret number;
v_temp number:=5;
begin
p(v_a, v_b, v_ret, v_temp);
dbms_output.put_line(v_ret);
dbms_output.put_line(v_temp);
end;
--結果
4
6
--刪除存儲過程
drop procedure p;
show error; --顯示錯誤.
--函數(function)
create or replace function sal_tax
(v_sal number) return number
is
begin
if(v_sal<2000)then
return 0.10;
elsif(v_sal<2750) then
return 0.15;
else
return 0.20;
end if;
end;
-- 運用函數
select lower(ename), sal_tax(sal) from emp;
--觸發器
create table emp2_log
(
aname varchar2(20),
action varchar2(10),
atime date
);
create or replace trigger trig
after insert or delete or update on emp2 for each row
begin
if inserting then
insert into emp2_log values(USER,'insert',sysdate);
elsif updating then
insert into emp2_log values(USER,'update',sysdate);
elsif deleting then
insert into emp2_log values(USER,'delete',sysdate);
end if;
end;
update emp2 set sal= sal*2 where deptno=30;
select * from emp2_log;
update dept set deptno = 99 where deptno=10;#違反完整約束條件 (DYS.FK_DEPTNO),因爲有外鍵參考.
--刪除觸發器
drop trigger trig;
create or replace trigger trig
after update on dept
for each row
begin
update emp set deptno=:NEW.deptno where deptno=:OLD.deptno;
end;
update dept set deptno=99 where deptno=10;
select deptno from dept;
--樹狀結構的存儲與展示
drop table article;
create table article
(
id number primary key,
cont varchar2(4000),
pid number,
isleaf number(1),--0代表非葉子節點,1代表葉子節點.
alevel number(2)
);
insert into article values(1,'螞蟻大戰大象',0,0,0);
insert into article values(2,'大象被打趴下了',1,0,0);
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 p1(v_pid article.pid%type, v_level binary_integer) is
cursor c is select * from article where pid=v_pid;
begin
for v_article in c loop
dbms_output.put_line(v_article.cont);