Oracle的PL SQL語法
PL/SQL
一、函式的應用
1.變數的宣告與賦值
--宣告一個變數,並賦值、列印
declare
str varchar2(30);
sname emp.ename%type;--宣告一個與emp表的ename屬性一致的型別
ctable emp%rowtype;--宣告一個與emp表相同的行型別
begin
str:='&請輸入:';--手動輸入,是一種動態賦值
select ename into sname from emp whereempno=7369;
select * into ctable from emp whereempno=7499;
dbms_output.put_line('str='||str);
dbms_output.put_line('sname='||sname);
dbms_output.put_line('ename='||ctable.ename);
end;
2.if語句的使用
--if 取出7369的薪水,判斷是否納稅
declare
salary emp.sal%type;
begin
select sal into salary from emp whereempno=7369;
if salary>=3000 then
dbms_output.put_line('需要納稅');
else --elsif相當於java裡elseif
dbms_output.put_line('需努力');
end if;
end;
--case 的兩種用法
1>.declarestr varchar2(10);
begin
str:='A';
case str
when'A' then dbms_output.put_line('優秀');
when 'B' thendbms_output.put_line('良好');
when 'C' thendbms_output.put_line('好');
when 'D' thendbms_output.put_line('一般好');
when 'E' thendbms_output.put_line('不好');
else dbms_output.put_line('很不好');
end case;
end;
2>.
declare mysalnumber(6,2);
eno number(6);
begin
eno:=7369; --直接賦值
select sal intomysal from emp where empno=eno; --這也是一種賦值
case when mysal>3500 then dbms_output.put_line('交稅');
when mysal=3500 thendbms_output.put_line('剛好');
when mysal<3500 thendbms_output.put_line('努力');
else dbms_output.put_line('其他');
end case;
end;
3.Loop While For 三種迴圈
1> --輸出1..100;
declare inumber(6):=1;
mysumnumber(6):=0;
begin
<<b_loop>>--給loop取個名字
loop
dbms_output.put_line(i);
mysum:=mysum+i;
exit b_loopwhen i=200; --跳出迴圈
i:=i+1;
end loop;
dbms_output.put_line(mysum);
end;
declare inumber(6):=1;
mysumnumber(6):=0;
begin
while i<=100 loop
mysum:=mysum+i;
i:=i+1;
end loop;
dbms_output.put_line(mysum);
end;
declare
mysumnumber(6):=0;
begin
for i in 1..100 loop --1..100這兩個引數均可使用變數
mysum:=mysum+i;
--i:=i+1;
end loop;
dbms_output.put_line(mysum);
end;
4.Oracle兩種常見的報錯
too_many_rows //太多行錯誤
no_data_found //沒找到資料
二、遊標
遊標分為隱式遊標、顯示遊標、REF遊標。
1>.隱式遊標
隱式遊標無需我們申明、建立、使用,它全由系統自動完成,我們在JDBC中使用的ResultSet物件就是這種用法。
2>顯示遊標
--pl/sql 宣告(declare) 程式碼(begin end) 異常(exception)
declare
cursor myc is select * from emp;--宣告遊標
myr emp%rowtype;
begin
open myc;--開啟遊標
--使用遊標:fetch (從遊標中提取一行)
loop
fetch myc intomyr;
exit when myc%notfound;
dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);
end loop;
close myc;
end;
--帶條件的遊標:列印2500以下的員工資訊
declare
cursor myc isselect * from emp where sal<2500;
myr emp%rowtype;
begin
open myc;
loop
fetch myc into myr;
exit when myc%notfound;
dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);
end loop;
close myc;
end;
--由使用者指定查詢的薪水:帶引數的遊標
declare
cursor myc(mysal number) is select * from emp wheresal<mysal;
myr emp%rowtype;
issalnumber(8,2);
begin
issal:=&請輸入;
open myc(issal);
loop
fetch myc into myr;
exit when myc%notfound;
dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);
end loop;
close myc;
end;
--for 循環遊標
declare
cursor myc(mysalnumber) is select * from emp where sal<mysal;
begin
for myr in myc(2500) loop
dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);
end loop;
end;
3.REF遊標
declare
type myc is ref cursor
return emp%rowtype;--有返回值表示它是強型別,無則是弱型別
mycd myc;
myr emp%rowtype;
begin
open mycd for select * from emp;
loop
fetch mycd into myr;
exit when mycd%notfound;
dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);
end loop;
close mycd;
end;
--動態ref
declare
type myc is refcursor;
myce myc;
myr emp%rowtype;
mysalnumber(7,2);
begin
mysal:=2500;
open myce for 'select * from emp where sal>:1' using mysal;--“:1”表預備的第一個引數,相當於JDBC中的預備語句的“?”
loop
fetch myce into myr;
exit when myce%notfound;
dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);
end loop;
close myce;
end;
三、同義詞、授權、序列、檢視、索引、
1.同義詞
--建立同義詞(需授權)
create or replacesynonym a for scott.emp;
--使用同義詞
select * from a;
--刪除同義詞
drop synonym a;--為什麼只刪除該同義詞的內容,此框架還存在,那應該怎麼刪除?
2、授權
--授權
grant create synonym to scott;
--收權
revoke create synonym from scott;
3.序列
--建立序列(它不能重複建立)
create sequence seq
start with 1
increment by 3
maxvalue 100
minvalue 1
cache 20;
create sequenceseq;--這也可以,預設為從1開始,每次加1;
--使用序列
select seq.nextvalfrom dual;
select seq.currvalfrom dual;
--刪除序列
drop sequence seq;
--修改序列裡的內容(不能修改其序列名,修改後也就不是此序列)
-- Alter sequence
alter sequence SEQ
minvalue 2
maxvalue 399
increment by 3;
-- Modify thelast number
alter sequenceSEQ increment by 2 nocache;
selectSEQ.nextval from dual;
alter sequenceSEQ increment by 3 cache 20;
4、檢視
--建立檢視(需授權)
檢視是一個虛表,資料表刪除了,但它還存在,只是不能執行,也就是說,檢視實際是一段select語句,它能保證資料的安全性。理論上檢視是可修改,但實際上不去修改,檢視可以巢狀檢視,但不能無窮巢狀。並且sqlserver 只能巢狀32層。
create or replace view v_emp as select * from emp;
--使用檢視
select * fromv_emp;
--刪除檢視
drop view v_emp;
5、索引(index)
索引:是資料庫內部編排資料的一種方法,兩個列可以建立同一個索引,稱為組合索引,表的每一個列都可以建立索引。索引依附於表存在,表刪除了,索引也沒了;能提高查詢速度,但會降低增、刪、改的速度。索引非常佔硬碟空間,若一個表裡有五個列,100萬行資料,有一個列加了索引,則硬碟除了儲存那原先的100萬行資料外,還要儲存100萬行索引資料,其中包含兩列,一個是主鍵,一個是建立索引的那個列,也就意味著,表裡每增加一個索引就會增加100萬行索引資料。
6.
nvl(condition,value);此方法:若condition為空,則值用value的值來填充。
五、儲存過程
儲存過程:是一段預先編譯好的儲存在資料庫裡一段SQL語句集。
其優點:模組化,安全性,減少網路的流通量
--建立儲存過程
create or replaceprocedure pname_1203(eno number)
as
myename varchar2(80);
mysal number(8,2);
begin
select ename,sal into myename,mysal fromemp where empno=eno
dbms_output.put_line('姓名'||myename||' 薪水為'||mysal);
end;
--使用儲存過程
begin
pname_1203(7369);
end;
過程引數的三種模式:
IN: 用於接受呼叫程式的值,預設的引數模式
OUT: 用於向呼叫程式返回值
IN OUT: 用於接受呼叫程式的值,並向呼叫程式返回更新的值
--out 型別表示該值是從儲存過程傳到外面去的
create or replace procedurepname_1203a(eno number,myjob out varchar2)
as
myename varchar2(50);
begin
select ename,job into myename,myjob fromemp where empno=eno;
dbms_output.put_line('姓名是'||myename);
end;
注意:oracle裡的子程式包括儲存過程與函式。
六、程式包(package)
--包頭的建立
create or replacepackage pname1203 is
procedure pr1203(eno number);
function fu1203(eno number)returnvarchar2;
end pname1203;
--包體的建立
create or replacepackage body pname1203 is
procedure pr1203(eno number)
is
myename varchar2(55);
begin
select ename into myename from emp whereempno=eno;
dbms_output.put_line('姓名是'||ename);
end pr1203;
function fu1203(eno number) return varchar2 is
myename varchar2(55);
begin
select ename into myename from emp whereempno=eno;
return myename||'hello';
end fu1203;
end pname1203;
--如何呼叫包裡面的東西
select pname1203.fu1203(7369)from dual;
七、觸發器
1.需記住的
(1).三種操作:delete update insert
(2).兩個臨時表: :new :old
:old表用來儲存要刪除時的資料,只有一行資料
:new表用來儲存要插入時的資料,只有一行資料
更新時需要:old and :new 兩個表都需要
(3).兩個時間點: after before
(4).兩種重要模式:行級 語句級(即表級)
(5).條件:when
2. --建立觸發器:學生資訊表中‘s25301'不能刪除、修改; 插入時,
-- 檢查名字叫'張洋洋'的不能新增 's25302'不能改
createor replace trigger t_stu
afterdelete or update or insert on stuinfo
for each row //這表示是行級觸發器,若沒寫,則為表級觸發器。
declaresno varchar2(40);
snamevarchar2(50);
begin
sno:=:old.stuno;
sname:=:new.stuname;
if deleting then
if sno='s25301' then
raise_application_error(-20009,'該學生不能動');//-20009是自定義錯誤,其自定義錯誤程式碼範圍:-20000至-21000.
end if;
elsif updating then
if sno='s25302' then
raise_application_error(-20004,'該學生不能動');
end if;
elsif inserting then
if sname='張洋洋'then
raise_application_error(-20006,'該學生不能要');
end if;
end if;
end;
3.在插入資料時自動插入序列號
create or replace trigger t_stua
beforeinsert on tb_study
for eachrow
begin
--:new.sid:=mys1208.nextval; //11g版本可使用
select mys1208.nextval into :new.sid from dual; //10g可使用
end;