SQL知识点大全(新手友好版)
一、SQL 基础与核心概念
1. 什么是SQL?
SQL是一种专门用来与数据库沟通的语言。通过SQL,你可以执行数据的查询、更新、插入和删除,以及创建和修改数据库结构等操作。
2. 数据库与表
- 数据库 (Database):一个有组织的数据集合,通常存储在计算机系统中。可以把它想象成一个大柜子。
- 表 (Table):数据库中的基本存储单位,由行 (Row) 和列 (Column) 组成。可以把它想象成柜子里的抽屉,每个抽屉里存放着特定类型的信息。
- 列 (Column/Field):表中的一个字段,代表一种特定类型的数据(如:姓名、年龄、成绩)。
- 行 (Row/Record):表中的一条记录,代表一组相关的数据(如:某个学生的完整信息)。
- 主键 (Primary Key):表中唯一标识每一行的列(或列组合)。例如学生表中的学号。
- 外键 (Foreign Key):一个表中的列,其值引用另一个表的主键。用于建立表与表之间的关联。
3. SQL命令分类
SQL命令主要可以分为以下几类:
- DDL (Data Definition Language - 数据定义语言):用于定义和管理数据库对象。
CREATE:创建数据库、表、视图、索引等。ALTER:修改数据库、表等结构。DROP:删除数据库、表等。TRUNCATE:快速删除表中的所有行,但保留表结构。
- DML (Data Manipulation Language - 数据操作语言):用于操作数据库中的数据。
SELECT:查询数据。INSERT:插入数据。UPDATE:更新数据。DELETE:删除数据。
- DCL (Data Control Language - 数据控制语言):用于控制数据库的访问权限。
GRANT:授予权限。REVOKE:撤销权限。
- TCL (Transaction Control Language - 事务控制语言):用于管理数据库事务。
COMMIT:提交事务,将更改永久保存。ROLLBACK:回滚事务,撤销未提交的更改。SAVEPOINT:在事务中设置保存点。
二、常用SQL语句用法
假设我们有以下两个表:
Students (学生表)
| StudentID (学号) | Name (姓名) | Age (年龄) | Major (专业) |
|---|---|---|---|
| 1 | 张三 | 20 | 计算机科学 |
| 2 | 李四 | 22 | 数学 |
| 3 | 王五 | 21 | 计算机科学 |
| 4 | 赵六 | 20 | 物理学 |
Courses (课程表)
| CourseID (课程号) | CourseName (课程名) | Teacher (教师) |
|---|---|---|
| C01 | 数据库原理 | 刘老师 |
| C02 | 高等数学 | 陈老师 |
| C03 | 大学物理 | 张老师 |
1. SELECT - 查询数据
SELECT 是SQL中最常用的语句,用于从数据库表中检索数据。
基本语法:
SELECT column1, column2, ...
FROM table_name;查询所有列:
sqlSELECT * FROM Students; -- 结果: 返回 Students 表中的所有行和所有列查询指定列:
sqlSELECT Name, Major FROM Students; -- 结果: 返回 Students 表中所有学生的姓名和专业
2. WHERE - 条件过滤
WHERE 子句用于根据指定的条件过滤记录。
基本语法:
SELECT column1, column2, ...
FROM table_name
WHERE condition;- 常用比较运算符:
=,>,<,>=,<=,!=(或<>) - 逻辑运算符:
AND,OR,NOT - 其他常用条件:
BETWEEN ... AND ...:在某个范围内IN (...):在指定的一组值中LIKE:模糊查询(%代表零个或多个字符,_代表一个字符)IS NULL/IS NOT NULL:检查是否为空值
示例:
查询专业为“计算机科学”的学生:
sqlSELECT Name, Age FROM Students WHERE Major = '计算机科学'; -- 结果: 张三 (20), 王五 (21)查询年龄大于20岁且专业为“计算机科学”的学生:
sqlSELECT * FROM Students WHERE Age > 20 AND Major = '计算机科学'; -- 结果: 王五 (21, 计算机科学)查询姓名以“张”开头的学生:
sqlSELECT * FROM Students WHERE Name LIKE '张%'; -- 结果: 张三查询专业是“数学”或“物理学”的学生:
sqlSELECT * FROM Students WHERE Major IN ('数学', '物理学'); -- 结果: 李四 (数学), 赵六 (物理学)
3. ORDER BY - 结果排序
ORDER BY 子句用于对结果集进行排序,默认为升序 (ASC),可指定降序 (DESC)。
基本语法:
SELECT column1, column2, ...
FROM table_name
ORDER BY column_to_sort ASC|DESC;示例:
按年龄升序排列所有学生:
sqlSELECT * FROM Students ORDER BY Age ASC; -- ASC 可以省略 -- 结果: 张三(20), 赵六(20), 王五(21), 李四(22)按年龄降序排列,如果年龄相同则按学号升序:
sqlSELECT * FROM Students ORDER BY Age DESC, StudentID ASC;
4. LIMIT / TOP - 限制结果数量
用于限制查询返回的记录数量。不同数据库系统语法不同:
- MySQL, PostgreSQL:
LIMIT - SQL Server:
TOP - Oracle:
ROWNUM(通常结合子查询使用)
MySQL/PostgreSQL 示例:
SELECT *
FROM Students
LIMIT 2; -- 返回前2条记录
SELECT *
FROM Students
ORDER BY Age DESC
LIMIT 1 OFFSET 1; -- 跳过第1条,取接下来1条 (即按年龄降序的第2个)SQL Server 示例:
SELECT TOP 2 *
FROM Students; -- 返回前2条记录5. INSERT INTO - 插入数据
用于向表中添加新的记录。
基本语法:
INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...);如果为所有列都提供值,并且顺序与表中列的顺序一致,可以省略列名:
INSERT INTO table_name
VALUES (value1_for_col1, value2_for_col2, ...);示例:
INSERT INTO Students (StudentID, Name, Age, Major)
VALUES (5, '孙七', 19, '英语');
-- 如果按表列顺序插入所有值
INSERT INTO Courses
VALUES ('C04', '线性代数', '王老师');6. UPDATE - 更新数据
用于修改表中已存在的记录。务必使用 WHERE 子句,否则会更新表中的所有行!
基本语法:
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;示例:
UPDATE Students
SET Major = '软件工程'
WHERE StudentID = 1; -- 将学号为1的学生的专业改为软件工程
UPDATE Students
SET Age = Age + 1
WHERE Major = '计算机科学'; -- 将所有计算机科学专业的学生年龄增加1岁7. DELETE - 删除数据
用于从表中删除记录。务必使用 WHERE 子句,否则会删除表中的所有行!
基本语法:
DELETE FROM table_name
WHERE condition;示例:
DELETE FROM Students
WHERE StudentID = 5; -- 删除学号为5的学生记录
-- 如果要删除表内所有数据(但保留表结构)
-- DELETE FROM Students; (不推荐,效率低,会记录日志)
-- TRUNCATE TABLE Students; (推荐,效率高,不记录日志,不可回滚)8. CREATE TABLE - 创建表
用于在数据库中创建新表。
基本语法:
CREATE TABLE table_name (
column1 datatype constraints,
column2 datatype constraints,
...
PRIMARY KEY (one_or_more_columns) -- 定义主键
);常用数据类型:INT (整数), VARCHAR(n) (可变长度字符串), CHAR(n) (固定长度字符串), DATE, DATETIME, DECIMAL(p,s) (精确小数)等。 常用约束:NOT NULL (非空), UNIQUE (唯一), PRIMARY KEY (主键), FOREIGN KEY (外键), CHECK (检查约束)。
示例:
CREATE TABLE Enrollments (
EnrollmentID INT PRIMARY KEY,
StudentID INT,
CourseID VARCHAR(10),
Grade CHAR(1),
FOREIGN KEY (StudentID) REFERENCES Students(StudentID), -- 外键关联到Students表的StudentID
FOREIGN KEY (CourseID) REFERENCES Courses(CourseID) -- 外键关联到Courses表的CourseID
);9. ALTER TABLE - 修改表结构
用于添加、删除或修改表的列。
示例:
- 添加列:sql
ALTER TABLE Students ADD COLUMN Email VARCHAR(100); - 修改列数据类型:sql
ALTER TABLE Students ALTER COLUMN Age TYPE SMALLINT; -- PostgreSQL语法,MySQL用 MODIFY COLUMN Age SMALLINT; SQL Server用 ALTER COLUMN Age SMALLINT; - 删除列:sql
ALTER TABLE Students DROP COLUMN Email;
10. DROP TABLE - 删除表
用于从数据库中永久删除一个表及其所有数据。
DROP TABLE Enrollments;三、进阶SQL知识点
1. 聚合函数 (Aggregate Functions) 与 GROUP BY
聚合函数对一组值进行计算,并返回单个值。
COUNT(*)或COUNT(column_name): 计算行数或某列非空值的数量。SUM(column_name): 计算某列数值的总和。AVG(column_name): 计算某列数值的平均值。MAX(column_name): 找出某列的最大值。MIN(column_name): 找出某列的最小值。
GROUP BY 子句通常与聚合函数一起使用,将结果集中的行按一个或多个列的值进行分组,然后对每个组应用聚合函数。
基本语法:
SELECT column_to_group_by, AGGREGATE_FUNCTION(column_name)
FROM table_name
WHERE condition
GROUP BY column_to_group_by;示例:
统计每个专业的学生人数:
sqlSELECT Major, COUNT(*) AS NumberOfStudents FROM Students GROUP BY Major; -- 结果: -- 计算机科学 | 2 -- 数学 | 1 -- 物理学 | 1统计每个专业学生的平均年龄:
sqlSELECT Major, AVG(Age) AS AverageAge FROM Students GROUP BY Major;
2. HAVING - 分组后过滤
HAVING 子句用于在 GROUP BY 分组之后对分组结果进行过滤。WHERE 是在分组前过滤行,HAVING 是在分组后过滤组。
基本语法:
SELECT column_to_group_by, AGGREGATE_FUNCTION(column_name)
FROM table_name
WHERE condition -- 过滤行
GROUP BY column_to_group_by
HAVING aggregate_condition; -- 过滤组示例:
- 查询学生人数超过1人的专业:sql
SELECT Major, COUNT(*) AS NumberOfStudents FROM Students GROUP BY Major HAVING COUNT(*) > 1; -- 结果: 计算机科学 | 2
3. JOIN - 表连接
JOIN 用于根据两个或多个表中的相关列将它们组合起来。
INNER JOIN(或JOIN): 返回两个表中连接字段匹配的行。sqlSELECT s.Name, c.CourseName FROM Students s INNER JOIN Enrollments e ON s.StudentID = e.StudentID INNER JOIN Courses c ON e.CourseID = c.CourseID; -- 假设 Enrollments 表中有数据,这将列出学生姓名和他们选修的课程名LEFT JOIN(或LEFT OUTER JOIN): 返回左表中的所有行,以及右表中匹配的行。如果右表中没有匹配,则结果中右表的列为NULL。sqlSELECT s.Name, c.CourseName FROM Students s LEFT JOIN Enrollments e ON s.StudentID = e.StudentID LEFT JOIN Courses c ON e.CourseID = c.CourseID; -- 列出所有学生,以及他们选修的课程名。如果学生没选课,课程名部分为NULLRIGHT JOIN(或RIGHT OUTER JOIN): 返回右表中的所有行,以及左表中匹配的行。如果左表中没有匹配,则结果中左表的列为NULL。sqlSELECT s.Name, c.CourseName FROM Students s RIGHT JOIN Enrollments e ON s.StudentID = e.StudentID RIGHT JOIN Courses c ON e.CourseID = c.CourseID; -- 列出所有被选的课程,以及选修该课程的学生。如果课程没人选,学生姓名部分为NULL (假设Enrollments和Courses有数据)FULL OUTER JOIN(或FULL JOIN): 返回左表和右表中的所有行。如果某行在另一个表中没有匹配,则另一个表的列为NULL。sqlSELECT s.Name, c.CourseName FROM Students s FULL OUTER JOIN Enrollments e ON s.StudentID = e.StudentID FULL OUTER JOIN Courses c ON e.CourseID = c.CourseID; -- 列出所有学生和所有课程,显示匹配关系,不匹配则为NULL
4. 子查询 (Subquery)
子查询是嵌套在另一个SQL查询(主查询)中的查询。它可以出现在 SELECT, FROM, WHERE, HAVING 子句中。
示例:
查询年龄大于平均年龄的学生:
sqlSELECT Name, Age FROM Students WHERE Age > (SELECT AVG(Age) FROM Students);查询选修了“数据库原理”课程的学生姓名 (假设
Enrollments表中有StudentID和CourseID):sqlSELECT Name FROM Students WHERE StudentID IN ( SELECT StudentID FROM Enrollments WHERE CourseID = (SELECT CourseID FROM Courses WHERE CourseName = '数据库原理') );
5. UNION 和 UNION ALL
用于合并两个或多个 SELECT 语句的结果集。
UNION: 合并结果集,并自动去除重复的行。UNION ALL: 合并结果集,包含所有行,包括重复行。
要求: 所有 SELECT 语句必须具有相同数量的列,列也必须具有相似的数据类型,并且列的顺序也必须相同。
示例:
SELECT Name, Major FROM Students WHERE Age > 20
UNION
SELECT Name, Major FROM Students WHERE Major = '计算机科学';
-- 合并两个查询结果,并去重6. 视图 (View)
视图是一个虚拟表,其内容由查询定义。视图本身不存储数据,数据仍然存储在基表中。
创建视图:
CREATE VIEW CS_Students AS
SELECT StudentID, Name, Age
FROM Students
WHERE Major = '计算机科学';之后可以像查询表一样查询视图:
SELECT * FROM CS_Students;优点:
- 简化复杂查询。
- 提高安全性(只暴露部分数据)。
- 数据独立性(基表结构改变,如果视图定义不涉及改变的列,视图仍可用)。
7. 索引 (Index)
索引是数据库表中一列或多列值的排序列表,用于加快查询速度。 创建索引会占用额外的存储空间,并可能降低写操作(INSERT, UPDATE, DELETE)的速度,因为索引也需要更新。
创建索引:
CREATE INDEX idx_student_major ON Students (Major);
-- 在 Students 表的 Major 列上创建索引查询 WHERE Major = 'xxx' 时会更快。
8. 事务 (Transaction)
事务是一组SQL操作,这些操作要么全部成功执行,要么全部失败回滚,以确保数据的一致性和完整性。 事务具有ACID特性:
- 原子性 (Atomicity): 事务是不可分割的最小工作单元,要么都做,要么都不做。
- 一致性 (Consistency): 事务执行前后,数据库从一个一致性状态转变到另一个一致性状态。
- 隔离性 (Isolation): 一个事务的执行不应被其他并发事务干扰。
- 持久性 (Durability): 一旦事务提交,其结果就是永久性的。
常用命令:
BEGIN TRANSACTION(或START TRANSACTION): 开始一个事务。COMMIT: 提交事务,将所有更改永久保存到数据库。ROLLBACK: 回滚事务,撤销自上次COMMIT或ROLLBACK以来的所有更改。
BEGIN TRANSACTION;
UPDATE Students SET Age = 21 WHERE StudentID = 1;
-- 假设这里有一个错误或者条件不满足
IF some_condition_is_false THEN
ROLLBACK;
ELSE
COMMIT;
END IF;9. 窗口函数 (Window Functions) - (较进阶)
窗口函数对一组与当前行相关的表行(称为窗口)执行计算。与聚合函数不同,窗口函数不会将多行聚合成单行,而是为结果集中的每一行都返回一个值。
常见窗口函数:
- 排名函数:
ROW_NUMBER(),RANK(),DENSE_RANK() - 聚合窗口函数:
SUM() OVER (...),AVG() OVER (...) - 值函数:
LAG(),LEAD()
示例:
- 按专业给学生排名(按年龄从小到大):sql
SELECT Name, Major, Age, ROW_NUMBER() OVER (PARTITION BY Major ORDER BY Age ASC) as RankInMajor FROM Students; -- PARTITION BY Major: 按专业分组(窗口) -- ORDER BY Age ASC: 在每个窗口内按年龄排序
10. 公用表表达式 (Common Table Expressions - CTEs) - (较进阶)
CTE 是一个临时的、命名的结果集,可以在单个SQL语句(如 SELECT, INSERT, UPDATE, DELETE 或 CREATE VIEW)的执行范围内引用。
基本语法:
WITH cte_name (column1, column2, ...) AS (
-- CTE 查询定义
SELECT ...
)
-- 主查询,可以引用 cte_name
SELECT * FROM cte_name;示例:
- 找出每个专业中最年轻的学生:sql
WITH RankedStudents AS ( SELECT Name, Major, Age, ROW_NUMBER() OVER (PARTITION BY Major ORDER BY Age ASC) as rn FROM Students ) SELECT Name, Major, Age FROM RankedStudents WHERE rn = 1;
四、学习建议
- 动手实践:理论学习后,最重要的是动手写SQL。找一个数据库环境(如MySQL, PostgreSQL, SQLite),创建表,插入数据,然后练习各种查询。
- 理解数据模型:学会看懂ER图(实体关系图),理解表与表之间的关系,这对写出正确的JOIN查询至关重要。
- 从简单到复杂:先掌握基础的
SELECT,WHERE,INSERT,UPDATE,DELETE,再逐步学习GROUP BY,JOIN, 子查询等。 - 查阅文档:不同的数据库系统(MySQL, PostgreSQL, SQL Server, Oracle等)在SQL语法上可能略有差异,遇到问题时查阅对应数据库的官方文档。
- 多看示例:通过看别人写的SQL语句,学习不同的写法和技巧。
希望这份介绍对你入门SQL有所帮助!记住,多练习是学好SQL的关键。