99热这里有精品-夜夜嗨av色一区二区不卡-亚洲国产精彩中文乱码AV-日本japanese乳偷乱熟

PL-SQL經典試題

  1. 準備工作:

set serveroutput on

 

hellowrold 程序

 

begin

dbms_output.put_line('hello world');

end;

/

 

[語法格式]

--declare

??--聲明的變量、類型、游標

begin

??--程序的執行部分(類似于java里的main()方法)

??dbms_output.put_line('helloworld');

--exception

??--針對begin塊中出現的異常,提供處理的機制

??--when .... then ...

??--when ?.... then ...

end;

 

*******************************************************************************

基本語法

*******************************************************************************

  1. 使用一個變量

 

declare

??--聲明一個變量

??v_name varchar2(25);

begin

??--通過 select ... into ... 語句為變量賦值

?select last_name into v_name

?from employees

?where employee_id = 186;

 

?-- 打印變量的值

?dbms_output.put_line(v_name);

end;

 

  1. 使用多個變量

 

declare

??--聲明變量

??v_name varchar2(25);

??v_email varchar2(25);

??v_salary number(8, 2);

??v_job_id varchar2(10);

begin

??--通過 select ... into ... 語句為變量賦值

??--被賦值的變量與SELECT中的列名要一一對應

?select last_name, email, salary, job_id into v_name, v_email, v_salary, v_job_id

?from employees

?where employee_id = 186;

 

?-- 打印變量的值

?dbms_output.put_line(v_name || ', ' || v_email || ', ' || ?v_salary || ', ' || ?v_job_id);

end;

----------------------------------------------------------------

記錄類型

----------------------------------------------------------------

3.1 自定義記錄類型

 

declare

??--定義一個記錄類型

??type customer_type is record(

????v_cust_name varchar2(20),

????v_cust_id number(10));

 

??--聲明自定義記錄類型的變量

??v_customer_type customer_type;

begin

??v_customer_type.v_cust_name := '劉德華';

??v_customer_type.v_cust_id := 1001;

 

??dbms_output.put_line(v_customer_type.v_cust_name||','||v_customer_type.v_cust_id);

end;

 

3.2 自定義記錄類型

 

declare

??--定義一個記錄類型

??type emp_record is record(

????v_name varchar2(25),

????v_email varchar2(25),

????v_salary number(8, 2),

????v_job_id varchar2(10));

 

??--聲明自定義記錄類型的變量

??v_emp_record emp_record;

begin

??--通過 select ... into ... 語句為變量賦值

?select last_name, email, salary, job_id into v_emp_record

?from employees

?where employee_id = 186;

 

?-- 打印變量的值

?dbms_output.put_line(v_emp_record.v_name || ', ' || v_emp_record.v_email || ', ' || ?v_emp_record.v_salary || ', ' || ?v_emp_record.v_job_id);

end;

 

  1. 使用 %type 定義變量,動態的獲取數據的聲明類型

 

declare

??--定義一個記錄類型

??type emp_record is record(

????v_name employees.last_name%type,

????v_email employees.email%type,

????v_salary employees.salary%type,

????v_job_id employees.job_id%type);

 

??--聲明自定義記錄類型的變量

??v_emp_record emp_record;

begin

??--通過 select ... into ... 語句為變量賦值

?select last_name, email, salary, job_id into v_emp_record

?from employees

?where employee_id = 186;

 

?-- 打印變量的值

?dbms_output.put_line(v_emp_record.v_name || ', ' || v_emp_record.v_email || ', ' || ?v_emp_record.v_salary || ', ' || ?v_emp_record.v_job_id);

end;

 

 

  1. 使用 %rowtype

 

declare

--聲明一個記錄類型的變量

??v_emp_record employees%rowtype;

begin

??--通過 select ... into ... 語句為變量賦值

?select * into v_emp_record

?from employees

?where employee_id = 186;

 

?-- 打印變量的值

?dbms_output.put_line(v_emp_record.last_name || ', ' || v_emp_record.email || ', ' || ?v_emp_record.salary || ', ' || ?v_emp_record.job_id ?|| ', ' || v_emp_record.hire_date);

