-- 1. 使用一個變量 declare -- Local variables here v_name varchar2(50); begin -- Test statements here select t.user_name into v_name from pay_mer_order t where t.id=3530816; dbms_output.put_line(v_name); end; -- 2. 使用多個變量 declare -- Local variables here v_name varchar2(50); v_trans_no varchar2(50); v_app_code varchar2(50); begin -- Test statements here select t.user_name, t.pay_brh_trans_no, t.app_code into v_name, v_trans_no, v_app_code from pay_mer_order t where t.id=3530816; dbms_output.put_line(v_name || ',' || v_trans_no || ',' || v_app_code); end; --3. 自定義記錄類型 declare -- 自定義一個記錄類型 type order_info is record( v_name varchar2(50), v_trans_no varchar2(50), v_app_code varchar2(50)); --聲明自定義記錄類型的變量 v_tmp_record order_info; begin select t.user_name, t.pay_brh_trans_no, t.app_code into v_tmp_record from pay_mer_order t where t.id=3530816; dbms_output.put_line(v_tmp_record.v_name || ',' || v_tmp_record.v_trans_no || ',' || v_tmp_record.v_app_code); end; -- 4. 使用%type定義變量,動態的獲取數據的聲明類型 declare -- 定義一個記錄類型 type order_info is record( v_name pay_mer_order.user_name%type, v_trans_no pay_mer_order.pay_brh_trans_no%type, v_app_code pay_mer_order.app_code%type); --聲明自定義記錄類型的變量 v_tmp_record order_info; begin select t.user_name, t.pay_brh_trans_no, t.app_code into v_tmp_record from pay_mer_order t where t.id=3530816; dbms_output.put_line(v_tmp_record.v_name || ',' || v_tmp_record.v_trans_no || ',' || v_tmp_record.v_app_code); end; -- 5. 使用%rowtype定義變量,動態的獲取數據的聲明類型 declare -- 聲明一個記錄類型的變量 v_tmp_record pay_mer_order%rowtype; begin select t.* into v_tmp_record from pay_mer_order t where t.id=3530816; dbms_output.put_line(v_tmp_record.user_name || ',' || v_tmp_record.pay_brh_trans_no || ',' || v_tmp_record.app_code); end; -- 6. 賦值語句:通過變量實現查詢語句 declare -- 聲明一個記錄類型的變量 v_tmp_record pay_mer_order%rowtype; v_order_info_id pay_mer_order.id%type; begin v_order_info_id := 3530816; select t.* into v_tmp_record from pay_mer_order t where t.id=v_order_info_id; dbms_output.put_line(v_tmp_record.user_name || ',' || v_tmp_record.pay_brh_trans_no || ',' || v_tmp_record.app_code); end; --7. 通過變量實現DELET, INSERT, UPDATE等操作 declare -- 聲明一個記錄類型的變量 v_order_info_id pay_mer_order.id%type; begin v_order_info_id := 3530816; delete from pay_mer_order t where t.id=v_order_info_id; commit; end; --8. 使用IF... THEN ... ELSIF ...THEN...ELSE...END IF; --要求: 查詢出 150 號 員工的工資, 若其工資大於或等於 10000 則打印 'salary >= 10000'; 若在 5000 到 10000 之間, 則打印 '5000<= salary < 10000'; 否則打印 'salary < 5000' --(方法一) declare v_salary employees.salary%type; begin --通過 select ... into ... 語句為變量賦值 select salary into v_salary from employees where employee_id = 150; dbms_output.put_line('salary: ' || v_salary); -- 打印變量的值 if v_salary >= 10000 then dbms_output.put_line('salary >= 10000'); elsif v_salary >= 5000 then dbms_output.put_line('5000 <= salary < 10000'); else dbms_output.put_line('salary < 5000'); end if; --(方法二) declare v_emp_name employees.last_name%type; v_emp_sal employees.salary%type; v_emp_sal_level varchar2(20); begin select last_name,salary into v_emp_name,v_emp_sal from employees where employee_id = 150; if(v_emp_sal >= 10000) then v_emp_sal_level := 'salary >= 10000'; elsif(v_emp_sal >= 5000) then v_emp_sal_level := '5000<= salary < 10000'; else v_emp_sal_level := 'salary < 5000'; end if; dbms_output.put_line(v_emp_name||','||v_emp_sal||','||v_emp_sal); end; --9. 使用 CASE ... WHEN ... THEN ...ELSE ... END 完成上面的任務 declare v_sal employees.salary%type; v_msg varchar2(50); begin select salary into v_sal from employees where employee_id = 150; --case 不能向下面這樣用 /* case v_sal when salary >= 10000 then v_msg := '>=10000' when salary >= 5000 then v_msg := '5000<= salary < 10000' else v_msg := 'salary < 5000' end; */ v_msg := case trunc(v_sal / 5000) when 0 then 'salary < 5000' when 1 then '5000<= salary < 10000' else 'salary >= 10000' end; dbms_output.put_line(v_sal ||','||v_msg); end; --10. 使用 CASE ... WHEN ... THEN ... ELSE ... END; --要求: 查詢出 122 號員工的 JOB_ID, 若其值為 'IT_PROG', 則打印 'GRADE: A'; 'AC_MGT', 打印 'GRADE B', 'AC_ACCOUNT', 打印 'GRADE C'; 否則打印 'GRADE D' declare --聲明變量 v_grade char(1); v_job_id employees.job_id%type; begin select job_id into v_job_id from employees where employee_id = 122; dbms_output.put_line('job_id: ' || v_job_id); --根據 v_job_id 的取值, 利用 case 字句為 v_grade 賦值 v_grade := case v_job_id when 'IT_PROG' then 'A' when 'AC_MGT' then 'B' when 'AC_ACCOUNT' then 'C' else 'D' end; dbms_output.put_line('GRADE: ' || v_grade); end; --11. 使用循環語句打印1-100.(三種方式) --a. LOOP...EXIT WHEN ... END LOOP declare v_i number(3) :=1; begin loop dbms_output.put_line(v_i); exit when v_i = 100; v_i := v_i + 1; end loop; end; --b. WHILE...LOOP...END LOOP declare v_i number(3) := 1; while v_i <= 100 loop dbms_output.put_line(v_i); v_i := v_i + i; end loop; end; --c. FOR...IN...LOOP begin for i in 1..100 loop dbms_oupput_put_line(i); end loop; end; --12. 綜合使用if, while語句,打印1-100之間的所有素數 --(素數:有且公有兩個正約數的整數,2, 3, 5,7,11,13...) declare v_i number(3) := 2; v_j number(3) := 2; v_flag number(1) := 0; begin while v_i < 101 loop v_j := 2; while v_j < v_i loop if(mod(v_i, v_j) = 0) then v_flag := 1; end if; exit when v_flag = 1; end loop; if(v_flag = 0) then dbms_output.put_line(v_i); end if; v_i := v_i + 1; end loop; end; --13. 使用for in實現12 declare v_flag number(1) := 0; begin for i in 2..100 loop for j in 2...i loop if(mod(i, j) = 0) then v_flag := 1; end if; exit when v_flag = 1; end loop; if(v_flag = 0) then dbms_output.put_line(i); end if; end loop; end; --14. goto declare v_flag number(1) := 0; begin for i in 2..100 loop v_flag := 1; for j in 2..sqrt(i) loop if i mod j = 0 then v_flag := 0; goto label; end if; end loop; <<label>> if v_flag = 1 then dbms_output.put_line(i); end if; end loop; end; ----------------------------------------------------------------------------
--游標的使用 --游標1. 打印出80部門的所有的員工的工資 declare --a. 定義游標 cursor salary_cursor is select salary from employees where department_i = 80; v_salary employees.salary%type; begin --b. 打開游標 open salary_cursor; --c. 提取游標 fetch salary_cursor into v_salary; --d. 對游標進行循環操作:判斷游標中是否有下一條記錄 while salary_cursor%found loop dbms_output.put_line('salary: ' || v_salary); fetch salary_cursor into v_salary; end loop; --e. 關閉游標 close salary_cursor; end; --游標2. 打印出80部門的所有員工的工資:Xxx's salary is: xxx declare cursor salary_cursor is select e.salary, e.last_name from employees e where department_i = 80; v_sal number(10); v_name varchar2(20); begin open salary_cursor; fetch salray_cursor into v_sal, v_name; while salary_cursor%found loop dbms_output.put_line(v_name || '、s salary is: ' || v_sal); fetch salary_cursor into v_sal, v_name; end loop; close salary_cursor; end; --游標3:打印同manage_id為100的員工的last_name, email, salary信息(使用游標,記錄類型) declare type v_emplyee is record( name emplyees.last_name%type, mail emplyees.email%type, sal emplyees.salary%type); v_employee_info v_employee; cursor salary_cursor is select e.last_name, e.email, e.salary from employees e where e.manage_id = 100; begin open salary_cursor; fetch salary_cursor into v_emplyeee_info; while salary_cursor%found loop dbms_output.put_line(v_employee_info.name || '、s salary is: ' || v_employee_info.mail ', email is: ' || v_employee_info.mail); fetch salary_cursor into v_employee_info; end loop; close salary_cursor; end; --游標4:使用for .. in declare type v_emplyee is record( name emplyees.last_name%type, mail emplyees.email%type, sal emplyees.salary%type); v_employee_info v_employee; cursor salary_cursor is select e.last_name, e.email, e.salary from employees e where e.manage_id = 100; begin for v_employee_info in salary_cursor loop dbms_output.put_line(v_employee_info.name || '、s salary is: ' || v_employee_info.mail ', email is: ' || v_employee_info.mail); end loop; end; --游標5:利用游標,調整公司中員工的工資 --0~5000 5%, 5000~10000 3%, 10000~15000 2%, 150~ 1% declare salary_info employees&rowtype cursor salary_adjust_cursor is select e.* from employees v_adjust number(4, 2); begin for salary_info in salary_adjust_cursor loop if(salary_info.salary <= 5000) then v_adjust := 0.05; elsif(salary_info.salary <= 10000) then v_adjust := 0.03; elsif(salary_info.salary <= 15000) then v_adjust := 0.02; else v_adjust := 0.01; end if; update employees e set e.salary=(s.salary + e.salary * v_adjust) where t.id = salary_info.id; end loop; end; --游標6:帶參數的游標 declare salary_info employees&rowtype cursor salary_adjust_cursor(dept_id number, sal number) is select salary + 1000 sal, employee_id id from employees e where t.department_id = dept_id and salary > sal; v_adjust number(4, 2); begin for salary_info in salary_adjust_cursor(sal => 4000, dept_id => 80) loop if(salary_info.salary <= 5000) then v_adjust := 0.05; elsif(salary_info.salary <= 10000) then v_adjust := 0.03; elsif(salary_info.salary <= 15000) then v_adjust := 0.02; else v_adjust := 0.01; end if; update employees e set e.salary=(s.salary + e.salary * v_adjust) where t.id = salary_info.id; end loop; end; --游標7:隱式游標,更新指定員工salary漲10%,如果該員工沒找到,則打印“查無此人” begin update employees e set salary = salary + salary * 0.1 where e.employees_id = 1055; if sql%notfound then dbms_output.put_line('查無此人!'); end if; end; ----------------------------------------------------------------------------
--異常處理1 declare v_sal employees.salary%type; begin select salary into v_sal from employees e where e.employee_id > 100; dbms_output.put_line(v_sal); exception when Too_many_rows then dbms_output.put_line('輸出的行數太多了'); end; --非預定義異常2 declare v_sal employees.salary%type; --聲明一個異常 delete_mgr_excep exception; --把自定義的異常和oracle的錯誤關聯起來 PRAGMA EXCEPTION INIT(delete_mgr_excep, -2292); begin delete from employees e where e.employee_id = 100; select salary into v_sal from employees where employee_id > 100; dbms_output.put_line(v_sal); exception when Too_many_rows then dbms_output.put_line('輸出的行數太多了'); when delete_mgr_excep then dbms_output.put_line('Manager不能直接被刪除'); end; --用戶自定義異常3 declare v_sal employees.salary%type; --聲明一個異常 delete_mgr_excep exception; --把自定義的異常和oracle的錯誤關聯起來 PRAGMA EXCEPTION INIT(delete_mgr_excep, -2292); --聲明一個異常 too_high_sal exception; begin select salary into v_sal from employees where employee_id > 100; dbms_output.put_line(v_sal); if(v_sql > 1000) then raise too_high_sal; end if; exception when Too_many_rows then dbms_output.put_line('輸出的行數太多了'); when delete_mgr_excep then dbms_output.put_line('Manager不能直接被刪除'); --處理異常 when too_high_sal then dbms_output.put_line('工資過高了'); end; --異常的基本程序4 declare v_sal employees.salary%type; begin select salary into v_sal from employees where employee_id=1000; dbms_output.put_line('salary: ' || v_sal); exception when No_data_found then dbms_output.put_line('未找到數據'); end; ---------------------------------------------------------------------------- --存儲過程和函數 --存儲函數:有返回值,創建完成後,通過select function() from dual;執行 --存儲過程:由於沒有返回值,創建完成後,不能使用select語句,只能使用pl/sql塊執行 --函數的聲明(有參數的寫在小括號裡) create or replace function func_name(v_param varchar2) --返回值類型 return varchar2 is --PL/SQL塊變量、記錄類型、游標的聲明(類似於前面的declare的部分) begin --函數體(可以實現crud操作,返回值需要return) return 'hello world' || v_param; end; --存儲函數1:helloworld create or replace function hello_func return varchar2 is begin return 'hello world'; end; --執行函數 begin dbms_output.put_line(hello_func()); end; --或者 select hello_func() from dual; --存儲函數2:參數輸入 create or replace function hello_func(v_logo varchar2) return varchar2 is begin return 'hello world ' || v_logo; end; --存儲函數3:使用OUT型的參數,因為函數只能有一個返回值,PL/SQL程序可以通過OUT型的參數實現多個返回值 --要求: 定義一個函數: 獲取給定部門的工資總和 和 該部門的員工總數(定義為 OUT 類型的參數). --要求: 部門號定義為參數, 工資總額定義為返回值. create or replace function sum_sql(dept_id number, total_count out number) return number is cursor sal_cursor is select salary from employees where department_id = dept_id; v_sum_sal number(8) := 0; begin total_count := 0; for c in sal_cursor loop v_sum_sal := v_sum_sal + c.salary; total_count := total_count + 1; end loop; return v_sum_sal; end; --執行函數 declare v_total number(3) := 0; begin dbms_output.put_line(sum_sal(80, v_total)); dbms_output.put_line(v_total); end; ----------------------------------------------------------------------------
--觸發器1:helloworld觸發器 create or replace trigger hello_trigger after update on employees begin dbms_output.put_line('hello world..'); end; --在執行以下更新語句之後會打出hello world update employees set salary = salary + 1000; --觸發囂2:行觸發器 create or replace trigger employees_trigger after update on employees for each row begin dbms_output.put_line('修改了一條記錄'); end; --觸發囂2:語句級觸發器:一個update/delete/insert語句只使觸發器執行一次 create or replace trigger employees_trigger after update on employees begin dbms_output.put_line('修改了一條記錄'); end; --觸發囂3:使用:new, :old修飾符 create or replace trigger employees_trigger after update on employees for each row begin dbms_output.put_line('old salary: ' || :old.salary || ', new salary: ' || :new.salary); end;