发布时间:2025-12-09 16:14:13 浏览次数:4
oracle数据可系统是美国oracle(甲骨文)公司提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器或B/S体系结构的数据库之一,oracle数据库时目前世界上使用最为广泛的数据库管理系统,作为一个通用的数据库系统,它具有完善的数据库管理功能,是关系型数据库,比mysql更为庞大,在现行的关系型数据库中排名第一(oracle、mysql、SqlServer),时间是最为精确的。
安装教程
Oracle数据库是数据的物理储存,这就包括(数据文件ORA或者DBF、控制文件、联机日志、参数文件)。其实Oracle数据库的概念和其他数据库不一样,这里的数据库时一个操作系统只有一个库,可以看做Oracle就只有一个大数据库。
一个数据库可以有n个实例,有一系列的后台进程和内存结构组成。
是数据库的物理储存单位,数据库的数据是储存在表空间中的,真正是在某一个或者多个数据文件中,而一个表空间可以由一个或多个数据文件组成,一个数据文件只能属于一个表空间,一旦数据文件被加入到某个表空间后,就不能删除这个文件,如果要删除某个数据文件,只能删除其所属于的表空间才行。
表空间是Oracle对物理数据库上相关数据文件的逻辑映射,一个数据库在逻辑上被划分成一到若干个表空间,每个表空间包含了在逻辑上相关联的一组结构,每个数据库至少有一个表空间(称之为system表空间)
每个表空间由同一磁盘上的一个或多个文件组成,这些文件叫数据文件,一个数据文件只能属于一个表空间。
用户是在实例下建立的,不同实例中可以建相同名字的用户,表的数据是由用户放入某一个表空间的,而这个表龙剑会随机把这些表数据进行管理和存放的,但是表不是由表空间去查询的,而是由用户去查询。
是Oracle帮我们建好的测试账户,Scott账户常用,里面有emp、dept表等。
1、新建项目的方式
MYSQL : 创建一个数据库,创建相应的表
2、Oracle是多用户的, MYSQL是多数据库的
3、Oracle安全级别要高,MYSQL开源免费
结构化查询语言
DDL : 数据定义语言 create alter drop truncate
DML : 数据操纵语言 insert update delete
DCL : 数据控制语言 安全 授权 grant revoke
DQL : 数据查询语言 select from子句 where子句
在oracle中将DQL放入DML中,多了TCL:事务控制语言 commit、rollback
所谓数据字典就是编写sql语句,全选可以一次性执行不报错
/* 1.删除数据对象 */-- 删除数据表drop table t_reply;drop table t_user;-- 删除序列drop sequence sq_user;drop sequence sq_reply;/* 2.创建数据对象 */-- 创建数据表create table t_user(u_id number(4) primary key,u_userName varchar2(40) unique not null,u_password varchar2(50) not null,u_gender number(1) check(u_gender in (0,1,2)),u_age number(3) check(u_age between 12 and 120),u_registeTime date not null);create table t_reply(r_id number(10) primary key,r_content varchar2(500) not null,r_userId number(4) not null,foreign key(r_userId) references t_user(u_id));-- 创建序列create sequence sq_user start with 1001;create sequence sq_reply start with 10000001;/* 3.添加测试数据 */-- 处理全新的数据表和全新的序列在使用时取不到初始值的问题insert into t_user values(1, '1', '1', 1, 25, sysdate);insert into t_reply values(1, '1', 1);delete from t_reply;delete from t_user;commit;/*insert into t_user values(1000, 'owner', '9999', 1, 25, sysdate);insert into t_reply values(10000000, '人员召集...', 1000);*/-- 添加数据insert into t_user values(sq_user.nextval, 'admin', '9999', 1, 25, sysdate);insert into t_reply values(sq_reply.nextval, '系统1.0上线...', sq_user.currval);/* 4.提交 */commit;/* 5.查询语句 *//*select * from t_user;select * from t_reply;*/dual : oracle中的虚表 ,伪表, 主要是用来补齐语法结构,
比如:select 1+1 from dual;注意:直接写一个常量比写 * 要高效select count(1) from emp;select count(*) from emp;使用as 关键字, 可以省略,别名中不能有特殊字符或者关键字, 如果有就加双引号(比如空格)
elect ename 姓名, sal 工资 from emp;select ename "姓 名", sal 工资 from emp;加在select和列名后面,多列去除重复: 每一列都一样才能够算作是重复
--单列去除重复select distinct job from emp;--多列去除重复的select distinct job,deptno from emp;需要用到伪表dual
select 1+1 from dual;--查询员工年薪 = 月薪* 12select sal*12 from emp;在Oracle 中 ,双引号主要是别名的时候使用, 单引号是使用的值, 是字符
注意: null值 , 代表不确定的 不可预知的内容 , 不可以做四则运算
1)mysql的空值处理
ifnull(参数1, 参数2):
判断参数1是否为null,
不为null, 则函数的结果取参数1的值
为null, 则取参数2的值
if(参数1, 参数2, 参数3)
判断参数1是否为null,
为null, 则取参数3的值
不为null, 则取参数2的值
注意if函数只能处理数值字段的空值
2)oracle的空值处理
nvl(参数1,参数2):如果1为null,则返回2,不为null就为1
nvl2(参数1, 参数2, 参数3)1为null,则返回,3,不为null,则返回2
decode(需要判断的字段,
常量值1, 结果值1,
常量值2, 结果值2,
…
常量值n, 结果值n,
默认结果值
)
条件查询就是where后面的写法
and or not
% 匹配多个字符
_ 匹配单个字符
如果有特殊字符, 需要使用escape转义
--查询员工姓名中,包含%的员工信息select * from emp where ename like '%\%%' escape '\';select * from emp where ename like '%#%%' escape '#';升序: asc ascend
降序: desc descend
排序注意null问题 : nulls first | last指定null值显示的位置
同时排列多列, 用逗号隔开
--查询员工信息,按照奖金由高到低排序select * from emp order by comm desc nulls last;--查询部门编号和按照工资 按照部门升序排序, 工资降序排序select deptno, sal from emp order by deptno asc, sal desc;分析函数:用来处理排名并列问题
rank——排名可并列,之后序号不会顺眼(如2个第二,下一个是第三名)
dense_rank——排名可并列,之后序号会顺眼(如2个第二,下一个是第四名)
row_number——不可并列排名
over——添加分组条件
partition—by——分组
sql的编写顺序:
select,from,where,group by,having,order by
sql的执行顺序:
from,where,group by,having,select,order by…
where和having的区别:
where后面不能跟聚合函数,可以接单行函数
having是在group by之后执行,可以接聚合函数
函数: 必须要有返回值
对某一行中的某个值进行处理
1)数值函数
取整
select ceil(45.926) from dual; --46 向上取整select floor(45.926) from dual; --45 向下取整四舍五入
round(a,b)
b如果是正数代表取到小数点后b位数为止
b如果是负数代表取到十位为止
elect round(45.926,2) from dual; --45.93select round(45.926,1) from dual; -- 45.9select round(45.926,0) from dual; --46select round(45.926,-1) from dual; --50select round(45.926,-2) from dual; --0select round(65.926,-2) from dual; --100截断(去尾法)
select trunc(45.926,2) from dual; --45.92select trunc(45.926,1) from dual; -- 45.9select trunc(45.926,0) from dual; --45select trunc(45.926,-1) from dual; --40select trunc(45.926,-2) from dual; --0select trunc(65.926,-2) from dual; --0求余
select mod(9,3) from dual; --0select mod(9,4) from dual; --12)字符函数
substr(str1,起始索引,长度) --注意: 起始索引不管写 0 还是 1 都是从第一个字符开始截取select substr('abcdefg',0,3) from dual; --abcselect substr('abcdefg',1,3) from dual; --abcselect substr('abcdefg',2,3) from dual; --bcd--获取字符串长度 24 28select length('abcdefg') from dual;--去除字符左右两边的空格select trim(' hello ') from dual;--替换字符串Select replace('hello','l','a') from dual;3) 日期函数
-查询今天的日期(查询的是服务器上的日期)select sysdate from dual;--查询3个月后的今天的日期select add_months(sysdate,3) from dual;--查询3天后的日期select sysdate + 3 from dual;--查询员工入职的天数select sysdate - hiredate from emp;select ceil(sysdate - hiredate) from emp;--查询员工入职的周数select (sysdate - hiredate)/7 from emp;--查询员工入职的月数select months_between(sysdate,hiredate) from emp;--查询员工入职的年份select months_between(sysdate,hiredate)/12 from emp;4) 转换函数
数值转字符
select to_char(sal,'$9,999.99') from emp;select to_char(sal,'L9,999.99') from emp;/*to_char(1210.73, '9999.9') 返回 '1210.7' to_char(1210.73, '9,999.99') 返回 '1,210.73' to_char(1210.73, '$9,999.00') 返回 '$1,210.73' to_char(21, '000099') 返回 '000021' to_char(852,'xxxx') 返回' 354'*/日期转字符 to_char() (不区分大小写)
select to_char(sysdate,'yyyy-mm-dd hh:mi:ss') from dual;select to_char(sysdate,'yyyy-mm-dd hh12:mi:ss') from dual; --默认的是24小时制度--只想要年select to_char(sysdate,'yyyy') from dual; --2017--只想要日select to_char(sysdate,'d') from dual; --2 代表一个星期中第几天(美国周天是一个星期的第一天)select to_char(sysdate,'dd') from dual; --10 代表一个月中的第几天select to_char(sysdate,'ddd') from dual; --100 代表一年中的第几天select to_char(sysdate,'day') from dual; --monday(星期的英文)select to_char(sysdate,'dy') from dual; --mon 星期的简写字符转日期
select to_date('2017-04-10','yyyy-mm-dd') from dual;--查询1981年 -- 1985年入职的员工信息select * from emp where hiredate between to_date('1981','yyyy') and to_date('1985','yyyy');5) 通用函数
nvl(参数1,参数2) 如果参数1 = null 就返回参数2nvl2(参数1,参数2,参数3) 如果参数1 = null ,就返回参数3, 否则返回参数2nullif(参数1,参数2) 如果参数1 = 参数2 那么就返回 null , 否则返回参数1coalesce: 返回第一个不为null的值select nvl2(null,5,6) from dual; --6;select nvl2(1,5,6) from dual; --5;select nullif(5,6) from dual; --5select nullif(6,6) from dual; --nullselect coalesce(null,null,3,5,6) from dual; --3对某一列的所有行进行处理
max() min count sum avg
注意:直接忽略空值
例子:
--统计员工的平均奖金 550 错误 2200/14 =,因为空值产生的影响select avg(comm) from emp;--统计员工的平均奖金 157.select sum(comm)/count(1) from emp;select ceil(sum(comm)/count(1)) from emp;作用:查询的时候用来替换列中所有数据的值,区别于取别名,取别名只是单纯的给子弹取别名
/*条件表达式:case 字段when 值1 then 值when 值2 then 值else默认值end "别名"case、when通用的写法,mysql和oracle中都可以用oracle特有的写法:decode(字段,if1,then1,if2,then2,else1)*/--给表中姓名取一个中文名select case enamewhen 'SMITH' then '刘备小二'when 'ALLEN' then '萨达'else '路人甲'end "中文名"from emp;--oracle 特有写法select decode(ename,'SMITH','刘备小二','ALLEN','萨达','路人甲') from emp;实际上是两张表的乘积,但是在实际开发中没有太大意义,格式: select * from 表1,表2
select * from emp;select * from dept;select * from emp, dept;select * from emp e1, dept d1 where e1.deptno = d1.deptno;隐式内联接:
等值内联接: where e1.deptno = d1.deptno;
不等值内联接: where e1.deptno <> d1.deptno;
自联接: 自己连接自己
显式内联接:
select * from 表1 inner join 表2 on 连接条件
inner 关键字可以省略
外连接: (标准,通用写法)
左外连接: left outer join 左表中所有的记录,如果右表没有对 应记录,就显示空
右外连接: right outer join 右表中的所有记录,如果左表没有对应记录,就显示空
outer 关键字可以省略
Oracle中的外连接: (+) 实际上是如果没有对应的记录就加上空值
select * from emp e1,dept d1 where e1.deptno = d1.deptno(+);
查询语句中嵌套查询语句; 用来解决复杂的查询语句
= = < <= <> !=
--查询最高工资的员工信息 --1.查询出最高工资 --5000select max(sal) from emp;--2. 工资等于最高工资select * from emp where sal = (select max(sal) from emp);--查询出比雇员7654的工资高,同时和7788从事相同工作的员工信息--1.雇员7654的工资 1250select sal from emp where empno = 7654;--2.7788从事的工作 ANALYSTselect job from emp where empno = 7788;--3.两个条件合并select * from emp where sal > 1250 and job = 'ANALYST';select * from emp where sal > (select sal from emp where empno = 7654) and job = (select job from emp where empno = 7788);--查询每个部门最低工资的员工信息和他所在的部门信息--1.查询每个部门的最低工资,分组统计select deptno,min(sal) minsal from emp group by deptno;--2.员工工资等于他所处部门的最低工资select * from emp e1,(select deptno,min(sal) minsal from emp group by deptno) t1 --将查询到的结果作为一张表进行两表连查where e1.deptno = t1.deptno and e1.sal = t1.minsal; --3.查询部门相关信息select * from emp e1,(select deptno,min(sal) minsal from emp group by deptno) t1,dept d1 where e1.deptno = t1.deptno and e1.sal = t1.minsal and e1.deptno = d1.deptno;in not in >any >all exists not exists
通常情况下, 数据库中不要出现null 最好的做法加上Not null
null值并不代表不占空间, char(100) null 100个字符
存在的意思,判断一张表里面的记录是否存在与另外一张表中,作布尔值来处理:, 当查询语句有结果的时候, 就是返回true,否则返回的是false,数据量比较大的时候是非常高效的
--查询有员工的部门的信息select * from dept d1 where exists(select * from emp e1 where e1.deptno = d1.deptno );Oracle的分页查询需要使用伪列辅助
伪列 : 在Oracle的结果集中默认带有的可以使用的
不出现在结果集列中的内容.
rownum : 伪列序号, 从1开始
rowid : 伪列地址
SQL执行顺序
from … where …group by…having … select…rownum…order by
默认都是从1开始。
rownum按照员工id排序后再分页select t.*from (select rownum rn,e.*from (select *from emp order by empno) e) twhere t.rn between 5 and 9; rowid去除表中重复数据create table p(name varchar2(10));insert into p values('黄伟福');insert into p values('赵洪');insert into p values('杨华');delete from p where select rowid,p.* from p;select distinct * from p;delete from p p1 where rowid > (select min(rowid) from p p2 where p1.name = p2.name);所有的查询结果可能不是来自同一张表, 将查询结果进行合并,并去除重复项
union : 去除重复的,并且排序
union all : 不会去除重复的
select * from emp where sal > 1500unionselect * from emp where deptno = 20;select * from emp where sal > 1500union allselect * from emp where deptno = 20;两个结果相减
--1981年入职员工(不包括总裁和经理)--1981年入职员工select * from emp where to_char(hiredate,'yyyy')='1981';--总裁和经理select * from emp where job = 'PRESIDENT' or job = 'MANAGER';select * from emp where to_char(hiredate,'yyyy')='1981'minusselect * from emp where job = 'PRESIDENT' or job = 'MANAGER';1.列的类型要一致
2.按照顺序写
3.列的数量要一致,如果不足,用空值填充
逻辑单位, 通常我们新建一个项目,就会去新建表空间,在表空间中创建用户来创建表
创建表空间
语法:
create tablespace 表空间的名称
datafile ‘文件的路径(服务器上)’
size 大小
autoextend on 自动扩展
next 每次扩展的大小
删除表空间
create user 用户名
identified by 密码
default tablespace 表空间的名称
create table 表名(
列名 列的类型 [列的约束],
列名 列的类型 [列的约束]
);
添加咧
alter table 表名 add 列
修改列
修改列类型:modify
修改列名:rename
删除咧
alter table 表名 drop column 列名;
修改列名
alter table 表名 rename column 列名;
重命名表
rename 旧表名 to 新表名;
drop table 表名
主键约束
primary key
非空约束
not null
唯一约束
unique
外键约束
添加外键约束:
alter table 表名 add foreign key(添加约束的字段) references 引用的表名 (引用的字段)
插入:先主表、再从表
删除:先从表,再主表
强制删除表(不建议):
drop table 表名 cascade constraint;
级联删除:
添加外键约束,使用级联约束 ,在删除的时候,使用级联删除
----添加外键约束,使用级联约束 ,在删除的时候,使用级联删除alter table product add foreign key(cno) references category(cid) on delete cascade;insert into category values(2,'电脑办公');insert into product values(11,'外星人',2);--级联删除 : 首先去从表中找有没有 关联数据, 如果在从表中找到关联数据,先删除从表中关联数据,然后再删除表中的数据delete from category where cid = 2;检查约束
check( 列名 in (‘值1’,‘值2’,‘值3’))
指定列名插入
insert into 表名 values(所有列的值都要对应写上)
不指定列名插入
insert into 表名(列1,列2) values(值1,值2);
使用子查询插入
insert into 表名 查询语句
update 表名 set 列名 = 列的值 [where 条件]
delete from 表名 [where 条件]
delete和truncate 区别delete: truncate:DML DDL逐条删除 先删除表再创建表支持事务操作 不支持事务操作,执行效率要高事务: 就是一系列的操作,要么都成功,要么都失败
四大特性: 原子性,隔离性,持久性,一致性
视图: 是对查询结果的一个封装
视图里面所有的数据,都是来自于它查询的那张表,视图本身不存储任何数据
1.能够封装复杂的查询结果
2.屏蔽表中的细节
语法:
create [or replace] view 视图的名称 as 查询语句 [ with read only]
注意: 通常不要通过视图去修改,视图创建的时候,通常要加上with read only
-同义词的概念(就是为视图取的一个别名)
create synonym dept for view_test3;
oracle中用来控制自增长的
语法:create sequence 序列的名称start with 从几开始increment by 每次增长多少maxvalue 最大值 | nomaxvalueminvalue 最小值 | nominvaluecycle | nocycle 是否循环 1,2,3,1,2,3cache 缓存的数量3 | nocache 1,2,3,4,5,6 如何从序列获取值currval : 当前值nextval : 下一个值注意: currval 需要在调用nextval之后才能使用 永不回头,往下取数据, 无论发生异常, 回滚 --序列用的最多的一种写法create sequence seq_test2;select seq_test2.nextval from dual;procedure Language 过程语言 Oracle对SQL的一个扩展
让我们能够像在java中一样写 if else else if 条件, 还可以编写循环逻辑 for while
%type --引用型变量
%rowtype --记录型变量
用来操作查询的结果集.相当于JDBC中的ResultSe
语法: cursor 游标名[(参数名 参数类型)] is 查询结果集开发步骤:1. 声明游标2. 打开游标 open 游标名3. 从游标中取数据 fetch 游标名 into 变量游标名%found :找到数据游标名%notfound : 没有找到数据 4. 关闭游标 close 游标名系统引用游标1. 声明游标 : 游标名 sys_refcursor2. 打开游标: open 游标名 for 结果集3. 从游标中取数据4. 关闭游标for循环遍历游标:不需要声明额外变量不需要打开游标不需要关闭游标例外:(意外)程序运行的过程发生异常,相当于是JAVA中的异常
declare--声明变量begin--业务逻辑exception--处理异常when 异常1 then...when 异常2 then...when others then...处理其它异常end;zero_pide : 除零异常value_error : 类型转换异常too_many_rows : 查询出多行记录,但是赋值给了rowtype记录一行数据变量no_data_found : 没有找到数据自定义异常:异常名 exception;raise 异常名 --查询指定编号的员工,如果没有找到,则抛出自定义的异常/*--错误的演示1.声明一个变量 %rowtype2.查询员工信息,保存起来3.判断员工信息是否为空4. 如果是 则抛出异常*/declare-- 1.声明一个变量 %rowtypevrow emp%rowtype;--2 .声明一个自定义的异常no_emp exception; begin--查询员工信息,保存起来select * into vrow from emp where empno = 8888; --抛出异常if vrow.sal is null thenraise no_emp; --抛出自定义的异常end if;exceptionwhen no_emp thendbms_output.put_line('输出了自定义的异常'); when others thendbms_output.put_line('输出了其它异常'||sqlerrm); end;--查询指定编号的员工,如果没有找到,则抛出自定义的异常/*游标来判断%found %notfound声明一个游标声明一个变量,记录数据从游标中取记录如果有,则不管它如果没有就抛出自定义的异常*/declare--声明游标cursor vrows is select * from emp where empno=8888; --声明一个记录型变量vrow emp%rowtype;--声明一个自定义异常no_emp exception; begin--1.打开游标open vrows;--2.取数据fetch vrows into vrow;--3.判断游标是否有数据if vrows%notfound thenraise no_emp;end if;close vrows;exceptionwhen no_emp thendbms_output.put_line('发生了自定义的异常');end;存储函数: 实际上是一段封装是Oracle服务器中的一段PLSQL代码片断,它是已经编译好了的代码片段
1)基本套路
/*JAVA调用存储过程JDBC的开发步骤:1.导入驱动包2.注册驱动3.获取连接4.获取执行SQL的statement5.封装参数6.执行SQL7.获取结果8.释放资源 *//*封装一个存储过程 : 输出所有表中的记录输出类型 : 游标 */create or replace procedure proc_getemps(vrows out sys_refcursor)isbegin--1.打开游标, 给游标赋值open vrows for select * from emp;end;2)调用存储过程
/*** 查询指定员工的年薪,用存储过程实现* create or replace procedure proc_gettotalsal(vempno in number,vtotalsal out number)isbeginselect sal*12 + nvl(comm,0) into vtotalsal from emp where empno = vempno;end;* @throws Exception*/public void test1() throws Exception {//注册驱动Class.forName("oracle.jdbc.driver.OracleDriver");//获取连接String url="jdbc:oracle:thin:@106.13.43.205:1521:orcl";String user="canghe";String password="canghe";Connection conn = DriverManager.getConnection(url, user, password);//获取执行对象String sql="{call proc_gettotalsal(?,?)}";CallableStatement state = conn.prepareCall(sql);//为问号赋值state.setInt(1, 7654);//设置员工编号state.registerOutParameter(2, OracleTypes.NUMBER);//执行statementstate.execute();//获取结果int totle = state.getInt(2);//输出结果System.out.println(totle);//释放资源state.close();conn.close();}3)调用存储函数
//调用存储函数/*create or replace function func_getsal(vempno number) return numberis--声明变量.保存年薪vtotalsal number; beginselect sal*12 + nvl(comm,0) into vtotalsal from emp where empno = vempno;return vtotalsal;end; */public void test2() throws Exception{//注册驱动Class.forName("oracle.jdbc.driver.OracleDriver");//2.获取连接String url = "jdbc:oracle:thin:@106.13.43.205:1521:orcl";String username = "canghe";String password = "canghe";Connection conn = DriverManager.getConnection(url, username,password);//3.获取执行SQL的statementString sql = " {?= call func_getsal(?)}";CallableStatement state = conn.prepareCall(sql);//4.封装参数//注册返回类型参数state.registerOutParameter(1, OracleTypes.NUMBER);//设置第二个参数state.setInt(2, 7788);//5.执行SQLstate.execute();//6.获取结果int totalsal = state.getInt(1);System.out.println("年薪 : ====" +totalsal);//7.释放资源state.close();conn.close();}3)通过游标输出结果集
/*** 通过游标输出结果集* @throws Exception*/public void test3() throws Exception{//注册驱动Class.forName("oracle.jdbc.driver.OracleDriver");//2.获取连接String url = "jdbc:oracle:thin:@106.13.43.205:1521:orcl";String username = "canghe";String password = "canghe";Connection conn = DriverManager.getConnection(url, username,password);//3.获取执行SQL的statementString sql = "{call proc_getemps(?)}";CallableStatement call = conn.prepareCall(sql);//接口 --- > 对象 -->实现类的名称System.out.println(call.getClass().getName());OracleCallableStatement oracleCall = (OracleCallableStatement)call;//4.注册输出类型的参数call.registerOutParameter(1, OracleTypes.CURSOR);//5.执行SQLcall.execute();//6.获取执行的结果ResultSet resultSet = oracleCall.getCursor(1);while(resultSet.next()){int empno = resultSet.getInt("empno");String name = resultSet.getString("ename");System.out.println(empno +" ==== "+name);}//7.释放资源resultSet.close();call.close();conn.close();}