end;

 

6.1 賦值語句:通過變量實現查詢語句

 

declare

??v_emp_record employees%rowtype;

??v_employee_id employees.employee_id%type;

begin

??--使用賦值符號位變量進行賦值

??v_employee_id := 186;

 

??--通過 select ... into ... 語句為變量賦值

?select * into v_emp_record

?from employees

?where employee_id = v_employee_id;

 

?-- 打印變量的值

?dbms_output.put_line(v_emp_record.last_name || ', ' || v_emp_record.email || ', ' || ?

v_emp_record.salary || ', ' || ?v_emp_record.job_id ?|| ', ' || v_emp_record.hire_date);

end;

 

6.2 ?通過變量實現DELETE、INSERT、UPDATE等操作

 

declare

??v_emp_id employees.employee_id%type;

 

begin

??v_emp_id := 109;

??delete from employees

??where employee_id = v_emp_id;

??--commit;

end;

*******************************************************************************

流程控制

*******************************************************************************

-----------------------------------------------------

條件判斷

-----------------------------------------------------

  1. 使用 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;

 

7+ 使用 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;

 

  1. 使用 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;

-----------------------------------------------------

循環結構

-----------------------------------------------------

  1. 使用循環語句打印 1 - 100.(三種方式)

 

1). ?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;

 

2). WHILE ... LOOP ... END LOOP

declare

???????--初始化條件

???????v_i number(3) := 1;

begin

???????--循環條件

???????while v_i <= 100 loop

?????--循環體

?????????????dbms_output.put_line(v_i);

?????--迭代條件

?????????????v_i := v_i + 1;

???????end loop;

end;

 

3).

begin

???????for i in 1 .. 100 loop

?????????????dbms_output.put_line(i);

???????end loop;

end;

 

  1. 綜合使用 if, while 語句, 打印 1 - 100 之間的所有素數

(素數: 有且僅用兩個正約數的整數, 2, 3, 5, 7, 11, 13, ...).

declare

??v_flag number(1):=1;

??v_i number(3):=2;

??v_j number(2):=2;

begin

 

??while (v_i<=100) loop

????????while v_j <= sqrt(v_i) loop

??????????????if (mod(v_i,v_j)=0) then v_flag:= 0;end if;

??????????????v_j :=v_j +1;

????????end loop;

????????if(v_flag=1) then dbms_output.put_line(v_i);end if;

 

????????v_flag :=1;

????????v_j := 2;

????????v_i :=v_i +1;

???end loop;

 

end;

 

 

(法二)使用for循環實現1-100之間的素數的輸出

declare

??--標記值, 若為 1 則是素數, 否則不是

??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;

???????????end if; ???????

???????end loop;

 

???????if v_flag = 1 then

???????????dbms_output.put_line(i);

???????end if;

 

???end loop;

end;

 

  1. 使用 goto

declare

??--標記值, 若為 1 則是素數, 否則不是

??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;

 

11+.打印1——100的自然數,當打印到50時,跳出循環,輸出“打印結束”

(方法一)

begin

??for i in 1..100 loop

??????dbms_output.put_line(i);

??????if(i = 50) then

??????goto label;

??????end if;

??end loop;

 

??????<<label>>

??????dbms_output.put_line('打印結束');

 

end;

(方法二)

begin

??for i in 1..100 loop

??????dbms_output.put_line(i);

??????if(i mod 50 = 0) then dbms_output.put_line('打印結束');

??????exit;

??????end if;

??end loop;

end;

******************************************************************************游標的使用

*******************************************************************************12.1 使用游標

要求: 打印出 80 部門的所有的員工的工資:salary: xxx

 

declare

??--1. 定義游標

??cursor salary_cursor is select salary from employees where department_id = 80;

??v_salary employees.salary%type;

begin

?--2. 打開游標

?open salary_cursor;

 

?--3. 提取游標

?fetch salary_cursor into v_salary;

 

?--4. 對游標進行循環操作: 判斷游標中是否有下一條記錄

while salary_cursor%found loop

??????dbms_output.put_line('salary: ' || v_salary);

??????fetch salary_cursor into v_salary;

