Oracle

Oracle数据库

本地环境连接Oracle数据库

	通过PLSql连接(需要整合instantclient工具使用)   

整合步骤:

PLSql中点击Tools,设置Oracle Home和OCI Library
E:\develop\instantclient_12_1(instantclient的路径)
E:\develop\instantclient_12_1\oci.dll(instantclient的路径\oci.dll)

登陆:

Username:system(该用户名为Oracle自带用户)  
Password:安装时设置的  
DataBase:服务器的Ip地址:端口号(Oracle默认端口为1521)/数据库名(默认为orcl) 
Connect as:以什么身份连接数据库 
将Oracle中的tnsnames.ora文件复制到本地,新建环境变量(变量名:TNS_ADMIN。值为tnsnames文件所在的路径)

Oracle数据库的体系结构

数据库:侧重硬件,Oracle 数据库的概念和其它数据库不一样,这里的数据库是一个操作系统只有一个库。可以看作是 Oracle 就只有一个大数据库
实例:侧重进程,一个数据库可以有N个实例   
用户:管理表的基本单位,Mysql管理表的基本单位是数据库
	Mysql可以说当前数据库下有几张表
	Oracle是用户下有几张表
表空间:逻辑单位,当实例比较大时,会把实例分成一些细小的块,块就是表空间,表空间里的内容就是数据文件(dbf,ora)
数据文件:一堆数据文件合到一起就是表空间

创建表空间
要创建表空间,必须使用有超级管理员权限的用户

写sql语句:PLSQL中File下new,Test Window和SQL Window都可以,一般用SQL Window  

注释:--  

创建表空间

create tablespace 表空间名  
datafile 'c:\itheima.dbf'(指定表空间位置,后缀一定要用dbf,因为是数据文件)  
size 100m(设置表空间初始大小为100m)
autoextend on(表空间大小不够用的时候自动扩展)  
next 10m;(每次扩展10m),点击小齿轮执行  

删除表空间

drop tablespace 表空间名;(该操作只是解除占用,还需要手动删除)  

创建用户
创建用户后不能立即登陆,因为每个用户显示的表不一样,需要给用户授权

create user 用户名  
identified by 密码(设置密码)  
default tablespace 表空间名;(指定用户出生的表空间)     

Oracle数据库中常用角色

connect--连接角色,基本角色  
resource--开发者角色  
dba--超级管理员角色  

给用户授权

grant 角色 to 用户;   

切换用户

点击session,log off,all退出所有用户,再点击session,log on,随便点击一个用户登陆即可

Oracl中的数据类型

字符类型

varchar:不常用
varchar2:常用,可变长度(只能缩小,不能增加)
char():定长,不可变

数值类型

NUMBER:
	NUMBER(n):表示整数,长度是n
		NUMBER(2):表示最大是两位数,能存99以内的数字
	NUMBER(m,n):表示一个小数,总长度是m,小数是n,整数是m-n
		NYUMBER(4,2)表示长度是4,最大存99.99
int:
	只能存整数,不能存小数,所以一般都会用NUMBER

日期类型

DATA:
	相当于Mysql中的datatime类型,精确到时分秒

大对象

CLOB:存文本,可存4G
BLOB:存二进制,可存4G

创建表,先写名称,再写类型

create table person(
   pid number(20),
   pname varchar2(10)
);

修改表结构(就是修改表的操作)

添加一列

alter table person add gender number(1);

添加多列

alter table person add (
	gender number(1),
	age number(1)
);

修改一列类型

alter table person modify gender varchar2(2);

修改多列类型

alter table person modify(
	gender varchar2(2);
	age char(2)
);

修改列名称

alter table person rename column gender to sex;

删除一列

alter table person drop column sex;

数据的增删改

添加一条记录

java中的Connection对象事务是自动提交的,使用Spring框架时,事务时Spring管理的,也就是事务会从dao挪到业务层。直接使用PLSQL工具时,没有第三方来管理事务,所以需要commit

insert into person (pid,pname) values (1,'小明');
commit;

修改一条记录

update person set pname = 'xiaoma' where pid = 1;
commit;

删除

删除表中全部记录

delete from person;  

删除表结构

drop table person;  

先删除表,再创建表,效果等同于删除表中全部记录,在数据量大的情况下,尤其表中带有索引,该操作效率高
索引可以提高查询效率,但是会影响增删改效率

truncate table person; 

