1.1、輸出helloworld
SQL> set serveroutput on
SQL> BEGIN
2 DBMS_OUTPUT.put_line('HELLO');
3 END;
4 /
注意點(diǎn):執(zhí)行結(jié)束后并未顯示輸出的結(jié)果,默認(rèn)情況下,輸出的選項(xiàng)是關(guān)閉狀態(tài)的,我們需要開啟一下 set serveroutput on

1.2變量
PLSQL編程中常見的變量分兩大類:
1.普通數(shù)據(jù)類型(char,varchar2, date, number, boolean, long)
2.特殊量類型(引用型委量、記錄型交量)
聲明變量的方式為
1變量名變量類型(變量長度) 例如:v_name varchar2(202月
1.41普通變量
變量賦值的方式有兩種:
1.直接賦值語句 := eg: v_name :='zhang'
2.語句賦值,使用select ...into ...賦值: (語法select值tinto變量)
【示例】打印人員個(gè)人信息,包括:姓名、薪水、地址
--打印人員個(gè)人信息,包括:姓名、薪水、地址
DECLARE
--姓名
V_NAME VARCHAR2(20):='張三'; --聲明變量直接賦值--薪水
v_SAL NUMBER;--地址
V_ADDR VARCHAR2 (200);
BEGIN
--在程序中直接賦值
v_SAL :=1580;
--語句賦值
SELECT '昆明'INTO V_ADDR FROM DUAL;
--打印變量
DBMS_OUTPUT.PUT_LINE('姓名:'||V_NAME ||',薪水:'|| v_SAL ||',地址:'||V_ADDR);
END;


1.4.2.引用型變量
變量的類型的長度取決于表中字段的類型和長度
通過表名.列名%TYPE指定變量的類型和長度,例如: v_name emp.ename%TYPE;
【示例】查詢emp表中7839號(hào)員工的個(gè)人信息,打印姓名和薪水
--查詢emp表中7839號(hào)員工的個(gè)人信息,打印姓名和薪水
DECLARE
--姓名
V_NAME emp.ename%TYPE;--薪水
V_SAL emp.sal%TYPE;
BEGIN
SELECT ENAME,SAL INTO V_NAME,V_SAL FROM EMP WHERE pid = 1;--打印輸出
DBMS_OUTPUT.PUT_LINE('姓名:'|| V_NAME|| ',薪水:'|| V_SAL);
END;


引用型變量的好處:
使用普通變量定義方式,需要知道表中列的類型,而使朋用類型,不需要考慮列的類型,使用%TYPE是非常好的編程風(fēng)格,因?yàn)樗沟肞LSQL更加靈活,更加適應(yīng)于對(duì)數(shù)據(jù)庫定義的更新。
1.4.3.記錄型變量
接受表中的一整行記錄,相當(dāng)于Java中的一個(gè)對(duì)象
語法:變量名稱表名%ROWTYPE,例如: v_emp emp%rowtype;
--查詢emp表中7839號(hào)員工的個(gè)人信息,打印姓名和薪水
DECLARE
--姓名
V_EMP emp%ROWTYPE;--
BEGIN
SELECT * INTO V_EMP FROM EMP WHERE pid = 1;--打印輸出
DBMS_OUTPUT.PUT_LINE('姓名:'|| V_EMP.ename|| ',薪水:'||V_EMP.SAL);
END;
如果有一個(gè)表,有100個(gè)字段,那么你程序如果要使用這100字段話,如果你使用型變量一個(gè)個(gè)聲明,會(huì)特別麻煩,記錄型變量可以方便的解決這個(gè)問題
錯(cuò)誤的使用:
1.記錄型變量只能存儲(chǔ)個(gè)完整的行數(shù)據(jù)

2.返回的行太多了,記錄型變量也接收不了

