Oracle
Oracle简介
Oracle特点
Oracle数据库具有以下特点:
- 支持多用户,大事务量的事务处理
- 数据安全性和完整性控制
- 支持分布式数据处理
- 可移植性
Oracle体系结构
数据库
Oracle数据库是数据的物理存储。Oracle的数据库是指一个操作系统只有一个库,可以看做Oracle只有一个大数据库。
实例
一个Oracle实例(Oracle Instance)有一系列的后台进程(Background Processes)和内存结构(Memory Structures)组成。一个数据库可以有多个(n个)实例。
数据文件(dbf)
- 数据文件是数据库的物理存储单位。数据库的数据是存储在表空间中的。
- 一个表空间可以由一个或多个数据文件组成,一个数据文件只能属于一个表空间。
- 一旦数据文件被加入到某个表空间,就不能删除这个文件,如果要删除该数据文件,必须删除其所属的表空间才可以。
表空间
- 表空间是Oracle对物理数据库上相关数据文件(ORA或者DBF文件)的逻辑映射。
- 一个数据库在逻辑上被划分成一到若干个表空间,每个表空间包含了在逻辑上相关联的一组结构。
- 每个数据库至少有一个表空间称之为 system 表空间 。
- 每个表空间由同一磁盘上的一个或多个文件组成,这些文件叫数据文件(datafile) 。一个数据文件只能属于一个表空间。

注:
(1)表的数据,是有用户放入某一个表空间的,而这个表空间会随机把这些表数据放到一个或者多个数据文件中。
(2)逻辑结构最小单位是数据块,不是磁盘块。
由于 oracle 的数据库不是普通的概念, oracle 是由用户和表空间对数据进行管理和存放的。但是表不是由表空间去查询的,而是由用户去查的。因为不同用户可以在同一个表空间建立同一个名字的表!这里区分就是用户了!

图片理解:
这个符号是指一个数据文件由多个磁盘块组成
用户
表空间--->用户--->表
用户是在表空间下建立的。用户登陆后只能看到和操作自己的表 , Oracle的用户与MySQL的数据库类似,每建立一个应用需要创建一个用户。

超级管理员账户

数据库操作
创建表空间
CREATE tablespace waterboss
datafile 'D:\2_dan\learningVideo\oracle\waterboss.dbf'
size 100m
autoextend ON
next 10m;
名字可以一样,也可以不一样

创建用户
create user wateruser
IDENTIFIED BY 123456
default tablespace waterboss;
wateruser:用户名
123456:密码
waterboss:默认表空间名称
用户赋权
grant dba to wateruser;--给用户赋dba权限
表的创建、修改与删除
创建表
语法:
CREATE TABLE 表名称(
字段名 类型 长度 primary key
字段名 类型 长度
......
);
create table t_owners
(
id number primary key,
name varchar2(30),
addressid number,
housenumber varchar2(30),
watermeter varchar2(30),
adddate date,
ownertypeid number
);
数据类型
字符型
- CHAR : 固定长度的字符类型,最多存储 2000 个字节
- VARCHAR2 : 可变长度的字符类型,最多存储 4000 个字节
- LONG : 大文本类型。 最大可以存储 2G
数值型
NUMBER : 数值类型
例如:
NUMBER (5) 最大可以存的数为 99999
NUMBER(5,2) 最大可以存的数为 999.99
日期型
- DATE :日期时间型,精确到秒
- TIMESTAMP :精确到秒的小数点后 9 位
二进制型
- CLOB : 存储字符 最大可以存 4G
- BLOB :存储图像、声音、 视频等二进制数据 最多可以存 4G
修改表
增加字段语法
ALTER TABLE 表名称 ADD
(
列名1 类型 [DEFAULT 默认值],
列名2 类型 [DEFAULT 默认值]
);
ALTER TABLE T_OWNERS ADD
(
REMARK VARCHAR2 20
OUTDATE DATE
)
修改字段语法
ALTER TABLE 表名称 MODIFY
(
列名1 类型 [DEFAULT 默认值],
列名2 类型 [DEFAULT 默认值]
)
ALTE R TABLE T_OWNERS MODIFY
(
REMARK CHAR 20
OUTDATE TIMESTAMP
)
修改字段名语法
ALTER TABLE 表名称 RNAME COLUMN 原列名 TO 新列名
ALTER TABLE T_OWNERS RENAME COLUMN OUTDATE TO EXITDATE
删除字段名
--删除一个字段
ALTER TABLE 表名称 DROP COLUMN 列名
--删除多个字段
ALTER TABLE 表名称 DROP( 列名1, 列名2...)
--删除字段
ALTER TABLE T_OWNERS DROP COLUMN REMARK
删除表
DROP TABLE 表名称
数据增删改
插入数据
语法:
INSERT INTO 表名( 列名1,列名2,...) VALUES ( 值1,值2...)
insert into T_OWNERS_COPY VALUES(11, '张三丰', 1, '123', '321', sysdate, 1);

