Oracle之plsql及遊標
一、賦值
–:= 賦值
declare
var_name varchar2(10) :=’&請輸入名字’;–&是一個提示輸入的特殊符號,會開啟一個輸入框
var_age number(3) :=’&請輸入年齡’;
begin
dbms_output.put_line(var_name||’—’||var_age);–輸入 ||是連線符號和java中的+一樣
end;
--into 賦值 declare var_name varchar2(10); var_age number(3); begin select stuname,age into var_name,var_age from t_student where id = 2; dbms_output.put_line(var_name||'---'||var_age); end;
二、 特殊型別:
–%type 繫結某個表中的特定欄位的型別
declare
v_name emp.ename%type;
v_job emp.job%type;
begin
select ename,job into v_name,v_job from emp where emp.empno=3;
dbms_output.put_line(v_name||’—’||v_job);
end;
–%rowtype:行型別和表中的一行對應
declare
v_emp emp%rowtype; – v_emp的型別是一個行型別 和emp的一條記錄對應
begin
select * into v_emp from emp where empno=1;
dbms_output.put_line(v_emp.ename||’ ‘||v_emp.sal||’ ‘||v_emp.job);
end;
三、if條件判斷
if語句
語法格式: if 條件 then
[ elsif 條件 then ]
[ elsif 條件 then]
[else ]
end if;
--例項
declare
v_age number(3) :=&請輸入年齡;
begin
if v_age = 18 then
dbms_output.put_line('18');
elsif v_age > 18 then
dbms_output.put_line('大於18');
else dbms_output.put_line('小於18');
end if;
end;
四、case
case when 條件 then
when 條件 then
else
end case;
--例項
declare
v_age number(3) :=&請輸入年齡;
begin
case
when v_age = 18 then dbms_output.put_line('18');--條件可以是一個定值也可以是>或者<
when v_age = 19 then dbms_output.put_line('19');
when v_age = 20 then dbms_output.put_line('20');
when v_age = 21 then dbms_output.put_line('21');
when v_age = 22 then dbms_output.put_line('22');
when v_age > 23 then dbms_output.put_line('大於23');
else dbms_output.put_line('不知道');
end case;
end;
五、迴圈
–5、1無限迴圈
loop
– 迴圈體
exit when 退出條件;
end loop;
--例項
declare
v_num number(3) := 1;
begin
loop
dbms_output.put_line(v_num);
v_num := v_num+1;
exit when v_num > 10;
end loop;
end;
--5、2 while帶條件的迴圈
while 迴圈條件 loop
--迴圈體
end loop;
--例項
declare
v_i number(5) := 1;
begin
while v_i<10 loop
dbms_output.put_line(v_i);
v_i := v_i+1;
end loop;
end;
--5/3 for迴圈:
--1.不用專門去宣告迴圈變數
--2.每次只能自增一,
--3.要想實現迴圈降序需要在 in 後加 reverse
--例項
declare
begin
for v_i in reverse 1..9 loop
dbms_output.put_line(v_i);
end loop;
end;
六、goto關鍵字:跳轉到指定的位置
--例項:
declare
v_num number(5) := &請輸入;
begin
if v_num = 18 then
dbms_output.put_line(18);
goto a1;
elsif v_num = 20 then
dbms_output.put_line(20);
goto a2;
else dbms_output.put_line('----------');
goto a3;
end if;
<<a1>>
dbms_output.put_line('a1======');
<<a2>>
dbms_output.put_line('a2======');
<<a3>>
dbms_output.put_line('a3======');
end;
七、動態SQL語句:解決的是字串格式的sql語句執行的問題
EXECUTE IMMEDIATE dynamic_sql_string
[INTO define_variable_list]
[USING bind_argument_list];
declare
v_stuname t_student.stuname%type;
v_sql varchar2(100) := 'select stuname from t_student where id = :id';
v_id number(3) := &請輸入查詢的id;
begin
execute immediate v_sql into v_stuname using v_id;
dbms_output.put_line(v_stuname);
end;
八、異常處理
–8、1 系統異常
no_data_found;沒有找到資料的異常
too_many_rows: 多行資料
others 其他異常
declare
v_stuname t_student.stuname%type;
v_id t_student.id%type;
begin
-- 業務邏輯程式碼
v_id:=100;
select stuname into v_stuname from t_student where id = v_id;
dbms_output.put_line(v_stuname);
-- 異常處理程式碼
exception
when no_data_found then
dbms_output.put_line('找不到資料');
when too_many_rows then
dbms_output.put_line('資料過多');
when others then
dbms_output.put_line('其他異常');
end;
--8、2 自定義異常
declare
v_i number(3) :=&請輸入;
myexception exception;
begin
if v_i = 2 then
raise myexception;
end if;
dbms_output.put_line('==================');
exception
when myexception then
dbms_output.put_line('自定義異常觸發了');
when others then
dbms_output.put_line('不知道的異常');
end;
遊標:
一.隱式遊標:系統自動維護的,在我們做DML操作的時候系統會自動的維護這樣一個遊標
名稱叫:sql
隱式遊標提供的常用的屬性:
sql%found: boolean 找到資料 true
sql%notfound: boolean 沒有找到資料 true
sql%rowcount: 數值型 影響的行數
sql%isopen: 是否開啟 dml中都是 false
插入:select * from student;
begin
update t_student set stuname='張三' where id = 10;
if sql%found then
dbms_output.put_line('影響了'|| sql%rowcount ||'行記錄');
end if;
if sql%isopen then
dbms_output.put_line('--------1--------');
end if;
if sql%notfound then
dbms_output.put_line('-----------2-----------');
end if;
end;
**二.顯示遊標:處理多行資料,隱式遊標配合顯示遊標使用**
2.1無參遊標
查詢出學生表中的所有的記錄:
使用的步驟:
1.宣告遊標
2.開啟遊標
3.迴圈提取資料
4.關閉遊標
declare
v_student t_student%rowtype;
--1.宣告遊標
cursor mycursor is select * from t_student;
v_count number(3):=0;
begin
--2.開啟遊標
open mycursor;
--3.迴圈提取資料
loop
--提取資料
-- 每迴圈一次從遊標中取一條記錄儲存到v_student變數中
fetch mycursor into v_student;
--指定退出條件
exit when mycursor%notfound;
v_count := v_count+1;
dbms_output.put_line(v_student.id||v_student.stuname||v_student.sex);
end loop;
dbms_output.put_line('有'||v_count||'記錄');
--4.關閉遊標
close mycursor;
end;
declare
v_student t_student%rowtype;
cursor mycursor is select * from student for update; -- 1. for update
begin
open mycursor;
loop
fetch mycursor into v_student;
exit when mycursor%notfound;
dbms_output.put_line(v_student.id||v_student.name||v_student.sex||v_student.birth);
if v_student.birth is null then
-- 2.在更新語句後加 current of 遊標名稱
update t_student set stuname='張三' where current of mycursor;
end if;
end loop;
commit;
close mycursor;
end;
2.2 有參遊標
根據姓名查詢學生表中的所有的學生資訊
declare
v_student t_student%rowtype;
v_name t_student.stuname%type:='&請輸入姓名';
cursor mycursor(c_name varchar2)
is select * from t_student where stuname like '%'||c_name||'%';
begin
open mycursor(v_name);
loop
fetch mycursor into v_student;
if mycursor%found then
dbms_output.put_line(v_student.id||'--'||v_student.stuname||'---'||v_student.age);
else
exit;
end if;
end loop;
close mycursor;
end;
declare
v_student t_student%rowtype;
v_name t_student.stuname%type := '&請輸入要查詢的姓名';
cursor mycursor -- 帶有引數
is select * from t_student where stuname like '%'||v_name||'%';
begin
open mycursor; --開啟的時候需要指定引數
loop
fetch mycursor into v_student;
if mycursor%found then
-- 有資料
dbms_output.put_line(v_student.id||v_student.stuname||v_student.sex);
else
-- 退出
exit;
end if;
end loop;
close mycursor;
end;
2.3 遊標迴圈時使用for迴圈提取
declare
v_name t_student.stuname%type := '&請輸入';
cursor mycursor is select * from t_student where stuname like '%'||v_name||'%';
begin
for v_student in mycursor loop
update t_student set age=23;
dbms_output.put_line(v_student.age||v_student.stuname||v_student.sex);
end loop;
commit;
end;
**3.REF遊標【動態遊標】:是解決遊標動態執行sql**
顯示遊標在宣告的時候就必須制定sql語句
動態遊標:在開啟的時候確定要執行的sql語句比顯示遊標更加的靈活
缺點:不能使用for迴圈和更新行
3.1 自定義ref遊標
通過REF遊標查詢出學生表中的所有的學生記錄
declare
type myreftype is ref cursor;-- 1.定義一個ref 型別
myrefcursor myreftype;-- 2.宣告一個myreftype型別的變數
v_student t_student%rowtype;
v_sql varchar2(100);
begin
v_sql:='select * from t_student';
-- for 後及可以帶'' 也可以直接是sql語句
--open myrefcursor for select * from student; -- 開啟遊標的同時指定要執行的sql語句
open myrefcursor for v_sql;
loop
fetch myrefcursor into v_student;
exit when myrefcursor%notfound;
dbms_output.put_line(v_student.age||v_student.stuname||v_student.sex);
end loop;
close myrefcursor;
end;
3.2 sys_refcursor:系統提供的一個 ref cursor 型別
declare
myrefcursor sys_refcursor; -- 宣告一個變數型別是 refcursor 型別
v_student t_student%rowtype;
v_sql varchar2(100);
begin
v_sql :='select * from t_student';
open myrefcursor for v_sql;
loop
fetch myrefcursor into v_student;
exit when myrefcursor%notfound;
dbms_output.put_line(v_student.age||v_student.stuname||v_student.sex);
end loop;
close myrefcursor;
end;
“