【数据库】【Oracle】SQL基础

Oracle SQL 基础完整指南

Oracle SQL 是管理和操作 Oracle 数据库的核心语言。本指南从基础到进阶,系统介绍最常用的 SQL 概念和操作。


一、基础查询(SELECT)

1.1 基本语法结构

sql 复制代码
SELECT [DISTINCT] 列1, 列2, ...
FROM 表名
[WHERE 条件]
[ORDER BY 排序列];

1.2 简单查询示例

sql 复制代码
-- 查询所有列
SELECT * FROM employees;

-- 查询指定列
SELECT employee_id, first_name, last_name, salary FROM employees;

-- 使用别名(AS可省略)
SELECT employee_id AS "员工编号", first_name || ' ' || last_name AS "姓名"
FROM employees;

-- 去除重复行
SELECT DISTINCT department_id FROM employees;

-- 查询常量(使用DUAL伪表)
SELECT 'Hello Oracle' AS greeting, 100*2 AS result FROM dual;

Oracle 特点|| 是字符串连接符,DUAL 是系统伪表,用于查询常量或表达式。


二、过滤数据(WHERE)

2.1 比较运算符

sql 复制代码
SELECT * FROM employees WHERE salary > 10000;
SELECT * FROM employees WHERE hire_date >= DATE '2020-01-01';
SELECT * FROM employees WHERE job_id = 'IT_PROG';
SELECT * FROM employees WHERE commission_pct IS NOT NULL;  -- 判断空值

2.2 逻辑运算符

sql 复制代码
-- AND、OR、NOT
SELECT * FROM employees 
WHERE department_id = 80 AND salary > 8000;

SELECT * FROM employees 
WHERE department_id = 80 OR job_id = 'MANAGER';

SELECT * FROM employees 
WHERE NOT commission_pct IS NULL;

2.3 范围与集合查询

sql 复制代码
-- BETWEEN...AND(包含边界)
SELECT * FROM employees WHERE salary BETWEEN 5000 AND 8000;

-- IN(在集合中)
SELECT * FROM employees WHERE department_id IN (10, 20, 30);

-- LIKE(模糊匹配),%匹配任意字符,_匹配单个字符
SELECT * FROM employees WHERE first_name LIKE 'S%';  -- 以S开头
SELECT * FROM employees WHERE first_name LIKE '_a%';  -- 第二个字母是a

三、排序(ORDER BY)

sql 复制代码
-- 默认升序(ASC)
SELECT * FROM employees ORDER BY salary;

-- 降序(DESC)
SELECT * FROM employees ORDER BY salary DESC;

-- 多列排序
SELECT * FROM employees 
ORDER BY department_id ASC, salary DESC;

-- 按表达式排序
SELECT employee_id, salary*12 AS annual_salary 
FROM employees 
ORDER BY annual_salary DESC;

-- 按列位置排序(不推荐)
SELECT employee_id, first_name, salary FROM employees ORDER BY 3 DESC;

四、聚合函数与分组

4.1 常用聚合函数

sql 复制代码
SELECT 
    COUNT(*) AS total_employees,
    COUNT(commission_pct) AS with_commission,  -- 不计NULL
    SUM(salary) AS total_salary,
    AVG(salary) AS avg_salary,
    MAX(salary) AS max_salary,
    MIN(salary) AS min_salary
FROM employees;

4.2 GROUP BY 分组

sql 复制代码
-- 按部门统计
SELECT 
    department_id,
    COUNT(*) AS emp_count,
    AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id;

-- 多列分组
SELECT department_id, job_id, COUNT(*) AS emp_count
FROM employees
GROUP BY department_id, job_id;

4.3 HAVING 过滤分组结果

sql 复制代码
-- 注意:HAVING 在 GROUP BY 后执行,WHERE 在 GROUP BY 前执行
SELECT department_id, AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
HAVING AVG(salary) > 8000
ORDER BY avg_salary DESC;

关键区别WHERE 过滤行,HAVING 过滤分组。


五、多表连接(JOIN)

5.1 内连接(INNER JOIN)

sql 复制代码
-- 查询员工及所在部门信息
SELECT e.employee_id, e.first_name, d.department_name
FROM employees e
INNER JOIN departments d ON e.department_id = d.department_id;