序列

默认从1开始,依次递增,主要用来给主键赋值使用

语法:[]里卖内容表示可写可不写  
	CREATE SEQUENCE 序列名  
	[INCREMENT BY n] n表示每次增加几,默认增加1    
	[START WITH n]   从几开始,默认从1开始  
	[{MAXVALUE/ MINVALUE n|NOMAXVALUE}]   
	[{CYCLE|NOCYCLE}]   
	[{CACHE n|NOCACHE}];
	缓存,如果序列用到8了,将n设置为2,会自动缓存9,10适当提高插入效率,但是效果不明显。
    序列不真的属于任何一张表,但是可以用逻辑和表做绑定  
dual:
	虚表,只是为了补全语法,没有任何实际意义

创建序列

create sequence s\_person;  

查询下一个序列

select s_person.nextval from dual;  

查询当前序列

selecr s_person.currval from dual;  

绑定序列和数据的关系

insert into person (pid,pname) values (s_person.nextval,'xiaoming');  
commit;

scott用户,该用户的默认密码为tiger
刚刚装完Oracle数据库,scott用户是被锁定的,需要超级管理员权限解锁

解锁scott用户

alter user scott account unlock;(lock为锁定用户)

解锁scott用户的密码,也可以重置密码

alter user scott identified by tiger;

函数

单行函数
作用于一行,返回一个值

字符函数

select upper('yse') from dual;--大写  
select lower('YES') from dual;--小写  

数值函数

select round(26.18,1) from dual;--四舍五入,后面的参数表示保留的位数,正数往后保留,负数往前保留  
select trunc(50.26,1) from dual;--直接截取,不再看后面的数字是否大于5 
select mod(10,3) from dual;--求余  

日期函数

--查询emp表中,所有员工入职距离现在几天  
select sysdate - e.hiredate from emp e;  
sysdate:系统时间  
日期可以相加减,单位是天  
--算出明天此刻  
select sysdate + 1 from dual;  
--查询emp表中,所有员工入职距离现在几个月  
select months_between(sysdate,e.hiredate) from emp e;  

转换函数,主要还是对日期进行转换

--将日期转换成字符串  
select to_char(sysdate,'yyyy-mm-dd hh:mi:ss') from dual;  
格式中不区分大小写,所以分钟处需要写mi,结果为2019-10-07 02:07:51  
select to_char(sysdate,'fm yyyy-mm-dd hh:mi:ss') from dual;--结果为 2019-10-7 2:9:18,格式前加fm,去掉结果中占位的0  
select to_char(sysdate,'fm yyyy-mm-dd hh24:mi:ss') from dual;--结果显示为24小时计数法  
--字符串转日期  
select to_date(' 2019-10-7 14:14:4','fm yyyy-mm-dd hh24:mi:ss') from dual;  

通用函数
–算出emp表中所有员工的年薪

select e.sal*12+e.comm from emp e;--结果有null,因为奖金里有null值,任何数和null计算,结果都为null  
select e.sal*12+nvl(e.comm,0) from emp e;  
nvl(列名,替换的值),如果该列有null,则会自动替换

条件表达式
条件表达式的通用写法,MySql和Oracle都可以这么写

--给emp表中员工起中文名
select e.ename,  
   case e.ename  
     when 'SMITH' then '小明'  
     when 'ALLEN' then '小华'  
     when 'WARD' then '郭德纲'  
     else '无名'  
     end  
from emp e;  
关键字when不限数量,可以写多个    
else可以不写,不写的时候结果为null  
end必须写  
--判断emp表中员工工资,如果高于3000显示高收入,高于1500低于3000显示中等,其余显示低收入  
select e.sal,  
   case   
     when e.sal>3000 then '高收入'  
     when e.sal>1500 then '中等收入'  
     else '低收入'  
     end  
from emp e;  

Oracle专用条件表达式

select e.ename,  
    decode( e.ename,  
      'SMITH' , '小明',  
      'ALLEN',  '小华',  
      'WARD' , '郭德纲',  
      '无名') 中文名   
from emp e;  
Oracle中,除了起别名,其他都用单引号'',别名可以用双引号,也可以什么都不用  

多行函数(聚合函数)
聚合函数的特性:作用于多行,返回一个值

select count(1) from emp;--查询总数量  
	--count(*)底层也是count(1),相当于count(主键)  
