oracle入门
Posted it~沃克尔
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle入门相关的知识,希望对你有一定的参考价值。
### 一,视图
```
1. 什么是视图
视图是一张虚表, 可以把视图看成表使用(增删改查),视图中没有数据,所有的数据都在基本表中(tables)
封装了一个复杂的DQL
操作视图就是操作table
视图一般不作为修改数据使用, 只用作查询
2. 语法
create [or replace] view 视图名 as DQL;
3. 栗子
create or replace view emp_view as select * from emp;
select * from emp_view;
select * from emp;
insert into emp_view(empno ,ename) values(1000, ‘rose‘);
-- 作用一 : 可以屏蔽敏感列
create or replace view employee
as select empno ,ename ,job ,mgr, hiredate ,deptno from emp;
select * from emp_view;
-- 作用二:可以定义只读的视图
create or replace view employee
as select empno ,ename ,job ,mgr, hiredate ,deptno from emp with read only;
-- 错误:virtual column not allowed here
insert into employee(empno ,ename) values(1001, ‘rose‘);
```
### 二、索引
```
1. 索引的目的
提高检索效率
前提:百万条记录以上, 不经常的修改列 , 经常查询的列
2. 语法: create index 索引 on 表(列1,列2)
3. 测试效率
准备表,数据
create table a(
b number primary key ,
c varchar2(200)
)
create sequence a_seq;
select sys_guid() from dual;
declare
begin
for i in 1..1000000 loop
insert into a values(a_seq.nextval ,sys_guid() );
end loop;
end;
添加索引前查询
select * from a where c = ‘1407AB1D7E26496797E63E2C7DA76DB9‘; -- 0.546
添加索引
create index a_index on a(c);
添加索引后查询
select * from a where c = ‘9C4CD7D2251348E4B02756BEE7558C46‘; -- 0.063
4. 复合索引的触发条件(了解) address age
where address = ‘‘ and age = ‘‘ 触发索引
where address = ‘‘ or age = ‘‘ 不能触发索引
where address = ‘‘ 触发索引
where age = ‘‘ 不能触发索引
```
### 三、plsql的基本语句(过程化语言)
```
1. plsql P: procedure 过程化
2. 过程化语言的基本结构
declare
-- 声明语句
begin
--- 过程化语言
[exception]
end;
3. 声明变量
declare
-- 声明普通变量
i number;
-- 声明变量且赋值
j number default 200;
-- 引用类型:引用某表.某列的类型
pname emp.ename%type;
pjob emp.job%type;
-- 记录类型:引用表的一行的列
emp_row emp%rowtype;
begin
-- 赋值语句
i := 100;
-- 打印
dbms_output.put_line(i);
-- || 连接符
dbms_output.put_line(‘j = ‘ || j);
--赋值语句: select 查询的列 into 变量;
select ename, job into pname,pjob from emp where empno = 7788;
dbms_output.put_line(pname || ‘::‘ ||pjob);
select * into emp_row from emp where empno = 7788;
dbms_output.put_line(emp_row.ename || ‘::‘ ||emp_row.job || emp_row.hiredate);
end;
4 . if语句
格式
if 条件 then
SQL语句;
end if;
if 条件 then
SQL语句;
else
sql语句;
end if;
if 条件 then
SQL语句;
elsif 条件 then
sql语句;
....
else
sql语句;
end if;
-- 输入一个整数,如果大于0,打印正数,如果小于,打印负数,否则打印零
declare
i number;
begin
i := &请输入;
if i > 0 then
dbms_output.put_line(‘正数‘);
elsif i<0 then
dbms_output.put_line(‘负数‘);
else
dbms_output.put_line(‘零‘);
end if;
end;
5. 循环
1) for 循环
/*
for 变量 in 集合|游标 loop
end loop;
*/-- 打印1-10所有的整数
declare
begin
for i in 1..10 loop
dbms_output.put_line(i);
end loop;
end;
2) 语法
/*
loop
循环体;
退出条件; exit when 条件;
end loop;
*/
-- 打印1-10所有的整数
declare
i number default 1;
begin
loop
dbms_output.put_line(i);
exit when i = 10;
i := i + 1;
end loop;
end;
3) 语法
/*
while 条件 loop
循环体;
end loop;
*/
-- 打印1-10所有的整数
declare
i number default 1;
begin
while i <= 10 loop
dbms_output.put_line(i);
i := i + 1;
end loop;
end;
```
### 四、游标
```
1. 什么是游标(主要使用在存储过程中)
就是一个集合
主要作用处理返回多行记录的问题
2. 声明游标
cursor 游标名 is DQL;
3. 遍历游标
1) 打开游标
open 游标名
2) 提取单行的记录
fetch 游标名 into 变量中;
3) 使用循环
结束语句: exit when 游标名%notfound;
4) 关闭游标
close 游标名;
4. 栗子
-- 使用游标在控制台打印20号部门的员工信息
declare
cursor cur is select * from emp where deptno = 20;
erow emp%rowtype;
begin
open cur;
loop
fetch cur into erow;
exit when cur%notfound; -- 判断是否提取到了记录
dbms_output.put_line(erow.empno || erow.ename ||erow.job);
end loop;
close cur;
end;
select * from emp where deptno = 20;
-- 给20号部门的所有员工涨工资
declare
cursor cur is select empno from emp where deptno = 20;
begin
-- for 特点:自动打开和关闭游标
-- a 是一个记录变量, 存放游标一行的记录
for a in cur loop
update emp set sal = sal +1 where empno = a.empno;
end loop;
commit;
end;
```
### 五、存储过程(重点)
```
1. 什么是存储过程
封装了一组sql语句, 提前编译,存储在服务端,
一般是由dba定义
2. 存储过程的使用场景
网上买了一件商品:商品表(update),订单表(insert), 余额表(update),销量表(update),物流表(insert)
日志表(insert)
3. 语法
create or replace procedure 过程名(参数1 in | out 数据类型, 参数2 in | out 数据类型,...)
as|is
-- 声明语句
begin
-- plsql
end;
4 .栗子 -- 只有输入参数
给某员工涨工资, 在控制台上打印涨前的工资和涨后的工资
create or replace procedure updateSal(eno in number, psal in number)
is
oldsal emp.sal%type;
newsal emp.sal%type;
begin
select sal into oldsal from emp where empno = eno;
dbms_output.put_line(‘涨前的工资:‘||oldsal );
update emp set sal = sal + psal where empno = eno;
commit;
select sal into newsal from emp where empno = eno;
dbms_output.put_line(‘涨后的工资:‘||newsal );
end;
-- 访问存储过程
call updateSal(7788,5);
5. 栗子 有输入有输出参数的存储过程
-- 获取某员工的年薪
create or replace procedure getYearSalByEno(eno in number, yearsal out number)
as
begin
select sal * 12 + nvl(comm , 0) into yearsal from emp where empno = eno;
end;
-- 访问存储过程
declare
yearsal number;
begin
getYearSalByEno(7902, yearsal);
dbms_output.put_line(‘年薪:‘ || yearsal);
end;
6. 栗子: 输出参数为游标类型
-- 获取某部门的所有员工信息
-- cursor :静态的游标
-- sys_refcursor:动态的游标,动态的指定sql语句
create or replace procedure getEmpsByDeptno(dno in number ,emps out sys_refcursor)
as
begin
-- 动态游标赋值sql语句
open emps for
select * from emp where deptno = dno;
end;
-- 访问带有输出参数为游标的存储过程
declare
emps sys_refcursor;
erow emp%rowtype;
begin
getEmpsByDeptno(20 ,emps);
-- 遍历游标
loop
fetch emps into erow;
exit when emps%notfound;
dbms_output.put_line(erow.empno ||erow.ename);
end loop;
close emps;
end;
```
### 六、存储函数(重点)
```
1. 什么是存储过程
封装了一组sql语句, 提前编译,存储在服务端
一般是由dba定义
一般在存储函数中没有输出参数
2. 与存储过程的区别
存储函数必须有一个返回值
存储函数可以使用select语句访问
3. 语法
create or replace function 函数名(参数1 in | out 数据类型, 参数2 in | out 数据类型,...)
retrun 类型
as|is
begin
return 值;
end;
4. 栗子: 获取某员工的年薪
create or replace function getYearSalByEnoFun(eno in number) return number
as
yearsal number;
begin
select sal * 12 + nvl(comm , 0) into yearsal from emp where empno = eno;
return yearsal;
end;
-- 访问存储函数
declare
yearsal number;
begin
yearsal := getYearSalByEnoFun(7902);
dbms_output.put_line(yearsal);
end;
5. 可以用在select语句中
select getYearSalByEnoFun(7902) from dual;
select length(‘abc‘) from dual;
```
### 七,触发器
```
1. 什么是触发器
监听器: 监听表的数据是否发生改变(insert ,update ,delete)
2. 语法
create or replace trigger 触发器名称
before | after
insert |update |delete
on 表
触发器的级别
表级触发器:默认的
行级触发器:更新一条记录,执行一次,
如果使用old,new ,必须使用行级触发器
for each row
declare
begin
end;
3. 栗子1
添加一条记录,在控制台打印 ’添加了一条记录‘
create or replace trigger insertEmp
after
insert
on emp
declare
begin
dbms_output.put_line(‘添加了一条记录‘);
end;
insert into emp(empno ,ename) values(1002 ,‘mike‘);
4. 栗子2:不能给员工降薪
create or replace trigger notUpdateEmpLowerSal
before
update
on emp
for each row
declare
begin
if :old.sal > :new.sal then
-- 提示:不能降薪
--dbms_output.put_line(‘不能降薪‘);
-- raise_application_error(p1,p2)
-- p1 : 错误的编号(-20001 ~~~ -20999)
-- p2: 错误的提示信息
raise_application_error(-20001, ‘不能降薪‘);
end if;
end;
update emp set sal = sal + 1 where empno = 7788;
```
![1535171397687](assets/1535171397687.png)
### 八,JDBC调用存储过程和存储函数
```
package com.jjy;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import oracle.jdbc.driver.OracleCallableStatement;
import oracle.jdbc.driver.OracleTypes;
public class JDBCTest {
String driver = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:thin:@192.168.***.***:1521:orcl";
String username = "scott";
String password = "tiger";
Connection conn;
PreparedStatement pst;
CallableStatement cst;
ResultSet rs;
/**
* 在执行test方法之前执行before
*/
/**
* 初始化信息
* @throws Exception
*/
@Before
public void init() throws Exception{
Class.forName(driver);
conn = DriverManager.getConnection(url, username, password);
}
/**
* 访问存储过程
* create or replace procedure getYearSalByEno(eno in number, yearsal out number)
* {call <procedure-name>[(<arg1>,<arg2>, ...)]}
*/
@Test
public void testProcedure()throws Exception{
//声明sql语句
String sql = "{call getYearSalByEno(?,?)}";
//创建statement对象
cst = conn.prepareCall(sql);
//设置占位符
cst.setInt(1, 7902);
//设置输出参数的类型
cst.registerOutParameter(2, OracleTypes.NUMBER);
//执行sql语句
cst.executeUpdate();
//获取结果
int yearsal = cst.getInt(2);
System.out.println("年薪:" + yearsal);
}
/**
* 访问存储过程
* create or replace procedure getEmpsByDeptno(dno in number ,emps out sys_refcursor)
* {call <procedure-name>[(<arg1>,<arg2>, ...)]}
*/
@Test
public void testProcedureOutCursor() throws Exception{
//声明sql语句
String sql = "{call getEmpsByDeptno(?,?)}";
//创建statement对象
cst = conn.prepareCall(sql);
//设置占位符
cst.setInt(1, 20);
//设置输出参数的类型
cst.registerOutParameter(2, OracleTypes.CURSOR);
//执行sql语句
cst.executeUpdate();
// //获取结果
//OracleCallableStatement ocst = (OracleCallableStatement) cst;
// rs = (ResultSet) cst.getObject(2);
// while(rs.next()){
// System.out.println(rs.getInt("empno") + rs.getString("ename"));
// }
}
/**
* 访问存储函数
* {?= call <procedure-name>[(<arg1>,<arg2>, ...)]}
* create or replace function getYearSalByEnoFun(eno in number) return number
*/
@Test
public void testFunction()throws Exception{
//声明sql语句
String sql = "{?= call getYearSalByEnoFun(?)}";
//创建statement对象
cst = conn.prepareCall(sql);
//设置占位符
cst.registerOutParameter(1, OracleTypes.NUMBER);
cst.setInt(2, 7902);
//执行sql语句
cst.executeUpdate();
//获取结果
int yearsal = cst.getInt(1);
System.out.println("年薪:" + yearsal);
}
/**
* 查询员工中的记录
* @throws Exception
*/
@Test
public void test()throws Exception {
String sql = "select * from emp";
pst = conn.prepareStatement(sql);
rs = pst.executeQuery();
while(rs.next()){
System.out.println(rs.getInt("empno") + rs.getString("ename"));
}
}
/**
* 关闭资源
*/
@After
public void close()throws Exception{
if(rs != null){
rs.close();
}
if(pst != null){
pst.close();
}
if(cst != null){
cst.close();
}
if(conn != null){
conn.close();
}
}
}
```
以上是关于oracle入门的主要内容,如果未能解决你的问题,请参考以下文章