1.5流程控制
1.5.1.條件分支
語法:
BEGIN
IF 條件1 THEN 執(zhí)行1
ELSIF 條件2 THEN 執(zhí)行2
ELSE 執(zhí)行3
END IF;
END;
--判斷emp表中數(shù)據(jù)的條數(shù)
DECLARE
-- 聲明變量 接收emp表中的記錄數(shù)
v_count number;
BEGIN
--查詢emp表中的記錄賦值給變量
SELECT count(1) INTO v_count FROM EMP;
--判斷打印
IF v_count > 20 THEN
DBMS_OUTPUT.PUT_LINE('EMP表的中數(shù)據(jù)大于了20條,條數(shù)為' || v_count);
ELSIF v_count >= 10 then
DBMS_OUTPUT.PUT_LINE('EMP表的中數(shù)據(jù)介于10-20之間,條數(shù)為' || v_count);
else
DBMS_OUTPUT.PUT_LINE('EMP表的中數(shù)據(jù)小于10條,條數(shù)為' || v_count);
end if;
END;
1.5.2.循環(huán)
在ORACLE中有三種循環(huán)方式,這里我們不展開,只介紹其中一種: loop循環(huán)
語法:
BEGIN
LOOP
EXIT WHEN 退出循環(huán)條件
END LOOP;
END;
--打印數(shù)字1-10
DECLARE
--聲明循環(huán)變量并賦值
v_num number :=1;
BEGIN
loop
exit when v_num>10;
DBMS_OUTPUT.put_line(V_NUM);
--循環(huán)變量自增
V_NUM:=V_NUM+1;
END LOOP;
END;
2.游標(biāo)
2.1.什么是游標(biāo)
用于臨時(shí)存儲(chǔ)一個(gè)查詢返回的多行數(shù)據(jù)(結(jié)果集,類似于Java的Jdbc連接返回的ResultSet集合),通過遍歷游標(biāo),可以逐行訪問處理該結(jié)果集的數(shù)據(jù)。
游標(biāo)的使用方式:聲明--->打開--->讀取--->關(guān)閉
2.2.語法
游標(biāo)聲明:
CURSOR游標(biāo)名[(參數(shù)列表)]IS查詢語句
游標(biāo)的打開:
OPEN 游標(biāo)名;
游標(biāo)的取值:
FETCH游標(biāo)名INTO變量列表;
游標(biāo)的關(guān)閉:
CLOSE游標(biāo)名;
2.3.游標(biāo)的屬性
| 游標(biāo)的屬性 | 返回值類型 | 說明 |
|---|---|---|
| %ROWcOUNT | 整型 | 獲得FETCH語句返回的數(shù)據(jù)行數(shù) |
| %FOUND | 布爾型 | 最近的FETCH語句返回一行數(shù)據(jù)則為真,否則為假 |
| %NOTFOUND | 布爾型 | 與%FOUND屬性返回值相反 |
| %ISOPEN | 布爾型 | 游標(biāo)已經(jīng)打開時(shí)值為真,否則為假 |
其中%NOTFOUND是在游標(biāo)中找不到元素的時(shí)候返回TRUE,通常用來判斷退出循環(huán)
2.4創(chuàng)建和使用
【示例】使用游標(biāo)查詢emp表中所有員工的姓名和工資,并將其依次打印出來
--使用游標(biāo)查詢emp表中所有員工的姓名和工資,并將其一次打印出來
DECLARE
--定義游標(biāo)
CURSOR C_EMP IS SELECT ename,sal FROM EMP;
--聲明變量用來接收游標(biāo)的數(shù)據(jù)
V_NAME EMP.ENAME%TYPE;
V_SAL EMP.SAL%TYPE;
BEGIN
--打開游標(biāo)
OPEN C_EMP;
LOOP
--通過 FETCH 語句獲取游標(biāo)中的值并賦給變量
FETCH C_EMP INTO V_NAME,V_SAL;
EXIT WHEN C_EMP%NOTFOUND;
DBMS_OUTPUT.put_line('姓名:'||v_name||',工資:'||v_sal);
end LOOP;
--關(guān)閉游標(biāo)
CLOSE C_EMP;
END;