select sum(sal) from emp;--工资总和    
select max(sal) from emp;--最大工资  
select min(sal) from emp;--最小工资  
select avg(sal) from emp;--平均工资  

分组查询
查询出每个部门的平均工资

select e.deptno,avg(sal) 
from emp e 
group by e.deptno 
--分组查询中,出现在group by 后面的原始列,才能出现在select的后面。
--没有出现在group by 后面的列,想要加到select的后面,必须加上聚合函数 

查询出平均工资高于2000的部门信息

select e.deptno, avg(e.sal)  
from emp e  
group by e.deptno  
having avg(e.sal) > 2000;  
--所有条件,都不能使用别名来判断,因为判断优先于查询

查询出每个部门工资高于800的员工的平均工资

select avg(e.sal)  
from emp e  
where e.sal>800  
group by e.deptno   

where和having的区别

where是过滤分组前的数据,having是过滤分组后的数据。  
表现形式:where必须在group by之前,having是在group by 之后  

查询出每个部门工资高于800的员工的平均工资,在查询平均工资高于2000的部门

select e.deptno,avg(e.sal)  
from emp e  
where e.sal > 800  
group by e.deptno  
having avg(e.sal) > 2000; 

多表查询的一些概念
笛卡尔积

select *
from emp e , dept d  

等值连接

select *  
from emp e , dept d  
where e.deptno = d.deptno   

内连接

select *  
from emp e  
inner join dept d  
on e.deptno = d.deptno;  

外连接

查询出所有部门,以及部门下的员工信息

select *   
from dept d  
left join emp e   
on d.deptno = e.deptno;  

Oracle中专用外连接

该方式是以(+)对面的表为主表

select *  
from emp e , dept d  
where e.deptno(+) = d.deptno   

自连接
查询员工姓名和员工领导姓名

select e1.ename,e2.ename  
from emp e1,emp e2  
where e1.empno = e2.mgr  
--e1的员工=e2的领导,因此,e1是领导表,e2是员工表。

查询员工名称部门名称,员工领导名称,部门名称

select e1.ename,e2.ename,d1.dname,d2.dname  
from emp e1,emp e2,dept d1,dept d2  
where e1.empno = e2.mgr   
and e1.deptno = d1.deptno  
and e2.deptno=d2.deptno  

子查询

子查询返回一个值
查询出工资和scott一样的员工信息

select *
from emp where sal in
(select sal from emp e where e.ename='SCOTT')  
--此处不能用=号,因为不能保证子查询的结果只为1,或者非空,除非子查询的条件是主键

子查询返回一个集合
查询工资和10号部门任意员工一样的员工信息

select * from emp where sal in   
(select sal from emp where deptno = 10);  

子查询返回一张表
查询每个部门的最低工资和最低工资员工姓名,和该员工所在部门名称

select e.ename,dm.ms,d.dname  
from emp e , dept d , (select deptno,min(sal) ms from emp e group by deptno) dm  
where dm.deptno = e.deptno   
and dm.ms = e.sal   
and e.deptno = d.deptno  
--1.先查询出每个部门的最低工资。
--2.三表联查(需要每个表都关联)

Oracle中的分页查询
rownum:行号
当我们做select操作的时候,每查询一行,就会在该行上加上一个行号,行号从1开始,依次递增,不能跳着走。排序操作会影响rownum的顺序
rownum不属于任何表,因此前面不能加别名,直接查询就可以
rownum不能写大于一个正数,因为从1开始,1小于任何一个正整数。
降序排列工资,查询最高的三个

select rownum,e.* from (select * from emp e order by sal desc) e where rownum < 4;  
--先执行查询,后排序,但是查询就会有行号,排序后将行号打乱了,因此需要在排序后重新加行号,使用嵌套查询,再取出前三个数据**  

emp工资表倒叙排列后,每页五条记录,查询第二页

select * from(  
select rownum rn ,e.*   
from (select * from emp  order by sal desc) e where rownum < 11) where rn> 5 ;   

由于rownum不能写大于正数,因此将第二层查询中的rownum当作一个列 加上别名后 作为最外层的条件使用

查询语句创建表
查询语句可以跨用户查询

create table emp as select * from scott.emp;    

视图
视图的概念

视图就是提供一个查询的窗口,所有数据来自于原表        

创建视图

--要创建视图,必须有dba权限,关键字view,后面加视图名
create view v_emp as select ename,job from emp;  

查询视图,和查询表一样

