本文总结了Oracle数据库中子查询和表操作的关键知识点。
子查询部分介绍了WHERE和FROM后的子查询用法,包括单值、单列返回形式及典型应用场景。
表操作部分涵盖创建、维护(重命名、增删列等)以及CRUD操作(增删改查),特别说明了不同删除方式的区别。
连接查询部分详细讲解了内连接和左右外连接的使用方法。
最后提供了4个综合练习题,涉及薪资比较、部门筛选等常见查询需求。
本文可作为Oracle数据库操作的快速复习资料。
Oracle 子查询与表操作复习笔记
一、子查询
1. 子查询的返回形式
-
返回一个固定值(一行一列)
-
返回一列内容(多行一列)
2. WHERE 后面的子查询
使用场景:筛选条件未知,需通过子查询动态获取。
示例1:找出与 SMITH 同部门的员工(不包括 SMITH)
sql
SELECT * FROM EMP
WHERE DEPTNO = (SELECT DEPTNO FROM EMP WHERE ENAME = 'SMITH')
AND ENAME <> 'SMITH';
示例2:薪资比 ALLEN 高的员工
sql
SELECT * FROM EMP
WHERE SAL > (SELECT SAL FROM EMP WHERE ENAME = 'ALLEN');
示例3:岗位在 10 号部门岗位列表中,但不在 10 号部门的员工
sql
SELECT * FROM EMP
WHERE JOB IN (SELECT JOB FROM EMP WHERE DEPTNO = 10)
AND DEPTNO <> 10;
3. FROM 后面的子查询(嵌套子查询)
原理:每个 SELECT 的结果都是一张表,可以放在 FROM 后面继续查询。
示例1:薪资不低于 1000 且岗位是销售的员工
sql
SELECT * FROM
(SELECT * FROM EMP WHERE SAL >= 1000)
WHERE JOB = 'SALESMAN';
示例2:比 20 号部门所有员工薪资都高的员工
sql
SELECT * FROM EMP
WHERE SAL > (
SELECT SAL FROM
(SELECT SAL FROM EMP WHERE DEPTNO = 20 ORDER BY SAL DESC)
WHERE ROWNUM <= 1
);
二、表的创建与维护
1. 创建表
sql
CREATE TABLE 表名 (
列名 数据类型,
列名 数据类型,
...
);
表名可以是中文,但一般都使用英文。
常见数据类型:
| 类型 | 说明 |
|---|---|
| NUMBER | 数值 |
| NUMBER(4) | 整数,范围 -9999~9999 |
| NUMBER(7,3) | 小数,整数4位,小数3位 *** ** * ** *** 第一个参数表示的是总长度,第二个参数是小数位 |
| VARCHAR2(X) | 变长字符串,最大4000 |
| CHAR(X) | 定长字符串 |
| DATE | 日期 |
NUMBER 核心特性:
可存储任意精度的数值(整数/小数/科学计数法)
最大精度 38位
是 Oracle 的默认数值类型
示例:学生信息表
sql
CREATE TABLE STUDENT_INFO (
SNAME VARCHAR2(20),
SEX VARCHAR2(10),
AGE NUMBER(3),
BIRTHDAY DATE
);
2. 表结构维护
| 操作 | 语法 |
|---|---|
| 表重命名 | RENAME 旧名 TO 新名; |
| 列重命名 | ALTER TABLE 表名 RENAME COLUMN 旧列名 TO 新列名; |
| 添加列 | ALTER TABLE 表名 ADD 列名 数据类型; |
| 删除列 | ALTER TABLE 表名 DROP COLUMN 列名; |
| 修改列类型 | ALTER TABLE 表名 MODIFY (列名 新数据类型); |
三、表的增删改查(CRUD)
1. 增(INSERT)
方式一:直接插入
sql
INSERT INTO 表名 VALUES (值1, 值2, ...);
COMMIT; -- 提交事务
方式二:从查询结果插入
sql
INSERT INTO 表名
SELECT 列1, 列2, ... FROM 另一张表;
COMMIT;
2. 改(UPDATE)
sql
UPDATE 表名
SET 列1 = 新值, 列2 = 新值
WHERE 条件;
COMMIT;
3. 删(DELETE / TRUNCATE / DROP)
| 方式 | 说明 | 是否可回滚 | 是否重置水位线 |
|---|---|---|---|
| DELETE | 删除部分或全部数据 | 是 | 否 |
| TRUNCATE | 清空表数据,保留结构 | 否 | 是 |
| DROP | 删除表结构和数据 | 否 | - |
区别:
- DELETE 是(DML)需要 提交的 而 TRUNCATE / DROP (DDL)不需要;
- DELETE 支持部分删除的,但是 TRUNCATE & DROP 都是全表删除;
- DELETE 跟 TRUNCATE 都是删除表数据 表结构还在
- DROP 不仅删除表数据 连带表结构全部都删了
- DELETE 不会重置表的水位线 容易导致 HWM(高水位线) 以及频繁使用会导致表的查询性能变差。
- TRUNCATE 会重置表的水位线,不影响下一次的查询性能。
示例:
sql
DELETE FROM STUDENT_INFO WHERE AGE < 30;
COMMIT;
TRUNCATE TABLE STUDENT_INFO;
DROP TABLE STUDENT_INFO;
💡 面试题:如何快速删除10亿表中的8亿条数据?
答:创建新表,保留2亿条数据,删除原表,重命名新表。
创建一张同结构的表,然后把需要保留的数据2亿条写到这个表,把原有的 10亿数据表 DROP 掉,然后再把新建表 RENAME 就行了。
4. 查(SELECT)
sql
SELECT * FROM 表名;
四、连接查询
1. 内连接(INNER JOIN)
特点:只返回满足连接条件的行。
sql
SELECT 字段
FROM 表A
INNER JOIN 表B ON 连接条件;
示例:员工姓名、薪资、部门名称
sql
SELECT ENAME, SAL, DNAME
FROM EMP E
INNER JOIN DEPT D ON E.DEPTNO = D.DEPTNO;
2. 外连接
左外连接(LEFT JOIN)
-
左表为主表,数据不丢失
-
右表无匹配则显示 NULL
sql
SELECT 字段
FROM 表A
LEFT JOIN 表B ON 连接条件;
右外连接(RIGHT JOIN)
-
右表为主表
-
等价于
B LEFT JOIN A
sql
SELECT 字段
FROM 表A
RIGHT JOIN 表B ON 连接条件;
示例:找出没有员工的部门
sql
SELECT D.*
FROM DEPT D
LEFT JOIN EMP E ON E.DEPTNO = D.DEPTNO
WHERE E.DEPTNO IS NULL;
五、综合练习题(含答案)
练习1:月薪比 MARTIN 高的员工
sql
SELECT * FROM EMP
WHERE SAL + NVL(COMM, 0) > (
SELECT SAL FROM EMP WHERE ENAME = 'MARTIN'
);
练习2:30号部门中薪资≥1500的销售
sql
SELECT * FROM
(SELECT * FROM EMP WHERE DEPTNO = 30 AND JOB = 'SALESMAN')
WHERE SAL >= 1500;
练习3:1981年入职且办公地点不在 CHICAGO 的员工
sql
SELECT ENAME, SAL, COMM, SAL+NVL(COMM,0) AS 月薪, DNAME
FROM DEPT D
JOIN EMP E ON E.DEPTNO = D.DEPTNO
WHERE TO_CHAR(HIREDATE, 'YYYY') = 1981 AND LOC <> 'CHICAGO';
练习4:不在 NEW YORK 办公的员工(包括无员工部门)
sql
SELECT LOC, ENAME, SAL, D.DEPTNO
FROM DEPT D
LEFT JOIN EMP E ON E.DEPTNO = D.DEPTNO
WHERE LOC <> 'NEW YORK';