SQL语言基础详解:语法、使用方法与综合案例
SQL(Structured Query Language)是用于管理关系型数据库的标准语言。本章系统讲解 SQL 语言的基础知识,包括其分类、编写规则、数据查询、函数使用、子查询、DML 操作等,并结合 Oracle 数据库环境提供详细示例和综合性实战。
一、SQL语言简介与特点
1. SQL 简介
- SQL 是 ANSI/ISO 标准的数据库查询与操作语言。
- 最早由 IBM 在 1970 年代开发(SEQUEL),后被 Oracle 等厂商广泛采用。
- 在 Oracle 中,SQL 与 PL/SQL 结合使用,支持复杂业务逻辑。
2. SQL 语言特点
| 特点 | 说明 |
|---|---|
| 非过程化 | 用户只需说明“做什么”,无需指定“怎么做” |
| 统一性 | DDL、DML、DCL 均用 SQL 实现 |
| 高度可读 | 语法接近自然语言(如 SELECT … FROM … WHERE) |
| 跨平台 | 支持多种数据库(Oracle、MySQL、PostgreSQL 等) |
二、SQL语言的分类
| 类别 | 全称 | 功能 | 常见语句 |
|---|---|---|---|
| DDL | Data Definition Language | 定义数据库结构 | CREATE, ALTER, DROP |
| DML | Data Manipulation Language | 操作表中数据 | SELECT, INSERT, UPDATE, DELETE |
| DCL | Data Control Language | 控制权限与事务 | GRANT, REVOKE, COMMIT, ROLLBACK |
| TCL | Transaction Control Language | 事务控制 | COMMIT, ROLLBACK, SAVEPOINT |
本章重点讲解DML(尤其是 SELECT)和部分 DDL/DCL。
三、SQL语言编写规则(Oracle)
大小写不敏感:
SELECT与select等效(但字符串值区分大小写)。语句以分号
;或/结束(在 SQL*Plus 中)。关键字建议大写,提高可读性。
对象名(表、列)默认大写,若用小写需加双引号(不推荐)。
注释方式:
-- 单行注释/* 多行注释 */
四、用户模式(Schema)与模式对象
1. 什么是模式(Schema)?
- 模式是数据库对象(表、视图、索引等)的集合,属于一个数据库用户。
- 用户名 = 模式名(如
SCOTT用户拥有SCOTT模式)。
2. 模式对象示例
| 对象类型 | 说明 |
|---|---|
| 表(Table) | 存储数据的基本单位 |
| 视图(View) | 虚拟表,基于 SQL 查询 |
| 索引(Index) | 加速查询 |
| 序列(Sequence) | 生成唯一数字 |
| 同义词(Synonym) | 对象别名 |
3. 示例模式:SCOTT
Oracle 自带的经典教学模式,包含以下表:
| 表名 | 说明 |
|---|---|
EMP | 员工表 |
DEPT | 部门表 |
SALGRADE | 工资等级表 |
BONUS | 奖金表(通常为空) |
启用 SCOTT 模式(Oracle 12c+)
-- 以 sysdba 登录CONNECT/ASSYSDBA-- 解锁 scott 用户并设置密码ALTERUSERscott ACCOUNTUNLOCKIDENTIFIEDBYtiger;-- 连接 scottCONNECTscott/tiger若未安装 SCOTT 表,可手动运行
$ORACLE_HOME/rdbms/admin/scott.sql脚本。
五、检索数据(SELECT 语句详解)
1. 简单查询(SELECT … FROM)
-- 查询所有员工姓名和职位SELECTename,jobFROMemp;-- 使用 * 查询所有列(不推荐用于生产)SELECT*FROMdept;2. 筛选查询(WHERE 子句)
-- 查询工资大于 2000 的员工SELECTename,salFROMempWHEREsal>2000;-- 多条件筛选SELECTename,job,hiredateFROMempWHEREdeptno=20ANDjob='ANALYST';3. 排序查询(ORDER BY)
-- 按工资降序排列SELECTename,salFROMempORDERBYsalDESC;-- 多列排序:先按部门升序,再按工资降序SELECTdeptno,ename,salFROMempORDERBYdeptnoASC,salDESC;4. 分组查询(GROUP BY + HAVING)
-- 统计每个部门的平均工资SELECTdeptno,AVG(sal)ASavg_salaryFROMempGROUPBYdeptno;-- 筛选平均工资 > 2000 的部门SELECTdeptno,AVG(sal)ASavg_salaryFROMempGROUPBYdeptnoHAVINGAVG(sal)>2000;⚠️ 注意:
WHERE用于筛选行,HAVING用于筛选分组。
5. 多表关联查询(JOIN)
-- 内连接:查询员工及其部门名称SELECTe.ename,e.job,d.dnameFROMemp eINNERJOINdept dONe.deptno=d.deptno;-- 左外连接:显示所有部门,即使没有员工SELECTd.dname,e.enameFROMdept dLEFTJOINemp eONd.deptno=e.deptno;-- Oracle 旧式写法(不推荐)SELECTe.ename,d.dnameFROMemp e,dept dWHEREe.deptno=d.deptno;六、Oracle常用系统函数
1. 字符类函数
| 函数 | 说明 | 示例 |
|---|---|---|
UPPER(str) | 转大写 | UPPER('scott') → 'SCOTT' |
LOWER(str) | 转小写 | LOWER('KING') → 'king' |
SUBSTR(str, pos, len) | 截取子串 | SUBSTR('ORACLE', 2, 3) → 'RAC' |
LENGTH(str) | 字符长度 | LENGTH('Hello') → 5 |
TRIM(str) | 去除空格 | TRIM(' abc ') → 'abc' |
-- 示例:格式化员工姓名为大写SELECTUPPER(ename)AS"Employee Name"FROMemp;2. 数字类函数
| 函数 | 说明 |
|---|---|
ROUND(n, d) | 四舍五入(d 为小数位) |
TRUNC(n, d) | 截断(不四舍五入) |
MOD(m, n) | 取余 |
ABS(n) | 绝对值 |
-- 计算每人奖金(假设佣金为 10%)SELECTename,sal,NVL(comm,0)AScommission,ROUND(sal*0.1+NVL(comm,0),2)AStotal_bonusFROMemp;3. 日期和时间类函数
| 函数 | 说明 |
|---|---|
SYSDATE | 当前系统日期时间 |
ADD_MONTHS(date, n) | 加 n 个月 |
MONTHS_BETWEEN(d1, d2) | 两日期间月数 |
TO_CHAR(date, fmt) | 日期转字符串 |
-- 查询入职超过 40 年的员工(截至 2026 年)SELECTename,hiredate,ROUND(MONTHS_BETWEEN(SYSDATE,hiredate)/12,1)ASyears_workedFROMempWHEREMONTHS_BETWEEN(SYSDATE,hiredate)/12>40;4. 转换类函数
| 函数 | 说明 |
|---|---|
TO_CHAR(value, fmt) | 转字符串 |
TO_NUMBER(str) | 转数字 |
TO_DATE(str, fmt) | 转日期 |
NVL(expr1, expr2) | 若 expr1 为 NULL,返回 expr2 |
-- 将工资格式化为货币字符串SELECTename,TO_CHAR(sal,'$99,999.99')ASformatted_salaryFROMemp;5. 聚集函数(Aggregate Functions)
| 函数 | 说明 |
|---|---|
COUNT(*) | 行数 |
SUM(col) | 求和 |
AVG(col) | 平均值 |
MAX(col) | 最大值 |
MIN(col) | 最小值 |
-- 统计员工总数、最高/最低工资、平均工资SELECTCOUNT(*)AStotal_employees,MAX(sal)ASmax_salary,MIN(sal)ASmin_salary,AVG(sal)ASavg_salaryFROMemp;七、子查询(Subquery)
1. 什么是子查询?
- 在一个 SQL 语句中嵌套另一个
SELECT语句。 - 子查询先执行,结果作为外层查询的条件。
2. 单行子查询(返回一行一列)
-- 查询工资高于平均工资的员工SELECTename,salFROMempWHEREsal>(SELECTAVG(sal)FROMemp);3. 多行子查询(返回多行)
-- 查询在 SALES 或 RESEARCH 部门工作的员工SELECTename,jobFROMempWHEREdeptnoIN(SELECTdeptnoFROMdeptWHEREdnameIN('SALES','RESEARCH'));-- 使用 ANY / ALLSELECTename,salFROMempWHEREsal>ANY(SELECTsalFROMempWHEREdeptno=30);-- 高于销售部任一员工4. 关联子查询(Correlated Subquery)
子查询引用外层查询的列。
-- 查询每个部门中工资最高的员工SELECTe1.ename,e1.deptno,e1.salFROMemp e1WHEREe1.sal=(SELECTMAX(e2.sal)FROMemp e2WHEREe2.deptno=e1.deptno-- 关联条件);八、操作数据库(DML 语句)
1. 插入数据(INSERT)
-- 插入完整行INSERTINTOdept(deptno,dname,loc)VALUES(50,'IT','BEIJING');-- 插入部分列(其他列为 NULL 或默认)INSERTINTOemp(empno,ename,job,hiredate,sal,deptno)VALUES(8000,'ALICE','DEVELOPER',SYSDATE,5000,50);2. 更新数据(UPDATE)
-- 给所有 ANALYST 加薪 10%UPDATEempSETsal=sal*1.1WHEREjob='ANALYST';-- 更新多个字段UPDATEempSETsal=6000,comm=500WHEREempno=8000;3. 删除数据
DELETE(可回滚,触发器生效)
-- 删除奖金为 NULL 的员工DELETEFROMempWHEREcommISNULL;TRUNCATE(不可回滚,更快,不触发触发器)
-- 清空 bonus 表TRUNCATETABLEbonus;⚠️ 区别:
DELETE是 DML,可ROLLBACK;TRUNCATE是 DDL,自动COMMIT,不能回滚。
九、综合性实战案例
案例:生成“高绩效员工年度报告”
需求:
- 找出每个部门工资最高的员工;
- 显示其姓名、职位、工资、部门名、入职年限;
- 工资格式化为货币;
- 按部门编号排序;
- 输出到 SQL*Plus 报表。
-- 设置 SQL*Plus 环境SETPAGESIZE40SETLINESIZE150SETFEEDBACKOFFTTITLE CENTER'High Performer Annual Report - &SYSDATE'SKIP2BTITLE CENTER'Confidential'-- 格式化列COLUMNename HEADING"Employee Name"FORMAT A15COLUMNjob HEADING"Job Title"FORMAT A12COLUMNdname HEADING"Department"FORMAT A15COLUMNsal_fmt HEADING"Salary"FORMAT A12COLUMNyears HEADING"Years Worked"FORMAT999.9-- 主查询:使用关联子查询找部门最高薪员工SELECTe.ename,e.job,d.dname,TO_CHAR(e.sal,'$99,999.99')ASsal_fmt,ROUND(MONTHS_BETWEEN(SYSDATE,e.hiredate)/12,1)ASyearsFROMemp eJOINdept dONe.deptno=d.deptnoWHEREe.sal=(SELECTMAX(sal)FROMemp e2WHEREe2.deptno=e.deptno)ORDERBYe.deptno;-- 清理TTITLEOFFBTITLEOFFSETFEEDBACKON输出效果(示例):
High Performer Annual Report - 14-JAN-2026 Employee Name Job Title Department Salary Years Worked --------------- ------------ --------------- ------------ ------------ KING PRESIDENT ACCOUNTING $5,000.00 41.2 SCOTT ANALYST RESEARCH $3,000.00 40.8 BLAKE MANAGER SALES $2,850.00 41.0十、总结
| 模块 | 核心知识点 |
|---|---|
| SQL 基础 | 分类、规则、模式概念 |
| 数据查询 | SELECT + WHERE + GROUP BY + ORDER BY + JOIN |
| 函数 | 字符、数字、日期、转换、聚集 |
| 子查询 | 单行、多行、关联 |
| DML | INSERT / UPDATE / DELETE / TRUNCATE |
💡 提示:掌握这些基础是进阶 PL/SQL、性能调优、数据库设计的前提。建议在SQL*Plus 或 SQL Developer中反复练习 SCOTT 模式下的各类查询。
✅ 附:快速启用 SCOTT 模式的完整脚本(若缺失)
-- 以 sys 用户运行@?/rdbms/admin/scott.sqlALTERUSERscott IDENTIFIEDBYtiger ACCOUNTUNLOCK;