select * from v_emp;  

修改视图

--由于视图的数据来源于原表,所以修改视图的数据就是修改原表的数据,因此不推荐修改视图数据
update v_emp set job = 'CLERK' where ename = 'ALLEN';  
commit;  

创建只读视图

--关键字 whih read only
create view v_emp1 as select * from emp with read only;  

视图的作用

1.视图可以屏蔽一些敏感字段  
2.保证总部和分部数据及时统一

索引
索引的概念:

就是再表的列上,构建一个二叉树,达到大幅度提高查询的效率的目的,但是索引会影响增删改的效率。  
--索引分为单列索引和复合索引,单列索引就是作用在一个列上,复合索引就是作用在多个列上

创建一个单列索引
创建索引 idx_ename 在emp表的ename列上

create index idx_ename on emp(ename);
--关键字index后面加索引的名字  
select * from emp where ename = 'SCOTT'; 
--单行索引的触发规则:条件必须是索引列中的原始值  
--单行函数,模糊查询,都会影响索引的触发

复合索引
创建复合索引

create index idx_enamejob on emp(ename,job);  
--复合索引中第一列为优先检索列,如果要触发复合索引,where条件中必须包含有优先列的原始值,如果条件只有一个,并且该条件既是单列索引,又是复合索引,则触发单列索引
select * from emp where ename = 'SOCTT' or job = 'CLERK';
--上面的查询不会触发索引,因为or等于是两个查询语句 一个where ename = 'SOCTT',一个where job = 'CLERK'

pl/sql编程语言

pl/sql编程语言是对sql语言的扩展,使得sql语言具有过程化编程的特性,它是面向过程的编程语言.
pl/sql编程语言比一般的过程化编程语言,更加灵活高效.
pl/sql编程语言主要用来编写存储过程和存储函数等.

声明方法
类似java中的main方法

declare  
	声明变量的地方  
begin  
	处理业务逻辑的地方  
end;   

定义一个数字变量i,长度为2(2位数),并输出

declare  
  i number(2) := 10;  
begin  
  dbms\_output.put\_line(i);  
end;   

定义ena变量为emp表中ename的类型,使用查询赋值,将empno为7788的ename赋值给ena

declare  
  ena emp.ename%type;--引用型变量
begin  
  select ename into ena from emp where empno = 7788;  
  dbms_output.put_line(ena);  
end;  
--总结:赋值操作可以使用:=,也可以使用查询语句into来赋值

java中有对象,在pl/sql中,一行的记录就是对象
定义对象emprow

declare  
  emprow emp%rowtype;--记录型变量  
begin  
  select * into emprow from emp where empno = 7788;  
 dbms_output.put_line(emprow.ename || '的工作为' || emprow.job);
 --这里没有get方法,只能用对象.来获取,连接符号为||,而不是+    
end;  

pl/sql编程语言中的if判断
输入小于18的数字,输出未成年,输入大于18小于40的数字,输出中年人,输入大于40的数字,输出老年人

declare  
  i number(3) := &i;--输入:&后面接变量,相当于Java中Scanner,中间不能有空格,变量名随便写    
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作为结束  
end;  
--pl/sql编程语言中的if与java中的类似,也可以只写if,或if...else

#pl/sql编程语言中的loop循环
用三种循环,输出1-10十个数字

--while循环  
declare  
  i number(2) := 0;  
begin  
  while i<11 loop  
    dbms\_output.put\_line(i);  
    i := i+1;--该语法中没有i++  
  end loop;  
end;  

--exit循环,退出循环
declare  
  i number(2) := 0;  
begin  
  loop  
    exit when i > 10;--当i>10的时候结束循环  
    dbms\_output.put\_line(i);  
    i := i+1;  
  end loop;  
end;  

--for循环 
declare  
  
begin  
  for i in 1..10 loop--定义变量i,从1开始循环,到10结束  
    dbms\_output.put\_line(i);  
  end loop;  
end;

PLSQL中的游标
游标:相当于java中的集合,可以存放多个对象,也就是多行记录


输出emp表中的所有员工姓名

declare  
  cursor c1 is select * from emp;--创建游标,取名c1  
  emprow emp%rowtype; --定义引用型变量接收从游标中获取的对象  