-- 隐式内连接(Oracle旧语法,不推荐)
SELECT e.employee_id, e.first_name, d.department_name
FROM employees e, departments d
WHERE e.department_id = d.department_id;

5.2 左外连接(LEFT JOIN)

sql 复制代码
-- 查询所有部门,包括没有员工的部门
SELECT d.department_id, d.department_name, COUNT(e.employee_id) AS emp_count
FROM departments d
LEFT JOIN employees e ON d.department_id = e.department_id
GROUP BY d.department_id, d.department_name;

5.3 右外连接(RIGHT JOIN)和全外连接(FULL JOIN)

sql 复制代码
-- 右外连接
SELECT e.employee_id, d.department_name
FROM employees e
RIGHT JOIN departments d ON e.department_id = d.department_id;

-- 全外连接(Oracle支持FULL OUTER JOIN)
SELECT e.employee_id, d.department_name
FROM employees e
FULL OUTER JOIN departments d ON e.department_id = d.department_id;

5.4 自连接

sql 复制代码
-- 查询员工及其经理
SELECT e.first_name AS employee, m.first_name AS manager
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.employee_id;

5.5 交叉连接(CROSS JOIN)

sql 复制代码
-- 生成笛卡尔积(慎用)
SELECT * FROM employees CROSS JOIN departments;

六、子查询

6.1 单行子查询

sql 复制代码
-- 查询工资高于平均工资的员工
SELECT * FROM employees 
WHERE salary > (SELECT AVG(salary) FROM employees);

6.2 多行子查询

sql 复制代码
-- 查询部门名称为'Sales'或'Marketing'的所有员工
SELECT * FROM employees
WHERE department_id IN (
    SELECT department_id FROM departments 
    WHERE department_name IN ('Sales', 'Marketing')
);

-- 使用ANY/SOME
SELECT * FROM employees
WHERE salary > ANY (SELECT salary FROM employees WHERE department_id = 80);

-- 使用ALL
SELECT * FROM employees
WHERE salary > ALL (SELECT AVG(salary) FROM employees GROUP BY department_id);

6.3 相关子查询

sql 复制代码
-- 查询工资高于本部门平均工资的员工
SELECT e1.first_name, e1.salary, e1.department_id
FROM employees e1
WHERE e1.salary > (
    SELECT AVG(e2.salary) 
    FROM employees e2 
    WHERE e2.department_id = e1.department_id  -- 与外层关联
);

七、集合操作

sql 复制代码
-- UNION:并集(去重)
SELECT employee_id FROM employees WHERE department_id = 80
UNION
SELECT employee_id FROM employees WHERE salary > 10000;

-- UNION ALL:并集(保留重复)
SELECT employee_id FROM employees WHERE department_id = 80
UNION ALL
SELECT employee_id FROM employees WHERE salary > 10000;

-- INTERSECT:交集
SELECT employee_id FROM employees WHERE department_id = 80
INTERSECT
SELECT employee_id FROM employees WHERE salary > 10000;

-- MINUS:差集(Oracle特有,MySQL用NOT IN)
SELECT employee_id FROM employees WHERE department_id = 80
MINUS
SELECT employee_id FROM employees WHERE salary > 10000;

八、常用函数

8.1 字符串函数

sql 复制代码
-- 连接
SELECT first_name || ' ' || last_name FROM employees;

-- 长度
SELECT LENGTH('Oracle SQL') FROM dual;  -- 返回10

-- 大小写转换
SELECT UPPER('oracle'), LOWER('SQL'), INITCAP('hello world') FROM dual;

-- 截取
SELECT SUBSTR('Oracle SQL', 1, 6) FROM dual;  -- 返回'Oracle'

-- 查找
SELECT INSTR('Oracle SQL', 'SQL') FROM dual;  -- 返回8

-- 替换
SELECT REPLACE('Oracle SQL', 'SQL', 'Database') FROM dual;

-- 填充
SELECT LPAD('123', 5, '0'), RPAD('456', 5, '*') FROM dual;  -- 返回'00123', '456**'

8.2 数值函数

sql 复制代码
-- 四舍五入
SELECT ROUND(123.456, 2), ROUND(123.456, 0), ROUND(123.456, -2) FROM dual;