end loop; ?

 

?--5. 關閉游標

?close ?salary_cursor;

end;

 

12.2 使用游標

要求: 打印出 80 部門的所有的員工的工資: Xxx 's salary is: xxx

 

declare

??cursor sal_cursor is select salary ,last_name from employees where department_id = 80;

??v_sal number(10);

??v_name varchar2(20);

begin

??open sal_cursor;

 

??fetch sal_cursor into v_sal,v_name;

 

??while sal_cursor%found loop

????????dbms_output.put_line(v_name||'`s salary is '||v_sal);

????????fetch sal_cursor into v_sal,v_name;

??end loop;

 

??close sal_cursor;

 

end;

 

  1. 使用游標的練習:

打印出 manager_id 為 100 的員工的 last_name, email, salary 信息(使用游標, 記錄類型)

 

declare ?

???????????--聲明游標 ???

???????????cursor emp_cursor is select last_name, email, salary from employees where manager_id = 100;

 

???????????--聲明記錄類型

???????????type emp_record is record(

????????????????name employees.last_name%type,

????????????????email employees.email%type,

????????????????salary employees.salary%type

???????????);

 

???????????-- 聲明記錄類型的變量

???????????v_emp_record emp_record;

begin

???????????--打開游標

???????????open emp_cursor;

 

???????????--提取游標

???????????fetch emp_cursor into v_emp_record;

 

???????????--對游標進行循環操作

???????????while emp_cursor%found loop

??????????????????dbms_output.put_line(v_emp_record.name || ', ' || v_emp_record.email || ', ' || v_emp_record.salary ); ???????????????

??????????????????fetch emp_cursor into v_emp_record;

???????????end loop;

 

???????????--關閉游標

???????????close emp_cursor;

end;

(法二:使用for循環)

declare

 

??????cursor emp_cursor is

??????select last_name,email,salary

??????from employees

??????where manager_id = 100;

 

begin

 

 

??????for v_emp_record in emp_cursor loop

??????????dbms_output.put_line(v_emp_record.last_name||','||v_emp_record.email||','||v_emp_record.salary);

??????end loop;

end;

 

  1. 利用游標, 調整公司中員工的工資:

 

????工資范圍 ??????調整基數

????0 - 5000 ??????5%

????5000 - 10000 ??3%

????10000 - 15000 ?2%

????15000 - ???????1%

 

declare

????--定義游標

????cursor emp_sal_cursor is select salary, employee_id from employees;

 

????--定義基數變量

????temp number(4, 2);

 

????--定義存放游標值的變量

????v_sal employees.salary%type;

????v_id employees.employee_id%type;

begin

????--打開游標

????open emp_sal_cursor;

 

????--提取游標

????fetch emp_sal_cursor into v_sal, v_id;

 

????--處理游標的循環操作

????while emp_sal_cursor%found loop

??????????--判斷員工的工資, 執行 update 操作

??????????--dbms_output.put_line(v_id || ': ' || v_sal);

 

??????????if v_sal <= 5000 then

?????????????temp := 0.05;

??????????elsif v_sal<= 10000 then

?????????????temp := 0.03; ??

??????????elsif v_sal <= 15000 then

?????????????temp := 0.02;

??????????else

?????????????temp := 0.01;

??????????end if;

 

??????????--dbms_output.put_line(v_id || ': ' || v_sal || ', ' || temp);

??????????update employees set salary = salary * (1 + temp) where employee_id = v_id;

 

??????????fetch emp_sal_cursor into v_sal, v_id;

????end loop;

????--關閉游標

????close emp_sal_cursor;

end;

 

使用SQL中的 decode 函數

 

update employees set salary = salary * (1 + (decode(trunc(salary/5000), 0, 0.05,

??????????????????????????????????????????????????????????1, 0.03,

??????????????????????????????????????????????????????????2, 0.02,

??????????????????????????????????????????????????????????0.01)))

 

  1. 利用游標 for 循環完成 14.

 

declare

????--定義游標

????cursor emp_sal_cursor is select salary, employee_id id from employees;

 

????--定義基數變量

????temp number(4, 2);

begin