begin  
  open c1;--要想使用游标,需要先打开  
    loop  
      fetch c1 into emprow;--从c1游标中拿对象,存入到变量emprow中  
      exit when c1%notfound;--当拿不到对象的时候自动退出  
      dbms\_output.put\_line(emprow.ename);  
    end loop;  
  close c1;--关闭游标  
end;  

给指定部门员工涨工资

declare  
 cursor c1(eno emp.deptno%type) is select empno from emp where deptno = eno; --定义带参数的游标,并赋值  
 en emp.empno%type;  
begin  
  open c1(10);--只在打开的时候给参数赋值,结束时不要带参数  
     loop  
       fetch c1 into en;  
       exit when c1%notfound;  
       update emp set sal = sal + 100 where empno = en;  
       commit;  
    end loop;  
  close c1;  
end;  

存储过程

--存储过程就是提前已经编译好的一段PL/SQL语言,放置在数据库端,可以直接被调用。这一段PL/SQL一般都是固定步骤的业务

给指定员工涨100工资

create or replace procedure p1(eno emp.empno%type)
--p1为过程名,相当于java中的方法名.  
--存储过程中的参数(eno in/out emp.empno%type),分为in/out类型,不写默认为in类型,参数不能具有长度.
  as  
begin  
  update emp set sal = sal+100 where emp.empno = eno;  
  commit;  
end;  
--执行存储过程时,出现错误不会报错,需要从Procedures文件夹中查看存储过程名中是否有红色的X号 

--测试p1  
declare  
  
begin  
  p1(7788);  
end;  

存储函数
通过存储函数,计算指定员工的年薪

create or replace function f_yearsal(eno emp.empno%type) return number   
is   
--f_yearsal为变量名,参数也有in/out,该参数不能带有长度,return后跟数据类型,该数据类型不能具有长度  
  s number(10);--定义变量s,长度为10的数字型  
begin  
  select sal*12+nvl(emp.comm,0) into s from emp where emp.empno = eno;  
  --into s:表示将查询结果存入变量s中  
  return s;--这个return后跟变量名  
end;  

调用存储函数,存储函数在调用的时候,返回值需要接收

declare   
  s number(10);  
begin  
  s := f\_yearsal(7369);   
  dbm\s_output.put\_line(s);  
end;  

out类型参数讲解
使用存储过程来计算年薪

create or replace procedure p_yearsal(eno emp.empno%type,yearsal out number)--yearsal为输出类型参数  
as  
  s emp.sal%type;  
  c emp.comm%type;  
begin  
  select sal*12 , nvl(emp.comm,0) into s,c from emp where emp.empno = eno;  
  yearsal := s+c;  
end;  

调用存储过程计算年薪

declare  
 yearsal emp.comm%type;--先定义yearsal参数  
begin  
  p_yearsal(7788,yearsal);  
  dbms_output.put_line(yearsal);  
end;  
--凡是涉及到into查询语句赋值或者:=赋值操作的参数,都必须使用out来修饰

存储过程和存储函数的区别

--关键字不同,procedure过程,function函数.
--存储过程比存储函数多了两个return.
--本质区别:存储函数有返回值,存储过程没有返回值,如果存储过程想实现有返回值的业务,我们就必须使用out类型的参数,即便是存储过程使用了out类型的参数,其本质也不是真的有了返回值,而是在存储过程内部给out类型参数赋值,在执行完毕后,我们直接拿到输出类型参数的值.

我们可以使用存储函数有返回值的特性来自定义函数。而存储过程不能用来自定义函数
案例需求:查询员工姓名和部门名称
先把scott用户下的dept表复制到当前用户下

create table dept as select * from scott.dept;  

定义函数,提供部门编号,查询部门名称

create or replace function fun(dno dept.deptno%type) return dept.dname%type  
is  
name dept.dname%type;  
begin  
  select dept.dname into name from dept where dept.deptno = dno;  
  return name;  
end;  

使用函数完成需求

select emp.ename,fun(emp.deptno)
from emp;  

触发器

触发器就是指定一个规则,在我们做增删改的时候,只要满足该规则,自动触发,无需调用。查询时无法触发触发器
触发器分为两类:语句级触发器(不包含有for each row的就是语句级触发器).
			 行级触发器(包含有for each row的就是行级触发器).
加 for each row是为了使用:old,:new 对象或一行记录。
触发语句:old:new
Insert所有字段都是空(null)将要插入的数据
Update更新以前该行的值更新后的值
Delete删除以前改行的值所有字段都是空(null)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值