一文搞定oracle数据库
Oracle数据库学习指南 摘要:本文介绍了Oracle数据库的学习和使用方法,重点对比了Oracle与MySQL的差异。Oracle作为商业级关系型数据库,适用于企业级应用和高并发场景。文章详细讲解了Oracle的基本概念、数据类型、约束条件、SQL语句操作(增删改查、分页查询)、存储过程、视图、触发器、索引、函数和序列等核心功能。特别提供了Oracle免费版XE的下载安装指南,适合个人学习和小
Oracle(甲骨文公司),主打一款商业级的关系型数据库,甲骨文核心的产品线:1.Java2.Mysql3.Oracle
Oracle:商业性-收费
国内现状:
互联网企业+小微企业:Mysql+PostgreSQL(PG)
大型国企、银行、电网:Oracle|互联网:偏重于Mysqli
传统行业:oracle(老项目)
互联网:头条、阿里、支付宝、百度、腾讯、京东、快手等|快速裂变、用户私域-爆发、海量用户、高并发、
传统行业:用友、金蝶、招商银行、中原银行、交通、国家电网社内部使用、并发量低
1.安装
商业版本的oracle很贵,我们个人学习阶段可以使用官方提供的免费版本
Oracle Database XE(Express Edition) 是 Oracle 官方提供的免费版本,适合个人学习、开发、小型项目甚至轻量级生产使用。
- 免费用于开发和生产(需遵守许可协议)
- 最多使用 2 个 CPU 核心
- 最大 2 GB 用户数据(注意:不是总数据库大小,是用户表数据)
- 最多使用 1 GB RAM
- 支持大部分企业版功能(如 PL/SQL、分区、JSON、XML 等)
下载地址:
https://www.oracle.com/database/technologies/xe-downloads.html
需要oracle账户,这个也很简单,自己注册一个就行,不用去到处找体验账户。
下载之后一路安装就行了,然后用数据库工具(navicat,DBeaver)连接


创建一个个人账户开发,不要使用system系统账户,权限过大
我装的是21版本的,是多租户的模式,切换个服务连接,然后创建角色