-- 向上/向下取整
SELECT CEIL(123.1), FLOOR(123.9) FROM dual;

-- MOD取模
SELECT MOD(10, 3) FROM dual;  -- 返回1

-- TRUNC截断
SELECT TRUNC(123.456, 2), TRUNC(123.456) FROM dual;

8.3 日期函数

sql 复制代码
-- 当前日期和时间
SELECT SYSDATE, SYSTIMESTAMP FROM dual;

-- 日期加减(单位:天)
SELECT SYSDATE + 1 AS tomorrow FROM dual;  -- 加1天
SELECT SYSDATE - 1/24 AS one_hour_ago FROM dual;  -- 减1小时

-- 月份加减
SELECT ADD_MONTHS(SYSDATE, 3) FROM dual;  -- 加3个月

-- 月份差
SELECT MONTHS_BETWEEN(SYSDATE, hire_date) FROM employees;

-- 年月提取
SELECT EXTRACT(YEAR FROM SYSDATE) AS year,
       EXTRACT(MONTH FROM SYSDATE) AS month,
       EXTRACT(DAY FROM SYSDATE) AS day
FROM dual;

-- 日期格式化
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') FROM dual;

8.4 转换函数

sql 复制代码
-- 数字转字符串
SELECT TO_CHAR(1234567.89, 'L999,999,999.99') FROM dual;  -- 本地货币格式

-- 字符串转数字
SELECT TO_NUMBER('12345') FROM dual;

-- 字符串转日期
SELECT TO_DATE('2023-12-25', 'YYYY-MM-DD') FROM dual;

-- 类型转换
SELECT CAST('123' AS NUMBER), CAST(SYSDATE AS VARCHAR2(20)) FROM dual;

九、数据操作(DML)

9.1 INSERT 插入

sql 复制代码
-- 插入单行
INSERT INTO employees (employee_id, first_name, last_name, email, hire_date, job_id)
VALUES (101, 'John', 'Doe', 'JDOE', SYSDATE, 'IT_PROG');

-- 插入多行(Oracle 23c 支持,旧版需用 INSERT ALL)
INSERT INTO departments (department_id, department_name)
VALUES (280, 'Data Science'), (290, 'Cloud Engineering');

-- 从查询结果插入
INSERT INTO employees_archive
SELECT * FROM employees WHERE hire_date < DATE '2010-01-01';

9.2 UPDATE 更新

sql 复制代码
-- 更新单列
UPDATE employees SET salary = salary * 1.1 WHERE employee_id = 101;

-- 更新多列
UPDATE employees 
SET salary = salary * 1.1, commission_pct = 0.2
WHERE job_id = 'SA_MAN';

-- 基于子查询更新
UPDATE employees e
SET e.salary = (SELECT AVG(salary) FROM employees WHERE department_id = e.department_id)
WHERE e.job_id = 'MANAGER';

9.3 DELETE 删除

sql 复制代码
-- 删除行
DELETE FROM employees WHERE employee_id = 101;

-- 基于子查询删除
DELETE FROM employees
WHERE department_id = (SELECT department_id FROM departments WHERE department_name = 'Temp');

-- 清空表(保留结构)
TRUNCATE TABLE employees_temp;  -- 比 DELETE 快,不可回滚

9.4 MERGE 合并(Oracle独有)

sql 复制代码
-- 根据条件插入或更新
MERGE INTO employees e
USING (SELECT 101 AS emp_id, 'Jane' AS f_name FROM dual) src
ON (e.employee_id = src.emp_id)
WHEN MATCHED THEN
    UPDATE SET e.first_name = src.f_name
WHEN NOT MATCHED THEN
    INSERT (employee_id, first_name, last_name)
    VALUES (src.emp_id, src.f_name, 'Smith');

十、数据定义(DDL)

10.1 CREATE TABLE 创建表

sql 复制代码
-- 基本建表
CREATE TABLE employees_temp (
    employee_id NUMBER(6) PRIMARY KEY,
    first_name VARCHAR2(20),
    last_name VARCHAR2(25) NOT NULL,
    email VARCHAR2(25) UNIQUE,
    hire_date DATE DEFAULT SYSDATE,
    salary NUMBER(8,2) CHECK (salary > 0),
    department_id NUMBER(4),
    CONSTRAINT emp_dept_fk FOREIGN KEY (department_id) REFERENCES departments(department_id)
);

