一、Oracle概述
使用Oracle数据库的好处:
1) Oracle的运行效率比MySQL数据库好高;2) Oracle数据库安全性最高;
3) Oracle数据库对分布式的支持非常好;
二、Oracle数据库的安装
2.1 Oracle数据库的下载
下载地址:https://www.oracle.com/downloads/index.html2.2 安装Oracle数据库的准备工作
1) 保证磁盘有足够的空间;2) 足够的内存空间。建议:把运行中的软件关闭,包括:防火墙和杀毒软件;
2.3 安装Oracle数据库
查看oracle11g的安装和卸载此文章2.4 Oracle服务
打开服务窗口:控制面板》管理工具》服务,或者在运行中输入“services.msc”命令。然后找到全部以Oracle开头的服务。只需要开启以下两项即可:
OracleServiceXXX:Oracle的核心服务。如果要访问Oracle数据库就必须要启动该服务。(必须启动)
OracleOraDb11g_home1TNSListener:监听器服务。如果要使用图形化工具访问Oracle数据库就必须要启动该服务。(建议启动)三、连接Oracle数据库
3.1 使用Oracle自带SQLPlus工具
输入用户名scott和密码tiger,然后回车。
如果看SQL>提示符就代表连接成功!
3.2 使用Oracle自带的SQLDeveloper工具
打开SQLDeveloper工具:第一次启动SQLDeveloper工具的时候,需要指定JDK1.8的根路径。
主界面:
接着,点击左上角绿色的加号 ,然后输入数据库连接信息。
主机名:访问Oracle数据库的地址。本地地址就是localhost;如果要访问远程Oracle数据库服务器就要输入服务器的IP地址;
SID:Oracle数据库的实例名,例如:orcl;
输入完成之后,然后点击“连接”。
如果看到左边出现了菜单树,就代表登录成功!
3.3 使用JDBC访问Oracle
使用JDBC的步骤:第一步:把数据库的驱动包导入到工程里面;
第二步:加载驱动;
第三步:获取数据库连接;
第四步:创建Statement对象;
第五步:编写SQL语句,然后就执行SQL语句;
第六步:遍历结果集;
第七步:关闭资源(ResultSet、Statement、Connection);
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/*
使用JDBC的步骤:
第一步:把数据库的驱动包导入到工程里面;
第二步:加载驱动;
第三步:获取数据库连接;
第四步:创建Statement对象;
第五步:编写SQL语句,然后就执行SQL语句;
第六步:遍历结果集;
第七步:关闭资源(ResultSet、Statement、Connection);
*/
public class Demo1 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//加载驱动(JDBC4.0)
//Class.forName("oracle.jdbc.OracleDriver");
//获取数据库连接
conn = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:orcl", //Oracle的URL地址
"scott", //用户名
"tiger"); //密码
//创建Statement对象
stmt = conn.createStatement();
//编写SQL并执行
rs = stmt.executeQuery("select * from emp");
//遍历结果集
if (rs != null) {
while (rs.next()) {
int empno = rs.getInt("empno");
String ename = rs.getString("ename");
System.out.println("编号:" + empno + ",姓名:" + ename);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//关闭资源
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
四、常用的SQLPlus命令
五、DDL(数据定义语言)
DDL命令:创建表、修改表、删除表。5.1 创建表
* 语法结构:
create table 表名 (列 数据类型 [primary key] auto_increment,
列 数据类型 [default 默认值] [not null],
…,
constraint 约束名 约束类型(列),
…
);
Oracle数据库的数据类型:
* 约束类型:
唯一约束、非空约束、主键约束、外键约束、check约束。check约束就是用来限制某一列的值。注意:在Oracle数据库中没有auto_increment关键字。使用序列来实现主键的自增长(后面章程有讲解)。
--创建表
create table student (
id number(10) primary key,
name nvarchar2(20) not null,
gender nchar(1) default '男',
constraint uni_student_name unique(name),
constraint chk_student_gender check(gender in ('男', '女'))
);
5.2 复制表
*语法格式:
create table 表名as
select语句;
--复制表(结构和数据)
create table student_bak
as
select * from student where 1=2;
5.3 修改表
*添加列
alter table 表名add (列名 数据类型 [not null]);
--添加列
alter table student
add(score number(3));
注意:如果表里面已经有数据,那么添加新的列就不能够指定not null约束。*修改列的数据类型
alter table 表名modify(列名 数据类型 [not null]);
--修改列的数据类型
alter table student
modify(name nvarchar2(50));
*修改列名
alter table 表名rename column 旧列名 to 新列名;
--修改列名
alter table student
rename column name to student_name;
*删除列
alter table 表名drop(列1, 列2, …);
--删除列
alter table student
drop(score);
5.4 删除表
*语法格式:
drop table 表名 [purge];--删除表
drop table stduent;
drop table student purge; --永久删除
注意:如果指定了purge参数,那么删除表的时候就不会保留在回收站里面。六、DML(数据操作语言)
6.1 添加数据
* 语法格式:
insert into 表名(列1, 列2, …)values(值1, 值2, …);
--添加数据
insert into emp(empno, ename)
values(1000, 'JACKY');
6.2 复制数据
*语法格式:
insert into 表1(列1, 列2, …)select 列1, 列2, … from 表2;
--复制表
insert into student_bak(id, name)
select empno, ename from emp;
注意:复制表和被复制表的列的数量和类型要保持一致。6.3 修改数据
* 语法格式:
update 表名 set 列1=值1, 列2=值2, … [where条件];--修改表的数据
update emp
set ename = '张三'
where empno = 1000;
6.4 删除数据
*语法格式:
delete from 表名 [where条件];--删除数据
delete from student_bak;
*delete和truncate命令的区别:
1) delete命令先把要删除的数据查询出来,然后再进行删除;truncate命令先把整个表删除,然后再重新创建表;因此,如果删除的数量很多,那么truncate命令的执行效率比delete命令要高;2) delete命令可以删除指定数据;truncate命令只能够把整个表删除;
七、DQL(数据查询语言)
7.1 多表查询
多表查询:同时查询两张或两张以上的表。*执行多表查询的注意事项:
1) 执行多表查询的时候,一张表的每一行记录会跟另外一张表的每一行记录进行组合,然后产生新的记录,这种现象也称为“笛卡尔积”现象。2) 笛卡尔积现象会产生许多的垃圾数据,因此在实际开发中要尽量避免笛卡尔积现象。如果要消除笛卡尔积,那么只需要在执行多表查询的时候添加连接条件:就是一个表的外键列等于另外一个表的主键列。
注意:执行多表查询的时候就一定会出现笛卡尔积现象。如果要消除笛卡尔积就必须要添加连接条件。
多表查询分为:内连接和外连接。
7.1.1 内连接
内连接分为:等值连接和非等值连接。等值连接就是指连接条件使用等号的连接。
非等值连接就是指连接条件使用<, <=, >, >=, <>符号的连接。
7.1.2 外连接
7.1.2.1 左外连接
左连接:左边的表作为主表,无论条件是否满足,主表的数据都会被查询出来。*语法格式:
select 列信息 from 表1 left join 表2 on 连接条件;--查询所有员工的信息以及该员工所在部门名称,无论员工的部门编号是否存在,员工的记录都会被查询出来。(左连接)
select emp.*, dept.dname
from emp left join dept
on emp.deptno = dept.deptno;
注意:left join左边的表是主表。7.1.2.2 右外连接
右连接:右连接就是右边的表作为主表,无论条件是否满足,主表的数据都会被查询出来。*语法格式:
select 列信息 from 表1 right join 表2 on 连接条件;
--查询所有员工的信息以及该员工所在部门名称,无论部门是否存在,部门的记录都会被查询出来。(右连接)
select emp.*, dept.dname
from emp right join dept
on emp.deptno = dept.deptno;
注意:right join右边的表是主表。除此以外,外连接还可以这样:
select 列信息 from 表1, 表2 where 表1.列1 = 表2.列2(+);
如果没有加号的一方就是主表。有加号的一方就是从表。这种写法是Oracle方言。一般不推荐使用。
--oracle方言
select emp.*, dept.dname from emp, dept where emp.deptno(+) = dept.deptno;
7.2 分组查询
*语法结构:
select 组信息 from 表名 group by 分组字段 [having 分组条件];--需求:查询每一个部门的平均工资
select deptno, avg(sal)
from emp
group by deptno;
组信息:分组字段或聚合函数。面试:
*什么时候使用where条件,什么时候使用having条件?
如果是分组前的条件就使用where,如果是分组后的条件就使用having。*select语句:select、from、where、group by、having、order by。
它们的执行顺序:from > where > group by > having > select > order by。--需求:统计每一个部门工资大于2000的人数
select count(*)
from emp
where sal > 2000
group by deptno;
--需求:统计每一个部门工资大于2000的人数,但是该部门的人数必须要大于1。
select count(*) as total
from emp
where sal > 2000
group by deptno
having count(*) > 1
order by total asc;
7.3 子查询
子查询:在一个查询中嵌套另外一个查询。按照子查询返回的结果:
a) 单行单列:可以放在where后面作为一条条件。
--需求:查询工资大于30部门最高工资的员工信息
Select max(sal) from emp where deptno = 30 ; -----2850
Select * from emp where sal > 2850;
===================================================================
select * from emp where sal > (select max(sal) from emp where deptno = 30);
b) 单行多列:可以放在where后面作为一个条件。
--需求:查询职位、部门编号与SCOTT用户的职位和部门编号相同的员工信息。
select job, deptno from emp where ename = 'SCOTT'; -----analyst 20
select * from emp where job = “analyst” and deptno = “20”;
==============================================================
select * from emp where (job, deptno) = (select job, deptno from emp where ename = 'SCOTT');
c) 多行单列:可以放在where后面作为一个条件。
--需求:获取所有所在地是NEW YORK的员工信息
select deptno from dept where loc = 'NEW YORK'; -----50 10
select * from emp where deptno in (50,10);
=================================================================
select * from emp where deptno in (select deptno from dept where loc = 'NEW YORK');
d) 多行多列:可以作为一个临时表放在from后面。
--需求:查询所有员工的姓名、职位、工资、所在部门的平均工资
select deptno, avg(sal) avgSal from emp group by deptno; ----查询出每个部门的平均工资
====================================================
select e.ename, e.job, e.sal, t.avgSal
from emp e, (select deptno, avg(sal) avgSal from emp group by deptno) t
where e.deptno = t.deptno;
除此以外,子查询还可以放在select后面作为一列。
--需求:查询所有员工的姓名、职位、工资、所在部门的平均工资
select e.ename, e.job, e.sal, (select avg(sal) from emp where deptno = e.deptno) from emp e;
八、伪表和伪列
8.1 伪表dual
伪表就是是一个虚拟的表。它的作用就是用来构造一个符合SQL语法的select语句。--查询当前用户
select user from dual;
--查询系统时间
select sysdate, systimestamp from dual;
--调用函数
select to_char(sysdate, 'yyyy-MM-dd') from dual;
--执行运算
select 1+2 from dual;
应用场景:1)查询系统参数;2)调用函数;3)执行运算:4)生成或查询序列的值;
8.2 伪列rowid(了解)
当用户往Oracle数据库添加数据的时候,Oracle数据库会为该条数据生成一个ID,该ID是该条记录在磁盘上的物理地址。伪列rowid的作用就是标识每一行的记录。正常情况下,一般用户是不会使用rowid获取某一条记录。
8.3 伪列rownum(重点)
当用户查询数据库的时候,Oracle数据库会对每一条记录从1开始进行编号。然后把该编号保存在rownum列中。它的作用:实现分页功能。注意:如果使用rownum作为条件,是不可以使用>, >=, =符号。因为每次查询的时候,rownum的值都不一样。
*分页的实现思路:
先查询前面10条的记录。然后再查询的结果作为一个临时表。接着再从临时表的第6条记录开始查询。--查询emp表的第二页数据,每页显示5条记录
select *
from (select rownum r, emp.* from emp where rownum <= 10)
where r >= 6;
九、运算符
9.1常用的运算符
算术运算符:+ - * /比较运算符:> >= <= < = != in between…and… is null is not null
逻辑运算符:and or not
连接运算符:||
集合运算符:
1) 并集:union(去重复)、union all(有重复)
2) 交集:intersect
3) 减集:minus
--查询员工的年薪(工资*12+奖金)
select ename, sal * 12 + comm as 年薪 from emp;
--工资大于 2000 的员工信息
select * from emp where sal > 2000;
--工资大于等于 2000,而且工资小于等于 3000 的员工信息
select * from emp where sal between 2000 and 3000;
--查询所有奖金不为空的员工信息
select * from emp where comm is not null;
--查询员工的职位信息
select ename || '的职位是:' || job from emp;
--查询工资大于 1000 并且小于 2500 的员工名字
select ename from emp where sal > 1000 and sal < 2500;
--查询工资大于 2000 并且小于 3500 的员工名字
select ename from emp where sal > 2000 and sal < 3500;
--并集
select ename from emp where sal > 1000 and sal < 2500 union select ename from emp where sal > 2000 and sal < 3500;
select ename from emp where sal > 1000 and sal < 2500 union all select ename from emp where sal > 2000 and sal < 3500;
--交集
select ename from emp where sal > 1000 and sal < 2500 intersect select ename from emp where sal > 2000 and sal < 3500;
--减集
select ename from emp where sal > 2000 and sal < 3500 minus
select ename from emp where sal > 1000 and sal < 2500;
9.2 运算符的优先级
9.3 函数
9.3.1 数值函数
--数值函数
select mod(10, 3) from dual;
select round(3.1415, 3), round(1314.1415, -2), round(1314.1415) from dual;
select trunc(3.1415, 3), trunc(1314.1415, -2), trunc(1314.1415) from dual; --3.141 1300 1314
9.3.2 字符型函数
--字符型函数
select * from emp where length(ename) > 5; --查询姓名的长度大于 5 的员工信息
select replace('明天放假吗?真的放假吗?', '放假', '自习') from dual; --替换
select substr('13088888888', 4, 8) from dual; --截取
9.3.3 日期函数
--获取当前时间
select systimestamp from dual;
--获取某日期的年份
select extract(year from sysdate) from dual;
--需求:查询 2016 入职的员工信息
select * from emp where extract(year from hiredate) = 2016;
--获取昨天的日期
select sysdate - interval '1' day from dual;
select sysdate - interval '1' month from dual;
select systimestamp + interval '1' hour from dual;
9.3.4 转换函数
--转换函数
select ename, job, to_char(hiredate, 'yyyy" 年 "MM" 月 "dd" 日 "'), to_char(sal,'$999,999,999') from emp;
select to_date('2017/04/01', 'yyyy/MM/dd') from dual;
select date '2017-04-01' from dual;
select to_timestamp('2017/04/01 12:56:12', 'yyyy/MM/dd hh24:mi:ss') from dual;
select timestamp '2017-04-01 12:56:12' from dual;
9.3.5 其他函数
--给所有入职超过 1 年的员工奖金加 300 update emp
set comm = nvl(comm, 0) + 300 where months_between(sysdate, hiredate) >= 12;
--查询员工的部门名称
select ename, deptno, decode(deptno, '10', 'ACCOUNTING', '20', 'SALES', '其他部门') from emp;