????--處理游標的循環操作

????for c in emp_sal_cursor loop

??????????--判斷員工的工資, 執行 update 操作

??????????--dbms_output.put_line(c.employee_id || ': ' || c.salary);

 

??????????if c.salary <= 5000 then

?????????????temp := 0.05;

??????????elsif c.salary <= 10000 then

?????????????temp := 0.03; ??

??????????elsif c.salary <= 15000 then

?????????????temp := 0.02;

??????????else

?????????????temp := 0.01;

??????????end if;

 

??????????--dbms_output.put_line(v_id || ': ' || v_sal || ', ' || temp);

??????????update employees set salary = salary * (1 + temp) where employee_id = c.id;

????end loop;

end;

 

16*. 帶參數的游標

 

declare

????--定義游標

????cursor emp_sal_cursor(dept_id number, sal number) is

???????????select salary + 1000 sal, employee_id id

???????????from employees

???????????where department_id = dept_id and salary > sal;

 

????--定義基數變量

????temp number(4, 2);

begin

????--處理游標的循環操作

????for c in emp_sal_cursor(sal => 4000, dept_id => 80) loop

??????????--判斷員工的工資, 執行 update 操作

??????????--dbms_output.put_line(c.id || ': ' || c.sal);

 

??????????if c.sal <= 5000 then

?????????????temp := 0.05;

??????????elsif c.sal <= 10000 then

?????????????temp := 0.03; ??

??????????elsif c.sal <= 15000 then

?????????????temp := 0.02;

??????????else

?????????????temp := 0.01;

??????????end if;

 

??????????dbms_output.put_line(c.sal || ': ' || c.id || ', ' || temp);

??????????--update employees set salary = salary * (1 + temp) where employee_id = c.id;

????end loop;

end;

 

  1. 隱式游標: 更新指定員工 salary(漲工資 10),如果該員工沒有找到,則打印”查無此人” 信息

 

begin

?????????update employees set salary = salary + 10 where employee_id = 1005;

 

?????????if sql%notfound then

????????????dbms_output.put_line('查無此人!');

?????????end if;

end;

 

*******************************************************************************

異常處理

*******************************************************************************

[預定義異常]

declare

 

??v_sal employees.salary%type;

begin

??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('輸出的行數太多了');

end;

 

[非預定義異常]

declare

 

??v_sal employees.salary%type;

??--聲明一個異常

??delete_mgr_excep exception;

??--把自定義的異常和oracle的錯誤關聯起來

??PRAGMA EXCEPTION_INIT(delete_mgr_excep,-2292);

begin

??delete from employees

??where 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;

 

[用戶自定義異常]

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;

 

??if v_sal > 1000 then

?????raise too_high_sal;

??end if;

 

??delete 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不能直接被刪除');

??--處理異常

??when too_high_sal then dbms_output.put_line('工資過高了');

end;

 

  1. 異常的基本程序:

通過 select ... into ... 查詢某人的工資, 若沒有查詢到, 則輸出 "未找到數據"

 

declare

??--定義一個變量

??v_sal employees.salary%type;

begin

??--使用 select ... into ... 為 v_sal 賦值

??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;

 

 

declare

??--定義一個變量

??v_sal employees.salary%type;

begin

??--使用 select ... into ... 為 v_sal 賦值

??select salary into v_sal from employees;

??dbms_output.put_line('salary: ' || v_sal);

exception

??when No_data_found then

???????dbms_output.put_line('未找到數據!');

??when Too_many_rows then

???????dbms_output.put_line('數據過多!'); ????

end;

 

  1. 更新指定員工工資,如工資小于300,則加100;對 NO_DATA_FOUND 異常, TOO_MANY_ROWS 進行處理.

declare

???v_sal employees.salary%type;

begin

???select salary into v_sal from employees where employee_id = 100;

 

???if(v_sal < 300) then update employees set salary = salary + 100 where employee_id = 100;

???else dbms_output.put_line('工資大于300');

???end if;

exception

???when no_data_found then dbms_output.put_line('未找到數據');

????when too_many_rows then dbms_output.put_line('輸出的數據行太多');