修改数据
方式1
update 表名 set 列名1=值1, 列名2=值2,... where 修改条件;
update T_OWNERS_COPY set NAME = '小红', ADDRESSID = '888' where id = 1;
方式2
truncate table 表名
两种方式的区别:
- truncate删除的数据不可以rollback,delete删除的数据可以rollback
删除数据
语法:
delete fromm 表名 where 删除条件;
delete from T_OWNERS_COPY where id = 11;
JDBC连接Oracle
导入驱动包ojdbc8.jar
oracle 19c安装之后的ojdbc.jar包在下面这个地方可以找到,D:\6_application\oracle\jdbc\lib

将上面的jar添加到工程的library,否则会报下面这个错误。
java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at dao.BaseDao.<clinit>(BaseDao.java:11)
at dao.OwnerDao.add(OwnerDao.java:15)
at test.Test01.main(Test01.java:17)
Exception in thread "main" java.lang.RuntimeException: java.sql.SQLException: No suitable driver found for jdbc:oracle:thin:@localhost:1521:orcl
at dao.OwnerDao.add(OwnerDao.java:26)
at test.Test01.main(Test01.java:17)
Caused by: java.sql.SQLException: No suitable driver found for jdbc:oracle:thin:@localhost:1521:orcl
at java.sql.DriverManager.getConnection(DriverManager.java:689)
at java.sql.DriverManager.getConnection(DriverManager.java:247)
at dao.BaseDao.getConnection(BaseDao.java:23)
at dao.OwnerDao.add(OwnerDao.java:15)
... 1 more