然后执行下面的命令创建即可
-- 密码含 @,必须加双引号!
CREATE USER xiao IDENTIFIED BY "FL@5201314";
GRANT CONNECT, RESOURCE TO xiao;
ALTER USER xiao QUOTA UNLIMITED ON USERS;
这样就可以了,用新创建的这个用户连接即可,下面开始使用教程。
2.使用
使用之前我们先来对比下mysql,oracle有哪些区别
| 对比项 | Oracle | MySQL |
|---|---|---|
| 授权模式 | 商业软件(有免费版 XE) | 开源(社区版免费,企业版收费) |
| 默认大小写敏感 | 对象名不区分大小写(存为大写) 密码区分 |
Linux 下:表名区分大小写 Windows/macOS:不区分 列名/值通常不区分(取决于 collation) |
| 自增主键 | 12c 前:需 SEQUENCE + 触发器12c+:支持 IDENTITY 列 |
原生支持 AUTO_INCREMENT |
| 事务支持 | 完全 ACID,默认不自动提交 (需显式 COMMIT) |
InnoDB 引擎支持 ACID 默认自动提交(可关闭) |
| 默认隔离级别 | READ COMMITTED |
REPEATABLE READ |
| 字符串类型 | VARCHAR2(n)(最大 4000/32767)CHAR 定长 |
VARCHAR(n)(最大 65535)CHAR 定长 |
| 日期类型 | DATE(含时分秒)TIMESTAMP(更高精度) |
DATETIME(含时分秒)TIMESTAMP(带时区转换) |
| 分页机制 | 无 LIMIT,用 ROWNUM 或 FETCH(12c+) |
原生支持 LIMIT offset, size |
| 空值处理 | NULL 与空字符串 '' 视为相同 |
NULL 与 '' 是不同值 |
| 默认端口 | 1521 | 3306 |
| 管理工具 | SQL Developer(官方免费) | MySQL Workbench(官方免费) |
oracle使用场景如下:
| 场景 | 推荐 |
|---|---|
| 企业级应用、高并发、强一致性 | Oracle(功能强大,稳定性高) |
| Web 应用、快速开发、成本敏感 | MySQL(生态丰富,上手快) |
| 学习 SQL 标准 | 两者都学,注意分页、自增、事务差异 |
2.1基本概念和类型
Oracle的约束条件:
1.主键约束,2.外键约束,3.默认约束,4.⾮空约束,5.unique 唯⼀约束,Oracle没有⾃增约束
数值类型
| 类型 | 说明 | 示例 |
|---|---|---|
NUMBER(p, s) |
最常用!p=总位数(1~38),s=小数位(-84~127) |
NUMBER(10,2) 表示最多 8 位整数 + 2 位小数 |
INTEGER |
NUMBER(38) 的别名,无小数 |
INTEGER |
FLOAT(b) |
二进制精度浮点数,b 是二进制位(1~126) |
FLOAT(10) |
BINARY_FLOAT / BINARY_DOUBLE |
IEEE 754 单/双精度浮点(10g+) | 高性能科学计算 |
DECIMAL, NUMERIC |
同 NUMBER,兼容 SQL 标准 |
字符串类型
| 类型 | 最大长度 | 说明 |
|---|---|---|
CHAR(n) |
2000 字节 | 定长,不足补空格(查询时自动去尾空格) |
VARCHAR2(n) |
4000 字节(12c 之前) 32767 字节(12c+ 开启 extended) |
变长,推荐用于所有字符串字段 |
NCHAR(n) |
2000 字符 | 定长 Unicode(国家字符集) |
NVARCHAR2(n) |
4000 字符 | 变长 Unicode |
LONG |
2GB | 已废弃! 不能用于索引、不能在 WHERE 中使用 |
日期时间类型
| 类型 | 精度 | 说明 |
|---|---|---|
| date | 秒级 | 包含 年月日时分秒(不含时区) ✅ 最常用 |
| timestamp | 纳秒级(默认 6 位小数) | 比 DATE 更精确 |
TIMESTAMP WITH TIME ZONE |
带时区 | 存储时区信息(如 +08:00) |
TIMESTAMP WITH LOCAL TIME ZONE |
本地时区转换 | 自动转为数据库时区 |
INTERVAL YEAR TO MONTH |
年-月间隔 | 如 INTERVAL '2-3' YEAR TO MONTH |
INTERVAL DAY TO SECOND |
日-秒间隔 | 如 INTERVAL '5 12:30:45' DAY TO SECOND |
大对象类型
| 类型 | 最大容量 | 用途 |
|---|---|---|
CLOB |
128TB | 存储大文本(如文章、JSON) |
NCLOB |
128TB | Unicode 大文本 |
BLOB |
128TB | 存储二进制数据(图片、PDF、视频) |
BFILE |
操作系统文件指针 | 指向数据库外部的文件 |
1. 主键约束(PRIMARY KEY)
- 自动创建 唯一索引
- 不允许 NULL
- 一个表只能有一个主键
CREATE TABLE users (
id NUMBER PRIMARY KEY,
name VARCHAR2(50)
);
2. 唯一约束(UNIQUE)
- 允许 NULL(且多个 NULL 不冲突)
- 自动创建唯一索引
ALTER TABLE users ADD CONSTRAINT uk_email UNIQUE(email);
3. 非空约束(NOT NULL)
- 只能定义在列级别(不能表级)
- 不会创建索引
name VARCHAR2(50) NOT NULL
4. 外键约束(FOREIGN KEY)
- 默认行为:禁止删除父记录(
ON DELETE NO ACTION) - 可选:
ON DELETE CASCADE(级联删除) - 可选:
ON DELETE SET NULL(设为空)
CREATE TABLE orders (
user_id NUMBER REFERENCES users(id) ON DELETE CASCADE
);
外键列必须有索引(否则 DML 性能极差)
5. 默认值(DEFAULT)
- 插入时若未指定值,则用默认值
- 不会阻止插入 NULL(除非同时加
NOT NULL)
created_at DATE DEFAULT SYSDATE
6. 检查约束(CHECK)
这是非常重要的约束类型:
ALTER TABLE employees
ADD CONSTRAINT chk_salary CHECK (salary > 0 AND salary < 100000);
- 可用于验证业务规则
- 支持复杂表达式(但不能用子查询、SYSDATE 等非确定性函数)
7.自增主键
序列直接作为默认值(12c+ 以上)
CREATE TABLE users (
id NUMBER DEFAULT seq_user_id.NEXTVAL PRIMARY KEY,
name VARCHAR2(50)
);
IDENTITY 列(新版本推荐)
CREATE TABLE users (
id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR2(50)
);
-- 或
id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY
2.2sql语句
2.2.1创建表
create table t_user(
id NUMBER primary key,
phone varchar2(11),
pass VARCHAR2(20),
ctime date
);
2.2.2新增
insert into t_user(id,phone,pass,ctime) values(1,'110','66666',
TO_DATE('2020-01-01 12:00:00', 'yyyy-MM-dd HH:mi:ss'));
insert into t_user(id,phone,pass,ctime) values(2,'210','66666',
TO_DATE('2020-01-01 12:00:00', 'yyyy-MM-dd HH:mi:ss'));
2.2.3查询
select * from t_user;
select * from t_user where id in (12);
select * from t_user where phone like '1%';
--子查询和联合查询都和mysql一致
2.2.4修改
update t_user set pass='168' where id=1;
2.2.5删除
delete FROM t_user where id=1;
2.2.6分页查询
oracle11版本之前:
-- 查询第 0~10 条
SELECT * FROM (
SELECT a.*, ROWNUM rn FROM (
SELECT * FROM t_users ORDER BY id
) a WHERE ROWNUM <= 10
) WHERE rn > 0;
执行效果如下:

ROWNUM是 Oracle 伪列,从 1 开始编号- 不能直接写
ROWNUM > 20(因为 ROWNUM 在过滤前生成,>20 永远为空) - 必须嵌套两层:先限制上限(≤30),再过滤下限(>20)
Oracle 12c 及以上 —— 标准 SQL 分页
-- 查询第 1~10 条
SELECT * FROM users
ORDER BY id
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
- 语法清晰,接近 MySQL 的
LIMIT - 符合 SQL 标准
- 性能优化更好
执行效果如下:

注意这种适用于数据量小的情况下,有深分页问题
数据库 高效分页建议 MySQL ORDER BY 索引列 LIMIT N
避免深度分页(如LIMIT 1000000, 10)Oracle (11g) 同样避免深度分页,考虑用“游标分页”(基于上一页最大 ID) Oracle (12c+) 优先用 OFFSET/FETCH,但深度分页仍慢
2.2.7分组查询、聚合函数
select count(*),max(id),min(id),avg(id),sum(id) from t_user;
group by --分组
having --限制
max min avg sum count -- 聚合函数
2.3存储过程
接下来代码展示
设置自增主键:
-- 创建序列,从 3 开始,每次加 1 因为我已经加了两条数据
CREATE SEQUENCE seq_t_user_id
START WITH 3
INCREMENT BY 1
NOCACHE;
插入用户:
CREATE OR REPLACE PROCEDURE proc_insert_user(
p_phone IN VARCHAR2,
p_pass IN VARCHAR2
)
AS
BEGIN
-- 简单插入(实际项目建议对密码加密,如用 DBMS_CRYPTO)
INSERT INTO t_user (id, phone, pass, ctime)
VALUES (seq_t_user_id.NEXTVAL, p_phone, p_pass, SYSDATE);
COMMIT; -- 显式提交(可选,也可由调用者控制)
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
RAISE_APPLICATION_ERROR(-20001, '手机号已存在(假设 phone 唯一)');
WHEN OTHERS THEN
ROLLBACK;
RAISE; -- 抛出原始错误
END;
/
调用:
BEGIN
proc_insert_user('13800138000', 'mypass123');
END;
/
我们来看下执行效果:


我们可以看到调用存储过程成功。
2.4视图
-- 直接创建视图:取前 2 条(按 id 排序)
CREATE VIEW v_u AS
SELECT *
FROM t_user
ORDER BY id
FETCH FIRST 2 ROWS ONLY;
--使⽤视图
select * from v_u;
--删除视图
drop VIEW v_u;
2.5触发器
--创建
create trigger t_triu after insert on t_user
for each row
begin
insert into t_userlog(id,userid,content,ctime)
values(:NEW.id,:NEW.id,'新增了⽤户-',to_date('2021-03-01','yyyy-MM-dd'));
end;
--触发使⽤
insert into t_user(id,phone,pass,ctime)
values(3,'120','abcd',to_date('2021-03-01','yyyy-MM-dd'));
select * from t_userlog;
--删除
drop trigger t_triu;
2.6索引
-- 普通索引
CREATE INDEX idx_user_phone ON t_user(phone);
-- 函数索引
CREATE INDEX idx_user_upper_phone ON t_user(UPPER(phone));
-- 位图索引(企业版)
CREATE BITMAP INDEX idx_user_gender ON t_user(gender);
之后准备单独出一篇文章将索引,这不在仔细描述
2.7函数
-- 函数
create FUNCTION f_u(n1 NUMBER,n2 NUMBER) return NUMBER
as
begin
return n1+n2;
end;
--使⽤
select f_u(id,userid) from t_userlog;
-- 删除
drop FUNCTION f_u;
2.8序列
-- 序列
create sequence 序列名称
increment by 增量
start with 起始值
max|min 最⼤|最⼩
cache|nocache 是否缓存
cycle|nocycle 是否循环
--创建
create sequence seq_id;
--使⽤序列
insert into t_userlog(id,userid,content,ctime)
values(seq_id.nextval,1,'测试序列',to_date('2021-03-01','yyyy-MMdd'));
select seq_id.currval from t_userlog;
--删除
drop sequence seq_id;
重要属性:
nextval:下⼀个值
currval:当前值
更多推荐
所有评论(0)