end;

 

  1. 處理非預定義的異常處理: "違反完整約束條件"

 

declare

??--1. 定義異常

??temp_exception exception;

 

??--2. 將其定義好的異常情況,與標準的 ORACLE 錯誤聯系起來,使用 EXCEPTION_INIT 語句

??PRAGMA EXCEPTION_INIT(temp_exception, -2292);

begin

??delete from employees where employee_id = 100;

 

exception

??--3. 處理異常

??when temp_exception then

???????dbms_output.put_line('違反完整性約束!');

end;

 

  1. 自定義異常: 更新指定員工工資,增加100;若該員工不存在則拋出用戶自定義異常: no_result

 

declare

??--自定義異常 ??????????????????????????????????

??no_result exception; ??

begin

??update employees set salary = salary + 100 where employee_id = 1001;

 

??--使用隱式游標, 拋出自定義異常

??if sql%notfound then

?????raise no_result;

??end if; ?

 

exception

 

??--處理程序拋出的異常

??when no_result 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

--函數體(可以實現增刪改查等操作,返回值需要return)

???????return 'helloworld'|| v_param;

end;

 

22.1 函數的 helloworld: 返回一個 "helloworld" 的字符串

 

create or replace function hello_func

return varchar2

is

begin

???????return 'helloworld';

end;

 

執行函數

 

begin

????dbms_output.put_line(hello_func());

end;

 

或者: select hello_func() from dual;

 

22.2 返回一個"helloworld: atguigu"的字符串,其中atguigu 由執行函數時輸入。

 

--函數的聲明(有參數的寫在小括號里)

create or replace function hello_func(v_logo varchar2)

--返回值類型

return varchar2

is

--PL/SQL塊變量的聲明

begin

--函數體

???????return 'helloworld'|| v_logo;

end;

 

22.3 創建一個存儲函數,返回當前的系統時間

create or replace function func1

return date

is

--定義變量

v_date date;

begin

-函數體

--v_date := sysdate;

????select sysdate into v_date from dual;

???????dbms_output.put_line('我是函數哦');

 

???????return v_date;

end;

 

執行法1:

select func1 from dual;

執行法2:

declare

??v_date date;

begin

??v_date := func1;

??dbms_output.put_line(v_date);

end;

 

  1. 定義帶參數的函數: 兩個數相加

 

create or replace function add_func(a number, b number)

return number

is

begin

???????return (a + b);

end;

 

執行函數

 

begin

????dbms_output.put_line(add_func(12, 13));

end;

或者

????select add_func(12,13) from dual;

 

  1. 定義一個函數: 獲取給定部門的工資總和, 要求:部門號定義為參數, 工資總額定義為返回值.

 

create or replace function sum_sal(dept_id number)

???????return number

???????is

 

???????cursor sal_cursor is select salary from employees where department_id = dept_id;

???????v_sum_sal number(8) := 0; ??

begin

???????for c in sal_cursor loop

???????????v_sum_sal := v_sum_sal + c.salary;

???????end loop; ??????

 

???????--dbms_output.put_line('sum salary: ' || v_sum_sal);

???????return v_sum_sal;

end;

 

執行函數

 

begin

????dbms_output.put_line(sum_sal(80));

end;

 

  1. 關于 OUT 型的參數: 因為函數只能有一個返回值, PL/SQL 程序可以通過 OUT 型的參數實現有多個返回值

 

要求: 定義一個函數: 獲取給定部門的工資總和 和 該部門的員工總數(定義為 OUT 類型的參數).

要求: 部門號定義為參數, 工資總額定義為返回值.

 