BaseDao
package dao;
import java.sql.*;
/**
* 基础数据访问类
*/
public class BaseDao {
static {
try {
Class.forName("oracle.jdbc.driver.OracleDriver"); // 加载Oracle JDBC驱动
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接
*
* @return 数据库连接对象
*/
public static Connection getConnection() throws SQLException {
//痩连接: jdbc:oracle:thin
return DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "wateruser", "123456");
}
/**
* 关闭数据库连接
*
* @param conn 数据库连接对象
*/
public static void close(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
OwnerDao
package dao;
import entity.Owners;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class OwnerDao {
public static void add(Owners owner) {
Connection conn = null;
//预处理,防止注入攻击
PreparedStatement stmt = null;
try {
conn = BaseDao.getConnection();
stmt = conn.prepareStatement("INSERT INTO T_OWNERS_COPY (id, name, addressid, housenumber, watermeter, adddate, ownertypeid) VALUES (?, ?, ?, ?, ?, ?, ?)");
stmt.setLong(1, owner.getId());
stmt.setString(2, owner.getName());
stmt.setLong(3, owner.getAddressid());
stmt.setString(4, owner.getHousenumber());
stmt.setString(5, owner.getWatermeter());
//日期转为长整型Long, 然后再构造为java.sql.Date类型
stmt.setDate(6, new java.sql.Date(owner.getAdddate().getTime()));
stmt.setLong(7, owner.getOwnertypeid());
stmt.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
BaseDao.close(null, stmt, conn);
}
}
public static void modify(Owners owner) {
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = BaseDao.getConnection();
stmt = conn.prepareStatement("update T_OWNERS_COPY set name =?, addressid=?, housenumber=?, watermeter=?, adddate=?, ownertypeid=? where id=?");
stmt.setString(1, owner.getName());
stmt.setLong(2, owner.getAddressid());
stmt.setString(3, owner.getHousenumber());
stmt.setString(4, owner.getWatermeter());
stmt.setDate(5, new java.sql.Date(owner.getAdddate().getTime()));
stmt.setLong(6, owner.getOwnertypeid());
stmt.setLong(7, owner.getId());
stmt.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
BaseDao.close(null, stmt, conn);
}
}
public static void delete(Owners owner) {
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = BaseDao.getConnection();
stmt = conn.prepareStatement("delete from T_OWNERS_COPY where id=?");
stmt.setLong(1, owner.getId());
stmt.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
BaseDao.close(null, stmt, conn);
}
}
}
实体类Owners
public class Owners {
private Long id;//业主编号
private String name;// 业主名称
private Long addressid;// 地址编号
private String housenumber;// 门牌号
private String watermeter;// 水表编号
private Date adddate;// 登记日期
private Long ownertypeid;// 业主类型 ID
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/*
其他getter,setter方法,省略
*/
}
测试代码
public class Test02 {
public static void main(String[] args) {
Owners owner = new Owners();
owner.setId(1L);
owner.setName("张三");
owner.setAddressid(111L);
owner.setHousenumber("111号");
owner.setWatermeter("6666");
owner.setAdddate(new java.util.Date());
owner.setOwnertypeid(888L);
OwnerDao.modify(owner);
}
}
执行modify方法之前

执行modify方法之后

数据导入与导出
数据库导入与导出
整库导出
exp system/超级管理员用户system的密码 full=y --full=y表示整库导出

执行命令后会在当前目录下生成一个叫EXPDAT.DMP,此文件为备份文件。

添加file参数即可指定备份文件的名称
exp system/超级管理员用户system的密码 file=文件名 full=y
整库导入
imp system/超级管理员用户system的密码 full=y
如果指定file 参数,则按照file指定的备份文件进行导入
imp system/超级管理员用户system的密码 full=y file=water.dmp
按用户导入与导出
导出
exp system/itcast owner=wateruser file=wateruser.dmp



导入
imp system/itcast file=wateruser.dmp fromuser=wateruser
导入前特意删掉T_OWNERS_COPY表

导入后刷新,表成功导入

按表导入与导出
导出
exp wateruser/123456 file=a.dmp tables=t_account,a_area
导入
imp wateruser/123456 file=a.dmp tables=t_account,a_area
单表查询
简单条件查询
精确查询
需求:查询水表编号为30408 的业主记录
查询语句:
SELECT
*
FROM
T_OWNERS
WHERE
watermeter = '30408'
查询结果:

模糊查询
需求:查询业主名称包含“刘”的业主记录
查询语句:
SELECT
*
FROM
t_owners
WHERE
name LIKE '%刘%'
查询结果:

and运算符
需求:查询业主名称包含“刘”的并且门牌号包含5 的业主记录
查询语句:
SELECT
*
FROM
t_owners
WHERE
name LIKE '%刘%'
AND housenumber LIKE '%5%'
查询结果:

or运算符
需求:查询业主名称包含“刘”的或者门牌号包含5 的业主记录
查询语句:
SELECT
*
FROM
t_owners
WHERE
name LIKE '%刘%'
OR housenumber LIKE '%5%'
查询结果:

and和or运算符混合使用
需求:查询业主名称包含“刘”的或者门牌号包含5 的业主记录,并且地址编号
为3 的记录。
查询语句:
--and 的优先级比or 大,需要用()来改变优先级。
SELECT
*
FROM
t_owners
WHERE
( name LIKE '%刘%' OR housenumber LIKE '%5%' )
AND addressid =3
查询结果:

范围查询
需求:查询台账记录中用水字数大于等于10000,并且小于等于20000 的记录
- 用>= 和<=来实现
查询语句:
SELECT
*
FROM
T_ACCOUNT
WHERE
usenum >= 10000
AND usenum <= 20000
查询结果:

- 用between .. and ..来实现
查询语句:
SELECT
*
FROM
T_ACCOUNT
WHERE
usenum BETWEEN 10000
AND 20000
查询结果:

空值查询
需求1:查询T_PRICETABLE 表中MAXNUM 为空的记录
查询语句:
SELECT
*
FROM
T_PRICETABLE t
WHERE
maxnum IS NULL
查询结果:

需求2:查询T_PRICETABLE 表中MAXNUM 不为空的记录
查询语句:
SELECT
*
FROM
T_PRICETABLE t
WHERE
maxnum IS NOT NULL
查询结果:

去重
需求:查询业主表中的地址ID,不重复显示
查询语句:
SELECT DISTINCT
addressid
FROM
T_OWNERS
查询结果:

排序查询
需求1:对T_ACCOUNT 表按使用量进行升序排序
查询语句:
--默认是升序
SELECT
*
FROM
T_ACCOUNT
ORDER BY
usenum
查询结果:

需求2:对T_ACCOUNT 表按使用量进行降序排序
查询语句:
SELECT
*
FROM
T_ACCOUNT
ORDER BY
usenum DESC
查询结果:

基于伪列的查询
在Oracle 的表的使用过程中,实际表中还有一些附加的列,称为伪列。伪列就
像表中的列一样,但是在表中并不存储。伪列只能查询,不能进行增删改操作。
ROWID
表中的每一行在数据文件中都有一个物理地址,ROWID 伪列返回的就是该行的
物理地址。
使用ROWID 可以快速的定位表中的某一行。
ROWID 值可以唯一的标识表中的一行。
由于ROWID 返回的是该行的物理地址,因此使用ROWID 可以显示行是如何存储的。
查询语句:
SELECT ROWID
,
t.*
FROM
T_AREA t
查询结果:

ROWNUM
在查询 的结果集中,ROWNUMM为结果集中每一行标识一个行号。第一行返回1,第二行返回2...。通过它可以限制查询结果集中返回的行数。
查询语句:
SELECT ROWNUM
,
t.*
FROM
T_OWNERTYPE t
查询结果:

聚合统计
Oralce中的聚合统计是通过分组函数来实现的。
聚合函数
- 求和sum
需求:统计2012 年所有用户的用水量总和
查询语句:
SELECT
sum( usenum )
FROM
t_account
WHERE
year = '2012'
查询结果:

- 求平均avg
需求:统计2012 年所有用水量(字数)的平均值
查询语句:
SELECT
avg(usenum)
FROM
T_ACCOUNT
WHERE
year = '2012'
查询结果:

- 求最大值max
需求:统计2012 年最高用水量(字数)
查询语句:
SELECT
max( usenum )
FROM
T_ACCOUNT
WHERE
year = '2012'
查询结果:

- 求最小值min
需求:统计2012 年最低用水量(字数)
查询语句:
SELECT
min( usenum )
FROM
T_ACCOUNT
WHERE
year = '2012'
查询结果:

- 统计记录个数count
需求:统计业主类型ID 为1 的业主数量
查询语句:
SELECT
count( * )
FROM
T_OWNERS t
WHERE
ownertypeid =1
查询结果:

分组聚合group by
需求:按区域分组统计水费合计数
查询语句:
SELECT
areaid,
sum( money )
FROM
t_account
GROUP BY
areaid
查询结果:

分组后条件查询having
需求:查询水费合计大于16900 的区域及水费合计
查询语句:
SELECT
areaid,
sum( money )
FROM
t_account
GROUP BY
areaid
HAVING
sum( money ) > 169000
查询结果:

连接查询
多表内连接查询
需求1:查询显示业主编号,业主名称,业主类型名称,如下图:

查询语句:
SELECT
o.id 业主编号,
o.name 业主名称,
ot.name 业主类型
FROM
T_OWNERS o,
T_OWNERTYPE ot
WHERE
o.ownertypeid = ot.id
查询结果:

需求2:查询显示业主编号,业主名称、地址和业主类型,如下图

查询语句:
SELECT
o.id 业主编号,
o.name 业主名称,
ad.name 地址,
ot.name 业主类型
FROM
T_OWNERS o,
T_OWNERTYPE ot,
T_ADDRESS ad
WHERE
o.ownertypeid = ot.id
AND o.addressid = ad.id
查询结果:

需求3:查询显示业主编号、业主名称、地址、所属区域、业主分类,如下
图:

查询语句:
SELECT
o.id 业主编号,
o.name 业主名称,
ar.name 区域,
ad.name 地址,
ot.name 业主类型
FROM
T_OWNERS o,
T_OWNERTYPE ot,
T_ADDRESS ad,
T_AREA ar
WHERE
o.ownertypeid = ot.id
AND o.addressid = ad.id
AND ad.areaid = ar.id
查询结果:

需求:查询显示业主编号、业主名称、地址、所属区域、收费员、业主分类,如下图:

查询语句:
SELECT
ow.id 业主编号,
ow.name 业主名称,
ad.name 地址,
ar.name 所属区域,
op.name 收费员,
ot.name 业主类型
FROM
T_OWNERS ow,
T_OWNERTYPE ot,
T_ADDRESS ad,
T_AREA ar,
T_OPERATOR op
WHERE
ow.ownertypeid = ot.id
AND ow.addressid = ad.id
AND ad.areaid = ar.id
AND ad.operatorid = op.id
查询结果:

左外连接查询
需求1:查询业主的账务记录,显示业主编号、名称、年、月、金额。如果此业主没有账务记录也要列出姓名。

分析:业主表为左表、账务表为右表。
按照SQL1999标准的语法,查询语句:
SELECT
ow.id,
ow.name,
ac.year,
ac.month,
ac.money
FROM
T_OWNERS ow
LEFT JOIN T_ACCOUNT ac ON ow.id = ac.owneruuid
查询结果:


按照Oracle提供的语法,查询语句:
如果是左外连接,就在右表所在的条件后面加上(+)
SELECT
ow.id,
ow.name,
ac.year,
ac.month,
ac.money
FROM
T_OWNERS ow,
T_ACCOUNT ac
WHERE
ow.id = ac.owneruuid ( + )
查询结果:
和上面的结果一样
右外连接查询
需求:查询业主的账务记录,显示业主编号、名称、年、月、金额。如果账务记录没有对应的业主信息,也要列出记录。如下图:

按照SQL1999标准的语法,查询语句:
SELECT
ow.id,
ow.name,
ac.year,
ac.month,
ac.money
FROM
T_OWNERS ow
RIGHT JOIN T_ACCOUNT ac ON ow.id = ac.owneruuid
查询结果:

按照Oracle提供的语法,查询语句:
SELECT
ow.id,
ow.name,
ac.year,
ac.month,
ac.money
FROM
T_OWNERS ow,
T_ACCOUNT ac
WHERE
ow.id ( + ) = ac.owneruuid
查询结果:
和上面的结果一样
子查询
where子句中的子查询
单行子查询
-
只返回一条记录
-
单行操作符

需求:查询2012 年1 月用水量大于平均值的台账记录
查询语句:
SELECT
*
FROM
T_ACCOUNT
WHERE
year = '2012'
AND month = '01'
AND usenum > ( SELECT avg( usenum ) FROM T_ACCOUNT WHERE year = '2012' AND month = '01' )
查询结果:

多行子查询
-
可能会返回多条记录
-
多行操作符

in运算符
需求1:查询地址编号为1 、3、4 的业主记录
查询语句:
SELECT
*
FROM
T_OWNERS
WHERE
addressid IN ( 1, 3, 4 )
查询结果:

需求2:查询地址含有“花园”的业主的信息
查询语句:
SELECT
*
FROM
T_OWNERS
WHERE
addressid IN ( SELECT id FROM t_address WHERE name LIKE '%花园%' )
查询结果:

需求3:查询地址不含有“花园”的业主的信息
查询语句:
SELECT
*
FROM
T_OWNERS
WHERE
addressid NOT IN ( SELECT id FROM t_address WHERE name LIKE '%花园%' )
查询结果:

from子句中的子查询
from 子句的子查询为多行子查询
需求:查询显示业主编号,业主名称,业主类型名称,条件为业主类型为”居民”,使用子查询实现。
查询语句:
SELECT
*
FROM
(
SELECT
o.id 业主编号,
o.name 业主名称,
ot.name 业主类型
FROM
T_OWNERS o,
T_OWNERTYPE ot
WHERE
o.ownertypeid = ot.id
)
WHERE
业主类型= '居民'
查询结果:

select子句中的子查询
select 子句的子查询必须为单行子查询
需求1:列出业主信息,包括ID,名称,所属地址。
查询语句:
SELECT
id,
name,
( SELECT name FROM t_address WHERE id = addressid ) addressname
FROM
t_owners
查询结果:

需求2:列出业主信息,包括ID,名称,所属地址,所属区域。
查询语句:
SELECT
id,
name,
( SELECT name FROM t_address WHERE id = addressid ) addressname,
( SELECT ( SELECT name FROM t_area WHERE id = areaid ) FROM t_address WHERE id = addressid ) adrename
FROM
t_owners;
查询结果:


浙公网安备 33010602011771号