2.5.帶參數(shù)的游標(biāo)
【示例】使用游標(biāo)查詢emp表中id為1的員工信息,編號(hào)為運(yùn)行時(shí)手動(dòng)輸入。
--使用游標(biāo)查詢emp表中id為1的員工信息
DECLARE
--定義游標(biāo)
CURSOR C_EMP(v_pid emp.pid%TYPE) IS SELECT ename,sal FROM EMP WHERE PID=V_PID;
--聲明變量用來接收游標(biāo)的數(shù)據(jù)
V_NAME EMP.ENAME%TYPE;
V_SAL EMP.SAL%TYPE;
BEGIN
--打開游標(biāo)
OPEN C_EMP(1);
LOOP
--通過 FETCH 語句獲取游標(biāo)中的值并賦給變量
FETCH C_EMP INTO V_NAME,V_SAL;
EXIT WHEN C_EMP%NOTFOUND;
DBMS_OUTPUT.put_line('姓名:'||v_name||',工資:'||v_sal);
end LOOP;
--關(guān)閉游標(biāo)
CLOSE C_EMP;
END;
注意:%NOTFOUND屬性默認(rèn)值為FLASE,所以在循環(huán)中要注意判斷條件的位.如果先判斷在FETCH會(huì)導(dǎo)致最后一條記錄的值被打印兩次(多循環(huán)一次默認(rèn));
3.存儲(chǔ)過程
3.1.概念作用
之前我們編寫的PLSQL程序可以進(jìn)行表的操作,判斷,循環(huán)邏輯處理的工作,但無法重復(fù)調(diào)用.
可以理解之前的代碼全都編寫在了main方法中,是匿名程序. JAVA可以通過封裝對(duì)象和方法來解決復(fù)用問題
PLSQL是將一個(gè)個(gè)PLSQL的業(yè)務(wù)處理過程存儲(chǔ)起來進(jìn)行復(fù)用,這些被存儲(chǔ)起來的PLSQL程序稱之為存儲(chǔ)過程
存儲(chǔ)過程作用:
1,在開發(fā)程序中,為了一個(gè)特定的業(yè)務(wù)功能,會(huì)向數(shù)據(jù)庫進(jìn)行多次連接關(guān)閉(連接和關(guān)閉是很耗費(fèi)資源)需要對(duì)數(shù)據(jù)庫進(jìn)行多次IO讀寫,性能比較低。如果把這些業(yè)務(wù)放到PLSQL中,在應(yīng)用程序中只需要調(diào)用PLSQL就可以做到連接關(guān)閉一次數(shù)據(jù)庫就可以實(shí)現(xiàn)我們的業(yè)務(wù),可以大大提高效率.
2,ORACLE官方給的建議:能夠讓數(shù)據(jù)庫操作的不要放在程序中。在數(shù)據(jù)庫中實(shí)現(xiàn)基本上不會(huì)出現(xiàn)錯(cuò)誤,在程序中操作可能會(huì)存在錯(cuò)誤.(如果在數(shù)據(jù)庫中操作數(shù)據(jù),可以有一定的日志恢復(fù)等功能.)
3.2.語法
CREATE OR REPLACE PROCEDURE 過程名稱[(參數(shù)列表)] IS
BEGIN
END[過程名稱];
根據(jù)參數(shù)的類型,我們將其分為3類講解:
不帶參數(shù)的
帶輸入?yún)?shù)的
帶輸入輸出參數(shù)(返回值)的。
3-3.無參存儲(chǔ)
3.3.1.創(chuàng)建存儲(chǔ)
通過Plsql Developer或者語句創(chuàng)建存儲(chǔ)過程:
新建一個(gè)Procedure
create or replace procedure P_HELLO is
begin
DBMS_OUTPUT.put_line('你妹的...');
end P_HELLO;

2、調(diào)用存儲(chǔ)過程
begin
--直接輸入存儲(chǔ)過程的名稱
p_hello;
p_hello;
p_hello;
p_hello;
end ;

sql 窗口執(zhí)行
set serveroutput on
create or replace procedure P_HELLO is
begin
DBMS_OUTPUT.put_line('你妹的...');
end P_HELLO;
--命苦窗口 通過exec 調(diào)用
exec p_hello //輸出

注意:
第一個(gè)問題:is和as是可以互用的,用哪個(gè)都沒關(guān)系的
第二個(gè)問題:過程中沒有declare關(guān)鍵字,declare用在語句塊中
3.4帶參數(shù)的存儲(chǔ)過程
--帶參數(shù)的存儲(chǔ)過程
create or replace procedure query_emp(i_empno in emp.pid%type) is
--聲明變量
v_name emp.ename%type;
v_sal emp.sal%type;
begin
select ename,sal into v_name,v_sal from emp where pid=i_empno;
DBMS_OUTPUT.put_line('姓名:'||v_name||',薪資:'||v_sal);
end ;
運(yùn)行
begin
query_emp(1);
end ;

sqlplus運(yùn)行
exec query_emp(1)

3.5帶輸出參數(shù)的存儲(chǔ)過程
--帶輸入輸出參數(shù)的存儲(chǔ)過程
create or replace procedure query_emp_out(i_empno in emp.pid%type, o_sal out emp.sal%type) is
begin
select sal into o_sal from emp where pid=i_empno;
end ;
運(yùn)行
declare
v_sal emp.sal%type;
begin
query_emp_out(1,v_sal);
DBMS_OUTPUT.put_line(V_SAL);
end;
java調(diào)用存儲(chǔ)過程
public static void main(String] args) throws Exception {
//1.加載驅(qū)動(dòng)
Class.forName("oracle.jdbc.driver. OracleDriver") ;
//2.獲取連接對(duì)象
String url = "jdbc:oracle:thin:Clocalhost:1521:xe";string user ="scott";
String password = "tiger";
Connection conn = DriverManager. getConnection(url,user,password);
//3.獲取語句對(duì)象
string sql = "{call p_querysal_out(?,?)}";//轉(zhuǎn)義語法, {call存儲(chǔ)過程(參數(shù)列表)}
Callablestatement call = conn.preparecall(sql);
1/4.設(shè)置輸入?yún)?shù)
call.setInt(1,7839);
//5.注冊(cè)輸出參數(shù)
call.registeroutParameter(2,oracleTypes.DOUBLE);
//6.執(zhí)行存儲(chǔ)過程
call.execute();
1/7.獲取輸出參數(shù)
double sal = call.getDouble(2);system.out.println("薪水:"+sal);
1/8.釋放資源
call.close();
conn.close();
}