-- 创建表时带约束
CREATE TABLE orders (
    order_id NUMBER CONSTRAINT order_pk PRIMARY KEY,
    customer_id NUMBER NOT NULL,
    order_date DATE DEFAULT SYSDATE,
    status VARCHAR2(20) CONSTRAINT status_check CHECK (status IN ('NEW', 'SHIPPED', 'CANCELLED'))
);

10.2 ALTER TABLE 修改表

sql 复制代码
-- 添加列
ALTER TABLE employees ADD (phone_number VARCHAR2(20));

-- 修改列
ALTER TABLE employees MODIFY (first_name VARCHAR2(50));

-- 删除列
ALTER TABLE employees DROP COLUMN phone_number;

-- 添加约束
ALTER TABLE employees ADD CONSTRAINT emp_salary_check CHECK (salary > 0);

-- 删除约束
ALTER TABLE employees DROP CONSTRAINT emp_salary_check;

10.3 DROP TABLE 删除表

sql 复制代码
-- 删除表
DROP TABLE employees_temp;

-- 级联删除(删除约束)
DROP TABLE departments CASCADE CONSTRAINTS;

10.4 CREATE INDEX 创建索引

sql 复制代码
-- 单列索引
CREATE INDEX emp_last_name_idx ON employees(last_name);

-- 唯一索引
CREATE UNIQUE INDEX emp_email_idx ON employees(email);

-- 复合索引
CREATE INDEX emp_dept_salary_idx ON employees(department_id, salary);

-- 函数索引
CREATE INDEX emp_upper_name_idx ON employees(UPPER(first_name));

十一、约束(Constraints)

sql 复制代码
-- 主键(PRIMARY KEY)
CONSTRAINT emp_pk PRIMARY KEY (employee_id)

-- 外键(FOREIGN KEY)
CONSTRAINT emp_dept_fk FOREIGN KEY (department_id) REFERENCES departments(department_id)
    ON DELETE CASCADE  -- 级联删除
    ON UPDATE SET NULL -- 父表更新时设为NULL

-- 唯一(UNIQUE)
CONSTRAINT emp_email_uk UNIQUE (email)

-- 非空(NOT NULL)
last_name VARCHAR2(25) NOT NULL

-- 检查(CHECK)
CONSTRAINT emp_salary_check CHECK (salary > 0 AND salary < 999999)

-- 默认(DEFAULT)
hire_date DATE DEFAULT SYSDATE

十二、视图(VIEW)

sql 复制代码
-- 创建视图
CREATE VIEW emp_details AS
SELECT e.employee_id, e.first_name, d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id
WHERE e.salary > 5000;

-- 使用视图
SELECT * FROM emp_details WHERE department_name = 'Sales';

-- 创建只读视图(WITH READ ONLY)
CREATE VIEW emp_readonly AS
SELECT * FROM employees
WITH READ ONLY;

-- 删除视图
DROP VIEW emp_details;

十三、事务控制(TCL)

13.1 自动提交与手动提交

sql 复制代码
-- 查看自动提交状态(SQL*Plus)
SHOW AUTOCOMMIT;

-- 关闭自动提交
SET AUTOCOMMIT OFF;

13.2 事务操作

sql 复制代码
-- 开始事务(Oracle自动开始)
UPDATE employees SET salary = 10000 WHERE employee_id = 101;

-- 保存点
SAVEPOINT update_salary;

-- 回滚到保存点
ROLLBACK TO update_salary;

-- 提交事务
COMMIT;

-- 回滚整个事务
ROLLBACK;

十四、Oracle 特有功能

14.1 伪列

sql 复制代码
-- ROWNUM:行号(结果集序号,查询时动态生成)
SELECT * FROM employees WHERE ROWNUM <= 10;  -- 取前10行

-- ROWID:物理地址(每行唯一)
SELECT ROWID, employee_id FROM employees;

-- 分页查询(ROWNUM方式)
SELECT * FROM (
    SELECT e.*, ROWNUM rn FROM (
        SELECT * FROM employees ORDER BY salary DESC
    ) e WHERE ROWNUM <= 20
) WHERE rn > 10;  -- 第11-20行(第2页)

