第一篇:plsql教學(本站推薦)
1、一個簡單的程序 set serveroutput on;&符號的作用:提示用戶輸入 begin
dbms_output.put_line('HelloWorld!');end;/--執行語句
2、一個簡單的程序塊 declare
v_name varchar2(20);begin
v_name:='i am ynp';
dbms_output.put_line(v_name);end;
3、一個完整的簡單程序 declare
v_num number := 0;begin
v_num :=2/v_num;
dbms_output.put_line(v_num);exception
when others then
dbms_output.put_line('error');end;
----變量聲明的規則
1.變量名不能夠使用保留字,如from、select等 2.第一個字符必須是字母 3.變量名最多包含30個字符 4.不要與數據庫的表或者列同名 5.每一行只能聲明一個變量
------
4、變量聲明盡量以v_ 開頭
5、常用變量類型
binary_integer :整數,主要用來計數而不是用來表示字段類型 number :數字類型
char :定長字符串類型
v_empnos(-1):=12;
v_empnos(2):=111;
dbms_output.put_line(v_empnos(-1));end;
說明:table變量類型命名規則:type(自定義變量)-table(table類型變量)-emp(表emp)-empno(empno字段); 下標值可以為負值;
2、Record變量類型(類似于java中的類)declare type type_record_dept is record(deptno dept.deptno%type,dname dept.dname%type,loc dept.loc%type);
v_temp type_record_dept;begin
v_temp.deptno:=50;
v_temp.loc:='bj';
v_temp.dname:='aaa';
dbms_output.put_line(v_temp.deptno||' '||v_temp.dname);end;
但上述dept表變動時,此程序也得手動做相應改動,可以用下述方法自動改動:
使用%rowtype聲明record變量 declare
v_temp dept%rowtype;begin
v_temp.deptno:=50;
v_temp.loc:='bj';
v_temp.dname:='aaa';
dbms_output.put_line(v_temp.deptno||' '||v_temp.dname);end;
errcode := SQLCODE;--出錯代碼 errmsg := SQLERRM
--出錯信息
-----------------------------pl/sql中的sql語句----------------------
1、select語句
有且只有一條返回值,且必須加into 例子: declare
else
dbms_output.put_line('middle');
end if;--注意有這條語句 end;
5、while語句 declare
k binary_integer:=1;begin
while(k <11)loop
dbms_output.put_line(k);
k:=k+1;
end loop;end;
6、do..while語句 declare
k binary_integer:=1;begin
loop
dbms_output.put_line(k);
k:=k+1;
exit when(k>=11);
end loop;end;
7、for循環 declare
k binary_integer:=1;begin
for k in 1..10 loop
dbms_output.put_line(k);
end loop;end;
declare
k binary_integer:=1;begin
for k in reverse 1..10 loop--加上reverse為逆序打印
dbms_output.put_line(k);
end loop;end;
close c;end;
4、for循環(循環時最簡單)declare
cursor c is
select * from emp;begin
for v_emp in c loop
--不用定義v_emp,不用打開關閉游標了
dbms_output.put_line(v_emp.ename);
end loop;end;
5、帶參數的游標 declare
cursor c(v_deptno emp.deptno%type,v_job emp.job%type)is
select * from emp where deptno = v_deptno and job= v_job;begin
for v_emp in c(30,'CLERK')loop
dbms_output.put_line(v_emp.ename);
end loop;end;
6、可更新的游標
游標一般是作為記錄集讀取數據用的,但有時候用游標修改記錄,這就是可更新游標; declare
cursor c is
select * from emp2 for update;begin
for v_emp in c loop
if(v_emp.sal <2000)then
update emp2 set sal =sal+1 where current of c;--修改定位到的當前記錄,注意形式
elsif(v_emp.sal>=2000)then
delete from emp2 where current of c;
end if;
end loop;
commit;--提交 end;
-------------------------存儲過程--------------------
1、把過程的declare變成 create or Replace produce p is 就行。
end if;
v_d := v_d+1;end;
---> 調試時:
可以在命令窗口調試,出錯時 用show errors 顯示出錯信息; 可以在plDv中調試;
---> 運行時:
可以在命令窗口運行: declare
v_a number:=3;
v_b number:=4;
v_c number;
v_d number:=5;begin
p(v_a,v_b,v_c,v_d);
dbms_output.put_line(v_c);
dbms_output.put_line(v_d);end;可以在plDv中調試;
------------------函數-------------------
1、它有返回值
create or replace function tax_tag(sal number)return number--計算稅率 is begin
if(sal > 1000)then
return 0.1;
elsif(sal>=2000)then
return 0.15;
else
return 0.2;
end if;end;
select ename, tax_tag(sal)from emp ;--直接用函數tax_tag
------------------------觸發器(trigger)------------------------------1.create table emp2_log(insert into article values(10,'螞蟻是護士',9,1,3);
----------》存儲過程
create or replace procedure p(v_pid article.pid%type,v_level binary_integer)is
cursor c is select * from article where pid = v_pid;
v_perStr varchar2(2000):=' ';begin
for i in 1..v_level loop
v_perStr := v_perStr||'***';
end loop;
for v_article in c loop
dbms_output.put_line(v_perStr||v_article.cont);
if(v_article.isleaf = 0)then
p(v_article.id,v_level + 1);
end if;
end loop;end;
第二篇:PLSQL學習
----最簡單的塊
set serveroutput on
begin
dbms_output.put_line('Hello,World');
end;
----有定義和執行部分的塊
----把用戶的編號也顯示出來
declare
----定義變量
v_ename varchar2(20);
v_salnumber(7,2);
begin
select ename,salinto v_ename,v_sal from empwhere empno = &xy;----在控制臺顯示用戶名
dbms_output.put_line('用戶名' || v_ename || '薪水是 ' ||v_sal);----異常處理
exception
when no_data_found then
dbms_output.put_line('朋友,你輸入的編號有問題');
end;
CallableStatement 對象為所有的 DBMS 提供了一種以標準形式調用已儲存過程的方法。已儲存過程儲存在數據庫中。對已儲存過程的調用是 CallableStatement對象所含的內容。這種調用是用一種換碼語法來寫的,有兩種形式:一種形式帶結果參,另一種形式不帶結果參數。結果參數是一種輸出(OUT)參數,是已儲存過程的返回值。兩種形式都可帶有數量可變的輸入(IN 參數)、輸出(OUT 參數)或輸入和輸出(INOUT 參數)的參數。問號將用作參數的占位符。
在 JDBC 中調用已儲存過程的語法如下所示。注意,方括號表示其間的內容是可選項;方括號本身并不是語法的組成部份。
{call 過程名[(?, ?,...)]}
返回結果參數的過程的語法為:
{? = call 過程名[(?, ?,...)]}
不帶參數的已儲存過程的語法類似:
{call 過程名}
通常,創建 CallableStatement 對象的人應當知道所用的 DBMS 是支持已儲存過程的,并且知道這些過程都是些什么。然而,如果需要檢查,多種DatabaseMetaData 方法都可以提供這樣的信息。例如,如果 DBMS 支持已儲存過程的調用,則supportsStoredProcedures 方法將返回 true,而getProcedures 方法將返回對已儲存過程的描述。CallableStatement 繼承 Statement 的方法(它們用于處理一般的 SQL 語句),還繼承了 PreparedStatement 的方法(它們用于處理 IN 參)。
CallableStatement 中定義的所有方法都用于處理 OUT 參數或 INOUT 參數的輸出部分:注冊 OUT 參數的 JDBC 類型(一般 SQL 類型)、從這些參數中檢索結果,或者檢查所返回的值是否為 JDBC NULL。
1、創建 CallableStatement 對象
CallableStatement 對象是用 Connection 方法 prepareCall 創建的。下例創建 CallableStatement 的實例,其中含有對已儲存過程 getTestData 調用。該過程有兩個變量,但不含結果參數:
CallableStatement cstmt = con.prepareCall(“{call getTestData(?, ?)}”);
其中?占位符為IN、OUT還是INOUT參數,取決于已儲存過程getTestData。
2、IN和OUT參數
將IN參數傳給 CallableStatement 對象是通過 setXXX 方法完成的。該方法繼承自 PreparedStatement。所傳入參數的類型決定了所用的setXXX方法(例如,用 setFloat 來傳入 float 值等)。
如果已儲存過程返回 OUT 參數,則在執行 CallableStatement 對象以前必須先注冊每個 OUT 參數的 JDBC 類型(這是必需的,因為某些 DBMS 要求 JDBC 類型)。注冊 JDBC 類型是用 registerOutParameter 方法來完成的。語句執行完后,CallableStatement 的 getXXX 方法將取回參數值。正確的 getXXX 方法是為各參數所注冊的 JDBC 類型所對應的 Java 類型。換言之,registerOutParameter 使用的是 JDBC 類型(因此它與數據庫返回的 JDBC 類型匹配),而 getXXX 將之轉換為 Java 類型。
作為示例,下述代碼先注冊 OUT 參數,執行由 cstmt 所調用的已儲存過程,然后檢索在 OUT 參數中返回的值。方法 getByte 從第一個 OUT 參數中取出一個 Java 字節,而 getBigDecimal 從第二個 OUT 參數中取出一個 BigDecimal 對象(小數點后面帶三位數):
CallableStatement cstmt = con.prepareCall(“{call getTestData(?, ?)}”);
cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
cstmt.registerOutParameter(2, java.sql.Types.DECIMAL, 3);
cstmt.executeQuery();
byte x = cstmt.getByte(1);
java.math.BigDecimal n = cstmt.getBigDecimal(2, 3);
CallableStatement 與 ResultSet 不同,它不提供用增量方式檢索大 OUT 值的特殊機制。
3、INOUT參數
既支持輸入又接受輸出的參數(INOUT 參數)除了調用 registerOutParameter 方法外,還要求調用適當的 setXXX 方法(該方法是從 PreparedStatement 繼承來的)。setXXX 方法將參數值設置為輸入參數,而 registerOutParameter 方法將它的 JDBC 類型注冊為輸出參數。setXXX 方法提供一個 Java 值,而驅動程序先把這個值轉換為 JDBC 值,然后將它送到數據庫中。這種 IN 值的 JDBC 類型和提供給 registerOutParameter 方法的 JDBC 類型應該相同。然后,要檢索輸出值,就要用對應的 getXXX 方法。例如,Java 類型為byte 的參數應該使用方法 setByte 來賦輸入值。應該給registerOutParameter 提供類型為 TINYINT 的 JDBC 類型,同時應使用 getByte 來檢索輸出值。
下例假設有一個已儲存過程 reviseTotal,其唯一參數是 INOUT 參數。方法setByte 把此參數設為 25,驅動程序將把它作為 JDBC TINYINT 類型送到數據庫中。接著,registerOutParameter 將該參數注冊為 JDBC TINYINT。執行完該已儲存過程后,將返回一個新的 JDBC TINYINT 值。方法 getByte 將把這個新值作為 Java byte 類型檢索。
CallableStatement cstmt = con.prepareCall(“{call reviseTotal(?)}”);
cstmt.setByte(1, 25);
cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
cstmt.executeUpdate();
byte x = cstmt.getByte(1);
4、先檢索結果,再檢索 OUT 參數
由于某些 DBMS 的限制,為了實現最大的可移植性,建議先檢索由執行CallableStatement 對象所產生的結果,然后再用 CallableStatement.getXXX 方法來檢索 OUT 參數。如果 CallableStatement 對象返回多個 ResultSet 對象(通過調用 execute 方法),在檢索 OUT 參數前應先檢索所有的結果。這種情況下,為確保對所有的結果都進行了訪問,必須對 Statement 方法 getResultSet、getUpdateCount 和getMoreResults 進行調用,直到不再有結果為止。
檢索完所有的結果后,就可用 CallableStatement.getXXX 方法來檢索 OUT 參數中的值。
5、檢索作為OUT參數的NULL值
返回到 OUT 參數中的值可能會是JDBC NULL。當出現這種情形時,將對 JDBC NULL 值進行轉換以使 getXXX 方法所返回的值為 null、0 或 false,這取決于getXXX 方法類型。對于 ResultSet 對象,要知道0或false是否源于JDBCNULL的唯一方法,是用方法wasNull進行檢測。如果 getXXX 方法讀取的最后一個值是 JDBC NULL,則該方法返回 true,否則返回 flases
第三篇:PLSQL學習總結
PL/SQL集合批量綁定(Bulk binds)減少循環開銷PL/SQL引擎會執行過程化語句,但它把SQL語句傳送給SQL引擎處理,然后SQL引擎把處理的結果返回給PL/SQL引擎。
PL/SQL和SQL引擎間的頻繁切換會大大降低效率。典型的情況就是在一個循環中反復執行SQL語句。
批量綁定如何提高性能?
在SQL語句中為PL/SQL變量賦值稱為綁定,PL/SQL綁定操作分為三種:
1.內綁定(in-bind):用INSERT或UPDATE語句將PL/SQL發量或主變量保存到數據庫。
2.外綁定(out-bind):途過INSERT、UPDATE或DELETE語句的RETURNING子句返回值為PL/SQL變量或主變量賦值。
3.定義(define):使用SELECT或FETCH語句為PL/SQL變量或主變量賦值.DML語句可以一次性傳遞集合中所有的元素,這個過程就是批量綁定。如果集合有20個元素,批量綁定的一次操作就相當于執行20次SELECT、INSERT、UPDATE或DELETE語句。綁定技術是靠減少PL/SQL和SQL引擎間的切換次數來提高性能的。
批量綁定(Bulk binds)包括:
(i)Input collections, use the FORALL statement,一般用來改善DML(INSERT、UPDATE和DELETE)操作的性能
(ii)Output collections, use BULK COLLECT clause,一般用來提高查詢(SELECT)的性能
例一:對DELETE語句應用批量綁定
下面的DELETE語句只往SQL引擎中發送一次,即使是執行了三次DELETE操作: DECLARE
TYPE numlist IS VARRAY(20)OF NUMBER;
depts numlist := numlist(10, 30, 70);
BEGIN
FORALL i IN depts.FIRST..depts.LAST
DELETE FROM emp WHERE deptno = depts(i);
END;
當執行DELETE的數據數量非常大時,使用上述批量綁定方法能大大的提高運行效率。注意集合變長數組類型只能通過構造函數初始化,不能像索引表和嵌套表一樣通過FOR循環直接賦值,具體可見下例。
例二:對INSERT語句應用批量綁定
CREATE TABLE blktest(num NUMBER(20), name varchar2(50));
DECLARE
type numtab is table of number(20)INDEX by binary_integer;
type nametab is TABLE of VARCHAR2(20)INDEX by binary_integer;
pnums
numtab;
pnames
nametab;
t1
number;
t2
number;
t3
number;
begin
for j in 1..100000?為集合索引表變量循環賦值
loop
pnums(j):= j;
pnames(j):= 'Seq No' || to_char(j);
end loop;
select Dbms_Utility.get_time into t1 from dual;--獲得FOR運行前時間
for i in 1..100000?使用普通FOR循環插入10000條數據
loop
insert into blktest values(pnums(i),pnames(i));
end loop;
select dbms_utility.get_time into t2 FROM dual;獲得FOR運行后時間和FORALL運行前時間
forall i in 1..100000?使用FORALL循環即集合批量綁定方法插入10000條數據
insert into blktest values(pnums(i),pnames(i));
select dbms_utility.get_time
into t3 from dual;--獲得FORALL運行后時間
dbms_output.put_line('Execution Time(secs)');
dbms_output.put_line('------------------------');
dbms_output.put_line('FOR loop: ' || TO_CHAR(t2t2));
END;
運行結果:
Execution Time(secs)
------------------------
FOR loop: 982
FORALL loop: 49
總結:
1.在PL/SQL DEVELOPER的SQL WINDOWS中獲得數據庫當前時間的方法是:dbms_utility.get_time;如果需要測試某一段PLSQL的性能,則只需在開始和結束的時候分別獲取數據庫時間并做差即可,如上例中分別獲取兩種循環的耗時。
2.上例中,我們把10000個編號和名稱放到索引表中。所有的表元素都向數據庫插入兩次:第一次使用FOR循環,然后使用FORALL語句。實際上,FORALL版本的代碼執行速度要比FOR語句版本的快得多。
3.上述測試過程也可以通過在PL/SQL DEVELOPER的COMMAND WINDOWS中先編寫PROCEDURE再運行的方法實現。在COMMAND WINDOWS中設置顯示OUTPUT方法如下:
本文章未結束,請繼續查看 “PLSQL學習總結:批量綁定減少循環開銷--張凱(2)”
第四篇:Oracle之PLSQL總結
基本數據類型變量 1.基本數據類型
Number 數字型
Int 整數型
Pls_integer 整數型,產生溢出時出現錯誤
Binary_integer 整數型,表示帶符號的整數
Char 定長字符型,最大255個字符
Varchar2 變長字符型,最大2000個字符
Long 變長字符型,最長2GB
Date 日期型
Boolean 布爾型(TRUE、FALSE、NULL三者取一)
在PL/SQL中使用的數據類型和Oracle數據庫中使用的數據類型,有的含義是完全一致的,有的是有不同的含義的。
2.基本數據類型變量的定義方法
變量名 類型標識符 [not null]:=值;
declare
age number(3):=26;--長度為3,初始值為26
commit;
begin
end;
其中,定義常量的語法格式:常量名 constant 類型標識符 [not null]:=值;
declare
pi constant number(9):=3.1415926;--為pi的數字型常量,長度為9,初始值為3.1415926
begin
表達式
變量、常量經常需要組成各種表達式來進行運算,下面介紹在PL/SQL中常見表達式的運算規則。
1.數值表達式
PL/SQL程序中的數值表達式是由數值型常數、變量、函數和算術運算符組成的,可以使用的算術運算符包括+(加法)、-(減法)、*(乘法)、/(除法)和**(乘方)等。
命令窗口中執行下列PL/SQL程序,該程序定義了名為result的整數型變量,計算的是10+3*4-20+5**2的值,理論結果應該是27。
set serveroutput on
Declare
result integer;
result:=10+3*4-20+5**2;
begin
commit;
end;dbms_output.put_line('運算結果是:'||to_char(result));
end;
dbms_output.put_line函數輸出只能是字符串,因此利用to_char函數將數值型結果轉換為字符型。
2.字符表達式
字符表達式由字符型常數、變量、函數和字符運算符組成,唯一可以使用的字符運算符就是連接運算符“||”。
3.關系表達式
關系表達式由字符表達式或數值表達式與關系運算符組成,可以使用的關系運算符包括以下9種。
4.邏輯表達式
邏輯表達式由邏輯常數、變量、函數和邏輯運算符組成,常見的邏輯運算符包括以下3種。
PLSQL函數
PL/SQL程序中提供了很多函數供擴展功能,除了標準SQL語言的函數可以使用外,最常見的數據類型轉換函數有以下3個。
系統輸出打印
利用pl/sql在數據庫服務器端打印一句話:
set serveroutput on--設置數據庫輸出,默認為關閉,每次重新打開窗口需要重新設置。
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello PL/SQL');
END;To_char:將其他類型數據轉換為字符型。
To_date:將其他類型數據轉換為日期型。
To_number:將其他類型數據轉換為數值型。
繼續追加中..NOT:邏輯非
OR:邏輯或
AND:邏輯與
運算的優先次序為NOT、AND和OR。< 小于
> 大于
= 等于(不是賦值運算符:=)
like 類似于
in 在??之中
<= 小于等于
>= 大于等于
!= 不等于 或<>
between 在??之間
關系型表達式運算符兩邊的表達式的數據類型必須一致。
pl/sql程序中對大小寫不敏感(打印聲明的變量)
set serveroutput on
DECLARE
pl語句塊是pl/sql里最小的編程塊,其中可以再嵌套 PL/SQL中的變量聲明
所有變量必須在declare中聲明,程序中不允許聲明。沒有初始化的變量默認值為null,屏幕上null是看不見的,命名習慣:PL/SQL中變量一般以v_開頭(等同于存儲過程中as和begin區域的變量定義習慣)。
注意number也能存小數,最長38位,所以以后建議整數都用binary_integer存。
long是字符類型,boolean類型不能打印。
標準變量類型:數字,字符,時間,布爾。
declare
v_number1 number;v_number2 number(3,2);v_number3 binary_integer :=1;v_name varchar2(20):='kettas';v_date date :=sysdate;v_long long :='ni hao';v_b boolean := true;
if(v_number1 is null)then dbms_output.put_line('hello');end if;
dbms_output.put_line(v_number1);dbms_output.put_line(v_number2);dbms_output.put_line(v_number3);dbms_output.put_line(v_name);dbms_output.put_line(v_date);dbms_output.put_line(v_long);
--dbms_output.put_line(v_b);--執行該句ORACLE提示“調用 'PUT_LINE' 時參數v_char varchar2(20):='a';
v_char1 varchar2(20):='b';
DBMS_OUTPUT.PUT_LINE(v_char);
DBMS_OUTPUT.PUT_LINE(v_char1);
BEGIN
END;begin
個數或類型錯誤”
end;
備注:關于聲明number(4,3)中括號中的兩個數字的意義,前面的數字叫精度,后面的叫刻度。刻度:當刻度為正數的時候,表示四舍五入到小數點后面的位數,當刻度為負數的時候,表示四舍五入到小數點前面的位數
精度:從數字的最前面不為零開始到刻度精確到的位置
―――――――――――――――――――――――――――――――――――――
v_Number number(4,3):=123.12312
1、按刻度進行四舍五入得到123.123
2、確定刻度精確到的位置123123處,精度為6位(.符號不算)
3、根據精度進行判斷6位(>4)精度上限值
--報錯不能存儲
―――――――――――――――――――――――――――――――――――――
number(3,-3):=44445
1、根據刻度-3進行四舍五入得到44000
2、小數點向前移動3位44.此位置為刻度精確到的位置
3、根據精度進行判斷2位(<3)精度上限值
--不報錯可存儲結果為44000
DECLARE
v_Number number(4,3):=123.12312;--實際精度6位大于上限精度值4位,提示“ORA-06502: PL/SQL: 數字或值錯誤 : 數值精度太高”
BEGIN
DECLARE
v_Number number(7,3):=4555;--實際精度7位等于上限精度值,可以存儲
DBMS_OUTPUT.PUT_LINE(v_Number);
BEGIN
END
;
―――――――――――――――――――――――――――――――――――――
變量賦值方式
oracle中變量賦值方式是值拷貝而非引用
declare
v_number1 number:=100;
v_number2 number;
v_number2:=v_number1;
v_number1:=200;
dbms_output.put_line(v_number1);--200
dbms_output.put_line(v_number2);--100
DBMS_OUTPUT.PUT_LINE(v_Number);
END
;
begin
end;
―――――――――――――――――――――――――――――――――――――
PLSQL復合類型
記錄類型record
record類型最常用,聲明的時候可以加not null,但必須給初始值,如果record類型一致可以相互賦值,如果類型不同,里面的字段恰好相同,不能互相賦值。
引用記錄型變量的方法是“記錄變量名.基本類型變量名”。
declare
type t_first is record(id number(3),name varchar2(20));
v_first t_first;
begin
v_first.id:=1;
v_first.name:='cheng';
dbms_output.put_line(v_first.id);
dbms_output.put_line(v_first.name);
end;―――――――――――――――――――――――――――――――――――――
record類型變量間賦值
declare
type t_first is record(id number,name varchar2(20));
v_first t_first;
v_second t_first;
v_first.id:=1;
v_first.name:='susu';
v_second:=v_first;--相互賦值
v_first.id:=2;
v_first.name:='kettas';
dbms_output.put_line(v_first.id);
dbms_output.put_line(v_first.name);
dbms_output.put_line(v_second.id);
dbms_output.put_line(v_second.name);
begin
end;
―――――――――――――――――――――――――――――――――――――
表類型變量table 語法如下:
type 表類型 is table of 類型 index by binary_integer;
表變量名 表類型;
類型可以是前面的類型定義,index by binary_integer子句代表以符號整數為索引,這樣訪問表類型變量中的數據方法就是“表變量名(索引符號整數)”。
table類型,相當于java中的Map容器,就是一個可變長的數組,key(符號整數索引)必須是整數,可以是負數,value(類型)可以是標量,也可以是record類型??梢圆话错樞蛸x值,但必須先賦值后使用。
――――――――――――――――――――――――――――――――――――― 1.定義一維表類型變量
declare
type t_tb is table of varchar2(20)index by binary_integer;
v_tb t_tb;
v_tb(100):='hello';
v_tb(98):='world';
dbms_output.put_line(v_tb(100));
dbms_output.put_line(v_tb(98));
begin
end;
類型為record的表類型變量
――――――――――――――――――――――――――――――――――――― declare
type t_rd is record(id number,name varchar2(20));
type t_tb is table of t_rd index by binary_integer;
v_tb2 t_tb;
v_tb2(100).id:=1;
v_tb2(100).name:='hello';
--dbms_output.put_line(v_tb2(100).id);
--dbms_output.put_line(v_tb2(100).name);
dbms_output.put_line(v_tb2(100).id||''||v_tb2(100).name);
begin
end;
――――――――――――――――――――――――――――――――――――
2.定義多維表類型變量
該程序定義了名為tabletype1的多維表類型,相當于多維數組,table1是多維表類型變量,將數據表tempuser.testtable中recordnumber為60的記錄提取出來存放在table1中并顯示。
declare
type tabletype1 is table of testtable%rowtype index by binary_integer;
table1 tabletype1;
select * into table1(60)from tempuser.testtable where recordnumber=60;
dbms_output.put_line(table1(60).recordnumber||table1(60).currentdate);
begin
end;
備注:在定義好的表類型變量里,可以使用count、delete、first、last、next、exists和prior等屬性進行操作,使用方法為“表變量名.屬性”,返回的是數字。
set serveroutput on
declare
type tabletype1 is table of varchar2(9)index by binary_integer;
table1 tabletype1;
table1(1):='成都市';
table1(2):='北京市';
table1(3):='青島市';
dbms_output.put_line('總記錄數:'||to_char(table1.count));
dbms_output.put_line('第一條記錄:'||table1.first);
dbms_output.put_line('最后條記錄:'||table1.last);
dbms_output.put_line('第二條的前一條記錄:'||table1.prior(2));
dbms_output.put_line('第二條的后一條記錄:'||table1.next(2));
begin
end;
――――――――――――――――――――――――――――――――――――― %type和%rowtype
使用%type定義變量,為了讓PL/SQL中變量的類型和數據表中的字段的數據類型一致,Oracle 9i提供了%type定義方法。
這樣當數據表的字段類型修改后,PL/SQL程序中相應變量的類型也自動修改。
―――――――――――――――――――――――――――――――――――――
create table student(id number, name varchar2(20),age number(3,0));insert into student(id,name,age)values(1,'susu',23);
查找一個字段的變量 declare
查找多個字段的變量
declare
查找一個類型的變量,推薦用* declare
也可以按字段查找,但是字段順序必須一樣,不推薦這樣做
declare
v_student student%rowtype;
select id,name,age into v_student from student where rownum=1;
dbms_output.put_line(v_student.id||''||v_student.name||''||v_student.age);
begin
v_student student%rowtype;
select * into v_student from student where rownum=1;
dbms_output.put_line(v_student.id||''||v_student.name||' '||v_student.age);
begin
v_id student.id%type;
v_name student.name%type;
v_age student.age%type;
select id,name,age into v_id,v_name,v_age from student where rownum=1;
dbms_output.put_line(v_id||' '||v_name||' '||v_age);
v_name varchar2(20);
v_name2 student.name%type;
select name
into
v_name2
from
student
where
rownum=1;
begin
dbms_output.put_line(v_name2);
end;begin
end;end;end;
declare
備注:insert,update,delete,select都可以,create table,drop table不行。DPL,DML,和流程控制語句可以在pl/sql里用,但DDL語句不行。
declare
v_name student.name%type:='wang';
insert into student(id,name,age)values(2,v_name,26);
begin
end;
begin
declare
v_name student.name%type:='hexian';
update student set name=v_name where id=1;
begin
end;
begin
update student set name='qinaide' where id=2;
end;
―――――――――――――――――――――――――――――――――――――
PLSQL變量的可見空間
變量的作用域和可見性,變量的作用域為變量申明開始到當前語句塊結束。
當外部過程和內嵌過程定義了相同名字的變量的時候,在內嵌過程中如果直接寫這個變量名是沒有辦法訪問外部過程的變量的,可以通過給外部過程定義一個名字<
declare
v_i1 binary_inteer:=1;
begin
declare
v_i2 binary_integer:=2;
begin
insert into student(id,name,age)values(5,'hehe',25);
end;v_student student%rowtype;
select id,name,age into v_student.id,v_student.name,v_student.age from--select * into v_student.id,v_student.name,v_student.age from student dbms_output.put_line();
begin
student where id=1;
where id=1;
end;
dbms_output.put_line(v_i1);
dbms_output.put_line(v_i2);
dbms_output.put_line(v_i1);
--dbms_output.put_line(v_i2);解開后執行Oracle會提示“必須說明標識符 'V_I2'”
end;
end;
―――――――――――――――――――――――――――――――――――――
PLSQL流程控制
if判斷
declare
if else判斷
declare
if elsif else判斷
declare
v_name varchar2(20):='cheng';
if v_name='0701' then dbms_output.put_line('0701');
elsif v_name='cheng' then dbms_output.put_line('cheng');
else dbms_output.put_line('false');
end if;begin
v_b boolean:=true;
if v_b then dbms_output.put_line('ok');
else dbms_output.put_line('false');
end if;begin
v_b boolean:=true;
if v_b then dbms_output.put_line('ok');end if;begin end;end;end;――――――――――――――――――――――――――――――――――――― loop循環,注意推出exit是推出循環,而不是推出整個代碼塊
declare
v_i binary_integer:=0;loop
if v_i>10 then exit;end if;
v_i:=v_i+1;
begin
dbms_output.put_line('hehe');
end loop;
dbms_output.put_line('over');
end;loop簡化寫法
declare
while循環
declare
for循環,注意不需要聲明變量
begin
for v_i in 0..10 loop
dbms_output.put_line('hello'||v_i);
end loop;
dbms_output.put_line('over');v_i binary_integer:=0;while v_i<10 loop
dbms_output.put_line('hello'||v_i);
v_i:=v_i+1;
end loop;
dbms_output.put_line('over');begin
v_i binary_integer :=0;loop
exit when v_i>10;
v_i :=v_i+1;
dbms_output.put_line('hehe');
end loop;
dbms_output.put_line('over');begin
end;end;end;―――――――――――――――――――――――――――――――――――――
PLSQL異常處理
1、聲明異常
異常名 EXCEPTION;
2、拋出異常
RAISE 異常名
3、處理異常
拋出異常后的邏輯代碼不會被繼續執行
異常的定義使用 begin
dbms_output.put_line(1/0);
exception when others then dbms_output.put_line('error');
end;declare
e_myException exception;
dbms_output.put_line('hello');
raise e_myException;
--raise拋出異常,用此關鍵字,拋出后轉到自定義的e_myException,執行其里面的--再跳到end處,結束PL/SQL塊,raise接下面的2句不會繼續執行。dbms_output.put_line('world');
dbms_output.put_line(1/0);
exception when e_myException then dbms_output.put_line(sqlcode);dbms_output.put_line(sqlerrm);--當前錯誤信息
dbms_output.put_line('my error');
when others then dbms_output.put_line('error');
begin
putline函數后,--當前會話執行狀態,錯誤編碼
end;
―――――――――――――――――――――――――――――――――――――
PLSQL游標和goto語句
備注:下面提到的游標為靜態cursor,包括顯示和隱式。
游標,從declare、open、fetch、close是一個完整的生命旅程。當然了一個這樣的游標是可以被多次open進行使用的,顯式cursor是靜態cursor,她的作用域是全局的,但也必須明白,靜態cursor也只有pl/sql代碼才可以使用它。
靜態游標變量是在定義時就必須指定SQL語句。
cursor 游標(結果集)用于提取多行數據,定義后不會有數據,使用后才有。一旦游標被打開,就無法再次打開(可以先關閉,再打開)。
declare
第二種游標的定義方式,用變量控制結果集的數量。
declare
cursor c_student is select * from book;
open c_student;
close c_student;
begin
end;v_id binary_integer;
cursor c_student is select * from book where id>v_id;
v_id:=10;
begin
第三種游標的定義方式,帶參數的游標,用的最多。
declare
cursor c_student(v_id binary_integer)is select * from book where id>v_id;
open c_student(10);
游標的使用,一定別忘了關游標。
declare
如何遍歷游標fetch
游標的屬性 %found,%notfound,%isopen,%rowcount。
%found:若前面的fetch語句返回一行數據,則%found返回true,如果對未打開的游標使用則報ORA-1001異常。
%notfound,與%found行為相反。
%isopen,判斷游標是否打開。
%rowcount:當前游標的指針位移量,到目前位置游標所檢索的數據行的個數,若未打開就引用,返回ORA-1001。
注: no_data_found和%notfound的用法是有區別的,小結如下
1)SELECT...INTO 語句觸發 no_data_found;
2)當一個顯式光標(靜態和動態)的 where 子句未找到時觸發 %notfound;
3)當UPDATE或DELETE 語句的where 子句未找到時觸發 sql%notfound;
4)在光標的提取(Fetch)循環中要用 %notfound 或%found 來確定循環的退出條件,不要用no_data_found。下面是幾個實例:
create table BOOK(ID VARCHAR2(10)not null,BOOKNAME VARCHAR2(10)not null,v_student book%rowtype;
cursor c_student(v_id binary_integer)is select * from book where id>v_id;
open c_student(10);fetch c_student into v_student;
close c_student;
dbms_output.put_line(v_student.name);
close c_student;
end;begin
open c_student;
close c_student;
end;begin
end;
PRICE
VARCHAR2(10)not null,CID
VARCHAR2(10)not null);--insert create or replace procedure say_hello(i_name in varchar2, o_result_msg out varchar2)as
v_price varchar2(100);
e_myException exception;begin
--update or delete create or replace procedure say_hello(i_name in varchar2, o_result_msg out varchar2)as v_price varchar2(100);
e_myException exception;
begin
--select create or replace procedure say_hello(i_name in varchar2, o_result_msg out varchar2)as
v_price varchar2(100);
e_myException exception;begin
--loop方式遍歷游標
declare
v_bookname varchar2(100);
cursor c_book(i_id number)is select bookname from book where id = i_id;
select price into v_price from book where bookname = i_name;
o_result_msg := 'success';
exception when no_data_found then rollback;
o_result_msg := 'select into dail';
update book set price = '55' where bookname = i_name;
delete from book where bookname = i_name;
if sql%notfound then raise e_myException;
end if;
/* if sql%rowcount = 0 then--寫法2 raise e_myException;end if;*/
o_result_msg := 'success';
exception when e_myException then rollback;
o_result_msg := 'update or delete dail';
insert into book(id,bookname,price)values(1,2,3);
o_result_msg := 'success';
exception when others then rollback;
o_result_msg := substr(sqlerrm, 1, 200);
end;end;end;begin
或
declare
while循環遍歷游標,注意,第一次游標剛打開就fetch,%found為null,進不去循環
解決方法:
while nvl(c_student%found,true)loop
declare
for循環遍歷,最簡單,用的最多,不需要聲明v_student,Open和Close游標和fetch操作(不用打開游標和關閉游標,實現遍歷游標最高效方式)
declare
v_bookname varchar2(100);
cursor c_book(i_id number)is select bookname from book where id = i_id;
Open c_book(i_id);
while nvl(c_book%found,true)
--或這種寫法:while c_book%found is null or c_book%found loop Fetch c_book
update book set price = '33' where bookname = v_bookname;
End Loop;
Close c_book;
v_bookname varchar2(100);
cursor c_book(i_id number)is select bookname from book where id = i_id;
Open c_book(i_id);
Fetch c_book into v_bookname;
While c_book%Found Loop
update book set price = '33' where bookname = v_bookname;
Fetch c_book into v_bookname;
End Loop;
Close c_book;
Open c_book(i_id);
Loop
Fetch c_book into v_bookname;
exit when c_student%notfound;
update book set price = '33' where bookname = v_bookname;
End Loop;
Close c_book;
end;
begin
end;
begin
into v_bookname;
end;
cursor c_book(i_id number)is select bookname from book where id = i_id;
for cur in c_book(i_id)--直接將入參i_id傳入cursor即可
loop
update book set price = '53' where bookname = cur.bookname;
end loop;
begin
end;goto例子,一般不推薦使用goto,會使程序結構變亂
declare
Oracle存儲過程
在談存儲過程書寫中的一些規則時,先看一下執行它的規則,在命令窗口執行存儲過程sp_get_product_prompt set serveroutput on
var ret1 varchar2(200);
var ret2 varchar2(200);
exec sp_get_product_prompt(83,:ret1,:ret2);--或execute print ret1;print ret2;或
set serveroutput on
declare
ret1 varchar2(200);
ret2 varchar2(200);
sp_get_product_prompt(83,ret1,ret2);
dbms_output.put_line(ret1);
i number:=0;
if i=0 then
goto hello;
end if;
<
begin
dbms_output.put_line('hello');
goto over;
begin
end;
<
begin
dbms_output.put_line('world');
goto over;
end;
<
dbms_output.put_line('over');
end;begin
dbms_output.put_line(ret2);
end;存儲過程入參,不論類型,缺省情況下值都為null,入參和出參不能有長度,其中關鍵字as可以替換成is,存儲過程中變量聲明在as和begin之間,同時,存儲過程中可以再調用其它的存儲過程,如果要保證存儲過程之間的事務處理不受影響,可以定義為自治事務。
create or replace procedure say_hello(v_name in varchar2, v_flag number, o_ret out number)as
begin
對于入參為null情況下給予缺省值
create or replace procedure say_hello(i_name in varchar2, i_flag number, o_ret out number)
as
或直接在insert語句中調用nvl函數賦缺省值
insert into phone(..,wname..,)values(..,nvl(v_name,' '),..);----如果將' '寫成'',則insert進來的v_name值還是為''等價于null值
帶一個參數的存儲過程
輸入參數in,輸入參數不能進行:=賦值,但可以將它賦給as后面定義的變量;
輸入參數in,可以作為變量進行條件判斷;默認不寫就是in; 存儲過程沒有重載,這個有參的say_hello會替代已經存在的無參say_hello。
create or replace procedure say_hello(v_name in varchar2)
as
begin
--v_name:='a';--存儲過程入參v_name不能做為賦值目標
dbms_output.put_line('hello '||v_name);
v_name varchar2(100);
if i_name is null then v_name := '0';
else
v_name := i_name;
end if;
insert into phone(..,wname..,)values(..,v_name,..);
begin
if v_name is null and v_flag is null then--v_name和v_flag都等于null
o_ret := 10;
else
o_ret := 100;
end if;
end;end;end;
存儲過程輸入參數作為變量進行條件判斷
create or replace procedure say_hello(i_opFlag in number)
as
利用存儲過程中定義的變量對入參的空值處理:
create or replace procedure say_hello(i_name in varchar2)
as
多個參數的存儲過程
create or replace procedure say_hello(v_first_name in varchar2, v_last_name in varchar2)
as
begin
out輸出參數,用于利用存儲過程給一個或多個變量賦值,類似于返回值
create or replace procedure say_hello(v_name in varchar2,v_content out varchar2)begin
調用:
declare
v_con varchar2(200);
v_in varchar2(20):='wang';
v_content:='hello'||v_name;
end;dbms_output.put_line('hello '||v_first_name||'.'||v_last_name);
end;v_name varchar2(100);
if i_name is null then v_name :='0';
else v_name :=i_name;--將入賦值給定義變量
end if;
dbms_output.put_line('hello '||v_name);
begin
v_name varchar2(100);
if i_opFlag = 1 then
v_name :='0';
else
v_name :='haha';
end if;
dbms_output.put_line('hello '||v_name);
begin
end;end;begin
in out參數,既賦值又取值
create or replace procedure say_hello(v_name in out varchar2)
as
begin
v_name:='hi '||v_name;
end;調用:
declare
對存儲過程入參賦缺省值
create or replace procedure say_hello(v_name varchar2 default 'susu', v_content varchar2 default 'hello')
as
begin
調用:(用指明形參名的方式調用更好)
begin
say_hello();
end;
或
begin
say_hello('cheng');
end;
或
begin
PLSQL中的function FUNCTION和PROCEDURE的區別
1、函數有返回值,過程沒有
2、函數調用在一個表達式中,過程則是作為pl/sql程序的一個語句
say_hello(v_name=>'cheng');
end;dbms_output.put_line(v_name||' '||v_content);
end;v_inout varchar2(20):='wangsu';
say_hello(v_inout);
dbms_output.put_line(v_inout);
begin
say_hello(v_in,v_con);
dbms_output.put_line(v_con);
end;end;
過程和函數都以編譯后的形式存放在數據庫中,函數可以沒有參數也可以有多個參數并有一個返回值。
過程有零個或多個參數,沒有返回值。函數和過程都可以通過參數列表接收或返回零個或多個值,函數和過程的主要區別不在于返回值,而在于他們的調用方式,過程是作為一個獨立執行語句調用的,函數以合法的表達式的方式調用
create or replace function func(v_name in varchar2)return varchar2
is begin
return(v_name||' hello');
end;
調用:
declare
v_name varchar2(20);
begin
v_name:=func('cheng');
dbms_output.put_line(v_name);
end;
帶out參數的函數
create or replace function func(v_name in varchar2, v_content out varchar2 return varchar2
is
begin
v_content:=v_name||' hello';
return v_content;
end;
調用:
declare
v_name varchar2(20);
v_name1 varchar2(20);
begin
v_name1:=func('susu',v_name);--返回v_name值
dbms_output.put_line(v_name1);--打印func結果
dbms_output.put_line(v_name);--打印v_name結果
end;帶in out 參數的函數
create or replace function func(v_name in out varchar2)return varchar2
is
begin
v_name:=v_name||' hello';
return 'cheng';)
end;調用:
declare
v_inout varchar2(20):='world';
v_ret varchar2(20);
v_ret:=func(v_inout);--返回調用v_inout值(作為出參)
dbms_output.put_line(v_ret);--打印func結果
dbms_output.put_line(v_inout);--返回v_name結果
begin
end;
第五篇:Oracle使用工具plsql遠程連接問題
使用PL/SQL Developer遠程連接Oracle數據庫,本地機器上已經安裝了Oracle數據庫只要
1.配置tnsnames.ora(我的安裝在D:oracleproduct10.2.0db_1networkADMIN)
2.登錄plsql時填寫相應信息
第一步:配置tnsnames.ora
找到tnsnames.ora文件,用記事本方式打開,你可以看到像如下配置信息
ORCL =
(DESCRIPTION =
(ADDRESS =(PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl)))
上面這段是連接本地(安裝好Oracle默認的,你也可以修改數據庫別名,將“ORCL”換成其他的)的數據庫的要連接遠程的Oracle數據庫則再增加配置信息如下
自己定義遠程數據庫名稱(別名)=
(DESCRIPTION =
(ADDRESS =(PROTOCOL = TCP)(HOST = 遠程服務器IP)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = 遠程服務器上數據庫名稱)))
注意:別名不能與其他數據庫(本地、遠程)的別名相同,它可以跟相應遠程服務器上的數據庫名稱不一樣,要連接多個遠程Oracle數據庫,照樣子在來幾段上述配置信息即可。
第二步:登錄plsql
Username:
Password:
Database:要登錄的數據庫名稱(別名)
Connect as:
注意:一定要寫對上面面的紅色部分(其余的3個字段我就不說了),且跟tnsnames.ora配置文件中的別名相同
知道這兩步后,以后不管是遠程還是本地上的數據庫你想怎么連就怎么連!只是tnsnames.ora文件中多了幾段配置信息。