存儲函數
create or replace function 函數名
(參數)
return 返回數據類型
is
begin
end;
--求兩個數的和
create or replace function f_sum
(
v_a number,v_b number
)
return number
is
begin
return nvl(v_a,0)+nvl(v_b,0);
end;
--從新聞表中查詢新聞標題,如果標題比定義的len長,就截取標題,後面換成...,否則就輸出標題
create or replace function f_newstitle
(
v_newstitle varchar2,
len number
)
return varchar2
is
begin
if length(v_newstitle)>len then
return substr(v_newstitle,1,len-3)||'...';
else
return v_newstitle;
end if;
end;
存儲過程
1 .不帶參數
--給所有員工工資加一百
create or replace procedure p_addsal
is
begin
update emp set sal=sal+100;
end;
執行過程:exec p_addsal;
打開輸出功能:set serveroutput on;
2.帶參數
--根據部門編號返回最高工資和最低工資
create or replace procedure p_getsal
(
v_deptno in number,
v_maxsal out number,
v_minsal out number
)
is
begin
select max(sal),min(sal) into v_maxsal,v_minsal from emp where deptno=v_deptno;
end;
--定義一個語句塊來執行這個過程
declare
v_max emp.sal%type;
v_min emp.sal%type;
begin
p_getsal(&deptno,v_max,v_min);
dbms_output.put_line('最高工資:'||v_max|| ' 最低工資:'||v_min);
end;
--根據職位查詢該職位的最高工資的姓名和最低工資的姓名
create or replace procedure p_getname
(
v_job in varchar2,
v_maxsalname out varchar2,
v_minsalname out varchar2
)
is
begin
select ename into v_maxsalname from emp where sal=(select max(sal) from emp where job=v_job);
select ename into v_minsalname from emp where sal=(select min(sal) from emp where job=v_job);
end;
declare
v_maxsalname emp.ename%type;
v_minsalname emp.ename%type;
begin
p_getname('&job',v_maxsalname,v_minsalname);
dbms_output.put_line('最高工資的姓名:'||v_maxsalname||'最低工資的姓名:'||v_minsalname);
end
--輸入輸出型參數 in out
--根據員工編號查詢他的工資
create or replace procedure p_getsal
(
v_empno in out number
)
is
begin
select sal into v_empno from emp where empno=v_empno;
end;
declare
v_empno number(10);
begin
v_empno:=7788;
p_getsal(v_empno);
dbms_output.put_line('工資'||v_empno);
end;
--根據部門編號查詢該部門的員工姓名,職位,薪水
create or replace procedure p_getemp
(
v_deptno in number,
v_result out sys_refcursor
)
is
begin
open v_result for select ename,job,sal from emp where deptno=v_deptno;
end;
--調用過程
declare
mycur sys_refcursor;
--定義一個記錄集
type t_record is record
(
v_name emp.ename%type,
v_job emp.job%type,
v_sal emp.sal%type
);
--用類型聲明一個變量
v_row t_record;
begin
p_getemp(&deptno,mycur);
loop
--提取數據
fetch mycur into v_row;
exit when mycur%notfound;
dbms_output.put_line(v_row.v_name||' '||v_row.v_job|| ' '||v_row.v_sal );
end loop;
close mycur;
end;
--輸入季節,返回這個季節入職的員工的姓名,職位,部門名稱;
思路1:select ename,job,(select dname from dept where deptno=emp.deptno) as dname from emp
where decode(to_char(hiredate,'q'),1,'春',2,'夏',3,'秋',4,'冬')='春'
思路2:select ename,job,(select dname from dept where deptno=emp.deptno) as dname from emp
where to_char(hiredate,'q')=instr('春夏秋冬','春')
create or replace procedure p_get
(
v_season in varchar2,
v_result out sys_refcursor
)
is
begin
open v_result for select ename,job,
(select dname from dept where deptno=emp.deptno) as dname from emp
where decode(to_char(hiredate,'q'),1,'春',2,'夏',3,'秋',4,'冬')='&v_reason';
end;
declare
mycur sys_refcursor;
type t_record is record
(
ename emp.ename%type,
job emp.job%type,
dname dept.dname%type
);
v_row t_record;
begin
p_get('&v_season',mycur);
loop
fetch mycur into v_row;
exit when mycur%notfound;
dbms_output.put_line(v_row.ename||' '||v_row.job||' '||v_row.dname);
end loop;
close mycur;
end;
觸發器
定義之後不能調用,在滿足某些特定條件的時候自動運行
分爲表級觸發器和行級觸發器
根據在事件前後觸發又分爲 before、after
根據觸發事件的不同又分爲insert、update、delete
for each row表示是行級觸發器,沒有它就表示是表級觸發器
特殊變量:
new --爲一個引用最新的列值
old --爲一個引用以前的列值
--只允許15號修改工資
create trigger tr_before_update_emp_sal
before update of sal on emp
for each row
declare
begin
if to_number(to_char(sysdate,'dd'))<>15 then
--引發一個自定義的異常,錯誤編號在-20000和-29999之間
RAISE_APPLICATION_ERROR(-20001,'今天不允許修改工資');
end if;
end;
-- 根據添加的交易記錄自動更新餘額
--創建餘額表
create table account
(
accid number(10) not null,
password varchar2(30) not null,
username varchar2(30) not null,
balance number(10,2) not null,
opendate date not null
);
--創建交易表
create table trade
(
accid number(10) not null,
tradedate date not null,
tradetype varchar2(20) not null,
money number(10,2) not null,
remark varchar2(50)
);
--在表中插入數據
insert into account values(10086,'123456','中國移動',10000,sysdate);
insert into account values(10010,'123456','中國聯通',50000,sysdate);
--創建觸發器
create or replace trigger tr_after_insert_trade
after insert on trade
for each row
declare
begin
if :new.tradetype='存入' then
update account set balance=balance+:new.money where accid=:new.accid;
else
update account set balance=balance-:new.money where accid=:new.accid;
end if;
end;
--在交易表中添加數據,此時查詢餘額表時餘額也多了八百
insert into trade values(10086,sysdate,'存入',800,null);
--數據校驗,在進行數據操作時進行提示
create or replace trigger tr_test
after insert or delete or update on account
for each row
declare
begin
if inserting then
dbms_output.put_line('正在添加數據:'||:new.accid);
elsif deleting then
dbms_output.put_line('正在刪除數據:'||:old.accid);
elsif updating then
dbms_output.put_line('正在修改數據:'||:old.accid);
end if;
end;
包
--創建包頭
create or replace package mypackage
is
type t_record is record
(
ename varchar2(50),
job varchar2(50),
sal number(10,2)
);
type t_cursor is ref cursor return t_record;
function sum(v_a number,v_b number)return number;
procedure p_getemp(v_deptno in number,v_cursor out t_cursor);
end;
--創建包體
create or replace package body mypackage
is
function sum(v_a number,v_b number)return number
is
begin
return v_a+v_b;
end;
procedure p_getemp(v_deptno in number,v_cursor out t_cursor)
is
begin
open v_cursor for select ename,job,sal from emp where deptno=v_deptno;
end;
end;
視圖
--創建視圖
--虛擬的查詢,建立視圖的目的是方便查詢,一般不做修改
create or replace view v_emp
as
select ename,job,hiredate,dname,grade from emp
inner join dept on emp.deptno=dept.deptno
inner join salgrade on sal between losal and hisal;
select * from v_emp
<==>
select * from
(
select * from emp
)
--刪除視圖
drop view v_emp;
--創建別名
create synonym mm for emp;
--創建索引
create index ix_emp_job on emp(job);
--正則表達式
select * from emp where regexp_like(ename,'\d{1,5}');
--在PL/SQL中使用DDL
--將sql語句賦給一個varchar2變量,再用execute immediate 執行這個varchar2變量即可;
declare
v_sql varchar2(100);
v_ename varchar2(50);
begin
v_sql:='select ename from emp where empno=7788';
execute immediate v_sql into v_ename;
dbms_output.put_line(v_ename);
end;