目录
-
视图
-
概念
- 是基于一个表或多个表或视图的逻辑表
- 是一个虚表, 只存储了对视图的定义, 没有存储数据
- 创建视图必须具有dba权限
- 通过视图是可以对原表中的数据进行查询和修改
-
创建只读视图
-
--创建只读视图 create view v_emp1 as select ename, job from emp with read only
-
-
视图的作用
- 可以用于屏蔽一些敏感字段
- 比如说, 你想让程序员只能使用表中数据的一部分(某些列不可以访问(员工的工资)), 就可以在创建视图的时候定义需要显示的字段
- 保证总部和分部数据及时统一
- 可以用于屏蔽一些敏感字段
-
--查询语句创建表 create table emp as select * from scott.emp--scott. 是跨用户查询 select * from emp --创建视图 create view v_emp as select ename, job from emp --查询视图 select * from v_emp
-
-
索引
-
概念
- 在列上构建一个二叉树(目录)
- 会大幅度提高查询效率, 但是会降低增删改的效率
-
单列索引
- 概念
- 把索引加到单列上
- 触发规则
- 条件必须是索引列中的原始值
-
--单列索引 create index idx_ename on emp(ename) select * from emp where ename='SCOTT'
- 概念
-
复合索引
- 概念
- 第一列为优先检索列
-
--复合索引 create index idx_ename_job on emp(ename, job)
- 触发条件
-
--触发规则 select * from emp where ename = 'SCOTT' and job = 'xx' --触发复合索引 select * from emp where ename = 'SCOTT' or job = 'xx' --不触发索引 select * from emp where ename = 'SCOTT' --触发单列索引
-
- 概念
-
-
pl/sql编程语言
-
概念
- 对sql语言的扩展, 使sql语言具有过程化变成的特性
-
基本语法
- 赋值方法 :=
- 引用表中某一字段的类型
- ena emp.ename%type;
- 使用select给变量赋值使用关键字into
- rowtype
- 记录型变量
- 可以存储一行的数据
- 连接符 ||
- 代码
-
declare i number(2) := 10; s varchar2(10) := '李乾'; ena emp.ename%type;--引用型变量 emprow emp%rowtype;--记录型变量 begin dbms_output.put_line(i); dbms_output.put_line(s); select ename into ena from emp where empno=7788; dbms_output.put_line(ena); select * into emprow from emp where empno=7788; dbms_output.put_line(emprow.ename || '的工作是: ' || emprow.job); end;
-
-
if语句
- 按照输入给变量赋值
- i number(3) := &i;
-
--if语句 declare i number(3) := &i; begin if i<18 then dbms_output.put_line('未成年'); elsif i<40 then dbms_output.put_line('中年人'); else dbms_output.put_line('老年人'); end if; end;
- 按照输入给变量赋值
-
loop循环
-
while
-
--while declare i number(2) :=1; begin while i<11 loop dbms_output.put_line(i); i := i + 1; end loop; end;
-
-
exit
- 常用
-
--exit declare i number(2) :=1; begin loop exit when i>10; dbms_output.put_line(i); i := i + 1; end loop; end;
-
for
-
--for declare i number(2) :=1; begin for i in 1..10 loop dbms_output.put_line(i); end loop; end;
-
-
-
游标
- 概念
- 类似于java中的集合, 用于存储记录
- 可以存储多个对象(多行记录)
- 游标也可以传递参数
-
--游标 declare cursor c1 is select * from emp; emprow emp%rowtype; begin open c1; loop fetch c1 into emprow; exit when c1%notfound; dbms_output.put_line(emprow.ename); end loop; close c1; end; --给指定部门的员工涨工资 select * from emp where deptno=10; declare cursor c2(eno emp.deptno%type) is select empno from emp where deptno=eno; en emp.empno%type; begin open c2(10); loop fetch c2 into en; exit when c2%notfound; update emp set sal=sal+100 where empno=en; commit; end loop; close c2; end;
- 概念
-
存储过程
-
概念
- 类似于java中的方法
- 是提前已经编译好的pl/sql语言, 可以直接调用
- 语法中不能使用return
-
参数类型
- 有in和out两种, 默认是in
-
or replace
- 可选选项
- 带上的话, 如果创建的有同名的会覆盖, 不带的话, 如果创建的有同名的会报错
- 一般都是带上
-
--存储过程 create or replace procedure p1(eno emp.empno%type) is begin update emp set sal=sal+100 where empno=eno; commit; end; --使用 select * from emp where empno=7788 declare begin p1(7788); end;
-
-
存储函数
- 概念
- 和存储过程差不多
- 语法中有两个return, 第一个return绝对不能带有长度(直接写个number就行)
- 存储过程和存储函数的参数都不能带长度
- 有返回值的方法在调用时必须使用一个变量接收, 否则报错
-
--存储函数 create or replace function f_yearsal(eno emp.empno%type) return number is s number(10); begin select sal*12+nvl(comm, 0) into s from emp where empno=eno; return s; end; --测试 declare s number(10); begin s := f_yearsal(7788); dbms_output.put_line(s); end;
- 概念
-
存储函数和存储过程的区别
-
语法区别
- 关键字不一样
- 存储函数比存储过程多了两个return
- 关键字不一样
-
本质区别
- 存储函数有返回值, 而存储过程没有返回值
- 在一些需要用到返回值的地方就必须使用存储函数了
- 案例: 必须使用存储函数
-
--准备工作 create table dept as select * from scott.dept --仅使用emp表来实现查询员工姓名以及员工所在部门名称 create or replace function fdna(dno dept.deptno%type) return dept.dname%type is dna dept.dname%type; begin select dname into dna from dept where deptno=dno; return dna; end; select ename, fdna(deptno) from emp;
-
- 存储函数有返回值, 而存储过程没有返回值
-
-
out类型参数
- 可以用来向外输出结果, 让存储过程实现存储函数中return的功能
- out和in的区别
- 凡是涉及到into查询语句复制或:=赋值的参数, 都必须使用out修饰, 否则报错
- 如果参数并没有涉及到上面的两种赋值情况, 而你还是使用了out给参数赋值了, 同样会报错
-
--out类型参数 create or replace procedure p_yearsal(eno emp.empno%type, yearsal out number) is s number(10); c emp.comm%type; begin select sal*12, nvl(comm, 0) into s, c from emp where empno = eno; yearsal := s+c; end; --测试 declare yearsal number(10); begin p_yearsal(7788, yearsal); dbms_output.put_line(yearsal); end;
-
-
触发器
-
概念
- 由事件驱动的特殊过程
-
分类
- 语句级触发器
- 不包含for each row的触发器
- 针对一些语句(update insert)进行限制
- 行级触发器
- 包含for each row的触发器
- 加for each row是为了使用:old或者:new对象或一行记录
- 语句级触发器
-
--触发器 select * from person --语句级触发器 create or replace trigger t1 after insert on person declare begin dbms_output.put_line('一个新员工入职'); end; --测试 insert into person values(23,'123') --行级触发器 --不能给员工降薪 create or replace trigger t2 after update on emp for each row declare begin if :old.sal>:new.sal then raise_application_error(-20001,'不能给员工降薪'); end if; end; --测试 update emp set sal=sal-1 where empno=7788; commit; select * from emp where empno=7788
-
触发器实现主键自增
- 需要使用到序列
-
--触发器实现主键自增 create or replace trigger auid before insert on person for each row declare begin select s_person.nextval into :new.pid from dual; end; select * from person; --测试 insert into person(pname) values('qwe');
-
-
java调用存储过程
-
环境准备
- 不同的oracle版本需要使用不同的驱动jar包
- oracle10g -- ojdbc14.jar
- oracle11g -- ojdbc6.jar
- 驱动jar包可以给他加上一个scope作用域runtime
- 驱动jar包只在运行的时候才用到, 正常编译的时候没有用到
- 不同的oracle版本需要使用不同的驱动jar包
-
环境测试
-
@Test public void test01() throws Exception { Class.forName("oracle.jdbc.driver.OracleDriver"); Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.102.10:1521:orcl", "lq01", "liqian0519"); PreparedStatement preparedStatement = connection.prepareStatement("select * from emp where empno=?"); preparedStatement.setObject(1,"7788"); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()){ System.out.println(resultSet.getString("ename")); } }
-
-
java调用存储过程和存储函数
- 调用存储过程
-
/** * java调用存储过程 * @throws Exception */ @Test public void test02() throws Exception { Class.forName("oracle.jdbc.driver.OracleDriver"); Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.102.10:1521:orcl", "lq01", "liqian0519"); //调用存储过程或存储函数时必须使用CallableStatement接口, 此接口是PreparedStatement接口的子接口 CallableStatement callableStatement = connection.prepareCall("{call p_yearsal(?, ?)}"); callableStatement.setObject(1, "7788"); callableStatement.registerOutParameter(2, OracleTypes.NUMBER); callableStatement.execute(); System.out.println(callableStatement.getObject(2)); callableStatement.close(); connection.close(); }
-
- 调用存储函数
-
/** * java调用存储函数 * @throws Exception */ @Test public void test03() throws Exception { Class.forName("oracle.jdbc.driver.OracleDriver"); Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.102.10:1521:orcl", "lq01", "liqian0519"); //调用存储过程或存储函数时必须使用CallableStatement接口, 此接口是PreparedStatement接口的子接口 CallableStatement callableStatement = connection.prepareCall("{?= call f_yearsal(?)}"); callableStatement.setObject(2, "7788"); callableStatement.registerOutParameter(1, OracleTypes.NUMBER); callableStatement.execute(); System.out.println(callableStatement.getObject(1)); callableStatement.close(); connection.close(); }
-
- 调用存储过程
-