oracle函数自定义过程 传参 执行过程 触发器 创建包 视图 动态执行sql语句

函数

函数可以return,过程不可以,过程可以out,函数也可以out,不过基本不用

create function 函数名
(参数)
return 返回数据类型
is
begin
end;

将一个函数创建两次,第二次覆盖第一次,不会报该函数已存在的错,加 or replace
create or replace function 函数名
(参数)//个数不受限制
return 返回数据类型//不写长度
is//定义临时变量,没有可以不写
begin
end;

定义函数

create or replace function f_sun
(
v_a number,v_b number
)
return number
is
begin
return nvl(v_a,0)+nvl(v_b,0);
end;

传参
select f_sun(3,5) from dual;
select ename,f_sun(sal,comm) from emp;

练习

新闻表,新闻标题

varchar 一个汉字占2个字符

nvarchar 一个汉字占1个字符

标题超过15个字符显示前12个加。。。

create or replace function f_char
(
v_a nvarchar2
)
return nvarchar2
is
begin
  if length(v_a)<15 then
    return v_a;
  else
   return (substr(v_a,1,12)||'...');
  end if;
  end;
  
  select f_char('我问问合并数据为i会晤i我去哦就爱看苍穹i额u发') from dual;
  
  方法2:
  create or replace function f_char
(
v_a nvarchar2,len num
)
return nvarchar2
is
begin
  if length(v_a)

过程

1、不带参数

create or replace procedure p_addsal
is 
begin
 update emp set sal=sal+100;
end;

exec p_addsal;
//执行
//没有限制过程结果

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_maxsalename out varchar2,
v_minsalename out varchar2
)
is 
begin
  select ename into v_maxsalename from emp where sal=(select max(sal) from emp where job=v_job);
  select ename into v_minsalename 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;

--//set serveroutput on;打开输出

输入输出型参数

in out 既可以输入也可以输出

根据员工编号查询他的工资

create or reolace procedure p_getsal
(
  v_emono in out number
)
is
begin
select sal into v_empno from emp where empno=v_empvo;
end;

declare
v_empno number(10);
begin
v_emp:=7788;
p_getsal(v_empno);
dbms_output.put_line('工资'||v_empno);
end;

返回结果是游标

系统中有定义好的动态游标(弱类型)sys_refcursor

根据部门编号查本部门的员工姓名,职位,薪水

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

练习

输入季节 to_char(q),返回这个季节入职的员工姓名,职位,部门名称

create or replace procedure p_getemp
(
v_jijie in varchar2,
v_result out sys_refcursor
)
is
begin
  open v_result for select ename,job,dname from emp
  inner join dept on dept.deptno=emp.deptno where hiredate in(
  select hiredate from emp where decode(to_char(hiredate,'q'),1,'春',2,'夏',3,'秋',4,'冬')=v_jijie);
  -----------------------------------to_char(hiredate,'q')=instr('春夏秋冬','春');
end;

declare
mycur sys_refcursor;
type t_record is record
(
v_ename emp.ename%type,
v_job emp.job%type,
v_dname dept.dname%type
);---一个类型
v_row t_record;--通过类型可定义变量
begin
  p_getemp(&v_jijie,mycur);
  loop
    fetch mycur into v_row;
    exit when mycur%notfound;
    dbms_output.put_line(v_row.v_ename||' '||v_row.v_job||' '||v_row.v_dname);
  end loop;
  close mycur;
  end;

触发器

行级

表级

按时间可分为:before,after

                       insert,update,delete

触发之后不能调用

满足某些条件之后自动触发

create or replace trigger <触发器名>

引发异常:raise_application_error(-20000到20000)

特殊变量

:new---------------引用最新的列值 增加的 修改之后的 数据

:old-----------------引用以前的列 删除的 修改之前的 数据

update 某一列数据时才会使用 ,of 列名 on 表名

insert,delete更新的都是一行数据,直接 ,on 表名

of 列名 不写表示对整个表的所有列

只允许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
 --//引发异常
 raise_application_error(-20001,'今天不允许修改工资');
 end if;
end;

update emp set sal=sal+100;

练习

账户表

账户,密码,用户名,开户日期,余额

10086,123456,中国移动,2019-7-10,10000

交易表

账户,交易时间,类型,金额,备注

10086,2019-7-12,存入,500,零花钱

create table account
(accid number(10) not null,
 password varchar2(20) not null,
 username varchar2(20) not null,
 opendate date not null,
 balance number(10,2)
)
create table trade
(
  accid number(10) not null,
  tradedate date not null,
  tradetype varchar(10) not null,
  money number(10,2) not null,
  remark number(20)
)
insert into account values(10086,'123456','中国移动',sysdate,10000);

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,'存入',100,null);

创建一触发器,可以有多个动作

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

禁用某个触发器

alter trigger <触发器名> disable

重新启用触发器

禁用所有触发器

数据包

CREATE [OR REPLACE] PACKAGE <数据包名> AS

           --公共类型和对象声明

           --子程序说明

  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;

视图

虚拟的查询

视图本身不保存数据

只支持select

创建视图
create or replacce view v_emp
as
select * from emp;

select * from v_emp;
等价于
select * from
(
  select * from emp
);

eg:

create or replacce view v_emp
as
select * from emp
inner join dept on dept.deptno=emp.deptno
inner join salgrade on emp.sal between losal and hisal 

–替代触发器–

同义词

create synonym mm for emp;

可以用mm代替emp

索引

加快查询速度(至少40W行数据才有效果)

多用于数据库优化

create index i_1 on emp(empno asc);

正则表达式

regexp_like ‘’

select * from emp where regexp_like(ename ,’\d{1,10}’);

最少出现一个,中间一段最多出现10个,\d数字

异常处理

exception

when <> then

动态执行sql语句

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('  ');
end;

你可能感兴趣的:(oracle笔记)