create or replace function sum_sal(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; ??????

 

???????--dbms_output.put_line('sum salary: ' || v_sum_sal);

???????return v_sum_sal;

end; ??

 

執行函數:

 

delare

??v_total number(3) := 0;

 

begin

????dbms_output.put_line(sum_sal(80, v_total));

????dbms_output.put_line(v_total);

end;

 

26*. 定義一個存儲過程: 獲取給定部門的工資總和(通過 out 參數), 要求:部門號和工資總額定義為參數

 

create or replace procedure sum_sal_procedure(dept_id number, v_sum_sal out number)

???????is

 

???????cursor sal_cursor is select salary from employees where department_id = dept_id;

begin

???????v_sum_sal := 0;

 

???????for c in sal_cursor loop

???????????--dbms_output.put_line(c.salary);

???????????v_sum_sal := v_sum_sal + c.salary;

???????end loop; ??????

 

???????dbms_output.put_line('sum salary: ' || v_sum_sal);

end;

[執行]

declare

?????v_sum_sal number(10) := 0;

begin

?????sum_sal_procedure(80,v_sum_sal);

end;

 

27*. 自定義一個存儲過程完成以下操作:

對給定部門(作為輸入參數)的員工進行加薪操作, 若其到公司的時間在

(? , 95) 期間, ???為其加薪 %5

[95 , 98)?????????????????%3 ??????????????????????????????????????????????????????????????????[98, ?) ?????????????????%1

得到以下返回結果: 為此次加薪公司每月需要額外付出多少成本(定義一個 OUT 型的輸出參數).

 

create or replace procedure add_sal_procedure(dept_id number, temp out number)

 

is

 

???????cursor sal_cursor is select employee_id id, hire_date hd, salary sal from employees where department_id = dept_id;

???????a number(4, 2) := 0;

begin

???????temp := 0; ??????

 

???????for c in sal_cursor loop

???????????a := 0; ???

 

???????????if c.hd < to_date('1995-1-1', 'yyyy-mm-dd') then

??????????????a := 0.05;

???????????elsif c.hd < to_date('1998-1-1', 'yyyy-mm-dd') then

??????????????a := 0.03;

???????????else

??????????????a := 0.01;

???????????end if;

 

???????????temp := temp + c.sal * a;

???????????update employees set salary = salary * (1 + a) where employee_id = c.id;

???????end loop; ??????

end;

 

*******************************************************************************

觸發器

*******************************************************************************

一個helloworld級別的觸發器

create or replace trigger hello_trigger

after

update on employees

--for each row

begin

????dbms_output.put_line('hello...');

????--dbms_output.put_line('old.salary:'|| :OLD.salary||',new.salary'||:NEW.salary);

end;

然后執行:update employees set salary = salary + 1000;

 

  1. 觸發器的 helloworld: 編寫一個觸發器, 在向 emp 表中插入記錄時, 打印 'helloworld'

 

create or replace trigger emp_trigger

after

insert on emp

for each row

begin

???????dbms_output.put_line('helloworld');

end;

 

  1. 行級觸發器: 每更新 employees 表中的一條記錄, 都會導致觸發器執行

 

create or replace trigger employees_trigger

after

update on employees

for each row

begin

???????dbms_output.put_line('修改了一條記錄!');

end;

 

語句級觸發器: 一個 update/delete/insert 語句只使觸發器執行一次

 

create or replace trigger employees_trigger

after

update on employees

begin

???????dbms_output.put_line('修改了一條記錄!');

end;

 

  1. 使用 :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;

 

  1. 編寫一個觸發器, 在對 my_emp 記錄進行刪除的時候, 在 my_emp_bak 表中備份對應的記錄

 

1). 準備工作:

create table my_emp as select employee_id id, last_name name, salary sal from employees;

 

create table my_emp_bak as select employee_id id, last_name name, salary sal from employees where 1 = 2

 

2).

create or replace trigger bak_emp_trigger

???????before delete on my_emp

???????for each row

 

begin

???????insert into my_emp_bak values(:old.id, :old.name, :old.sal);

end;

 

蕉岭县| 东至县| 龙井市| 孟津县| 大安市| 福安市| 峡江县| 曲阜市| 四会市| 夏邑县| 贺州市| 遵义县| 舒兰市| 延川县| 德化县| 布尔津县| 韶关市| 邯郸县| 县级市| 江城| 浦江县| 垦利县| 海丰县| 平江县| 三台县| 陇西县| 绥宁县| 宜宾市| 潢川县| 桓台县| 霍州市| 静宁县| 峨边| 平果县| 金门县| 介休市| 新河县| 龙陵县| 隆回县| 定兴县| 宁乡县|