14.2 序列(SEQUENCE)

sql 复制代码
-- 创建序列
CREATE SEQUENCE emp_seq
    START WITH 1
    INCREMENT BY 1
    NOCACHE
    NOCYCLE;

-- 使用序列
SELECT emp_seq.NEXTVAL FROM dual;  -- 下一个值
SELECT emp_seq.CURRVAL FROM dual;  -- 当前值

-- 插入时使用
INSERT INTO employees (employee_id, first_name)
VALUES (emp_seq.NEXTVAL, 'John');

14.3 同义词(SYNONYM)

sql 复制代码
-- 创建同义词(简化对象访问)
CREATE SYNONYM emp FOR hr.employees;

-- 使用同义词
SELECT * FROM emp;

-- 删除同义词
DROP SYNONYM emp;

十五、常用查询技巧

15.1 分页查询(Oracle 12c+ 新语法)

sql 复制代码
-- 推荐使用 OFFSET FETCH(Oracle 12c+)
SELECT * FROM employees
ORDER BY employee_id
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;  -- 第11-20行

15.2 递归查询(层次查询)

sql 复制代码
-- 查询员工及其上级(树形结构)
SELECT 
    employee_id, 
    first_name, 
    manager_id,
    LEVEL
FROM employees
START WITH manager_id IS NULL  -- 从根节点开始
CONNECT BY PRIOR employee_id = manager_id;  -- 递归条件

15.3 分析函数(窗口函数)

sql 复制代码
-- 计算每个部门的工资排名
SELECT 
    employee_id,
    department_id,
    salary,
    RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS dept_rank,
    AVG(salary) OVER (PARTITION BY department_id) AS dept_avg_salary
FROM employees;

十六、学习建议与路径

16.1 初学者必经阶段

  1. 基础查询:SELECT, WHERE, ORDER BY(1-2天)
  2. 多表连接:JOIN, 子查询(2-3天)
  3. 聚合分组:GROUP BY, HAVING(1天)
  4. 数据操作:INSERT, UPDATE, DELETE(1天)
  5. DDL操作:CREATE, ALTER, DROP(1天)
  6. 高级函数:字符串、日期、转换(2-3天)
  7. 事务与约束:事务控制、约束管理(1天)

16.2 进阶方向

  • 分析函数与窗口函数
  • PL/SQL 存储过程与函数
  • 性能优化(索引、执行计划)
  • 分区表与大表设计
  • 闪回查询与数据恢复

16.3 实践建议

  • ✅ 安装本地 Oracle XE 或 Docker 版本练习
  • ✅ 使用 SQL*Plus 或 SQL Developer 工具
  • ✅ 从简单的单表查询开始,逐步增加复杂度
  • ✅ 理解执行计划(EXPLAIN PLAN FOR
  • ✅ 掌握常见错误代码及解决方法

总结

Oracle SQL 是一门强大而严谨的数据库语言。掌握基础后,建议深入学习 PL/SQL 编程和性能优化,这将极大提升企业级应用开发能力。记住:多练习、多思考、多优化是成为 SQL 专家的唯一路径。

相关推荐
曹牧2 小时前
Oracle统计每日发生次数
数据库·oracle
范纹杉想快点毕业2 小时前
返璞归真还是拥抱现代?——嵌入式研发中的“裸机开发”与RTOS全景解析
c语言·数据库·mongodb·设计模式·nosql
辗转.9532 小时前
MongoDB入门指南:从零开始掌握NoSQL数据库
数据库·mongodb·nosql
有什么东东2 小时前
山东大学软件学院2024-2025非关系型数据库背诵整理
数据库·nosql
李少兄2 小时前
一文搞懂什么是关系型数据库?什么是非关系型数据库?
数据库·redis·mysql·mongodb·nosql
ja哇2 小时前
NoSql数据库原理期末(课后思考题)
数据库·nosql
会开花的二叉树2 小时前
即时通讯系统核心模块实现
数据库·mysql·elasticsearch
少云清3 小时前
【接口测试】5_PyMySQL模块 _数据库工具类封装
数据库·pymysql
小光学长3 小时前
基于ssm旅游管理系统的开发与设计z050cft7(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
java·数据库·旅游