数据库多表查询学习文档
一、多表查询概述
在实际开发中,我们经常需要从多个数据表中组合获取数据。例如:查询考试成绩时需要同时显示学员姓名,但姓名存储在学员信息表中,而成绩存储在成绩表中。
二、内连接查询(INNER JOIN)
2.1 概念
内连接查询两个表的公共部分,类似于集合的交集,只返回满足连接条件的记录。
2.2 语法格式
SELECT字段列表FROM表1INNERJOIN表2ON表1.关联字段=表2.关联字段WHERE条件2.3 两个表内连接查询示例
-- 查询字段(StudentId是两个关联表的公共字段,需要指明来源表)SELECTScoreList.StudentId,StudentName,C#成绩 = CSharpFROMScoreListINNERJOINStudentsONStudents.StudentId=ScoreList.StudentIdWHERECSharp>752.4 多表内连接查询示例
SELECTStudents.StudentId,StudentName,C#成绩 = CSharp, ClassNameFROMStudentsINNERJOINScoreListONScoreList.StudentId=Students.StudentIdINNERJOINStudentClassONStudentClass.ClassId=Students.ClassIdWHERECSharp>752.5 注意事项
- 需要明确连接的表
- 两个表连接的条件(主外键关系)
- 两个表中相同的字段,必须说明来自哪个表
- 多表内连接时,表的顺序不影响结果
三、左外连接查询(LEFT OUTER JOIN)
3.1 概念
左外连接以左表为基准,返回左表的所有记录,以及右表中满足连接条件的记录。如果右表中没有匹配的记录,则返回 NULL。
3.2 语法格式
SELECT字段列表FROM左表LEFTOUTERJOIN右表ON左表.关联字段=右表.关联字段WHERE条件3.3 示例对比
-- 内连接查询(没有成绩的男性不显示)SELECTStudents.StudentId,StudentName,C#成绩 = CSharpFROMStudentsINNERJOINScoreListONScoreList.StudentId=Students.StudentIdWHEREGender='男'-- 左外连接查询(董存瑞显示,但成绩为 NULL)SELECTStudents.StudentId,StudentName,C#成绩 = CSharpFROMStudentsLEFTOUTERJOINScoreListONScoreList.StudentId=Students.StudentIdWHEREGender='男'3.4 注意事项
- 左外连接左右表的顺序会影响查询结果
- 交换左右表位置,查询结果会有区别(内连接没有此区别)
四、右外连接查询(RIGHT OUTER JOIN)
4.1 概念
右外连接以右表为基准,返回右表的所有记录,以及左表中满足连接条件的记录。如果左表中没有匹配的记录,则返回 NULL。
4.2 语法格式
SELECT字段列表FROM左表RIGHTOUTERJOIN右表ON左表.关联字段=右表.关联字段WHERE条件4.3 示例
-- 查询所有班级及其学生(包括没有学生的班级)SELECTStudentId,StudentName,ClassNameFROMStudentsRIGHTOUTERJOINStudentClassONStudentClass.ClassId=Students.ClassId五、全连接查询(FULL OUTER JOIN)
5.1 概念
全连接返回两个表的所有记录。当某条记录在另一个表中没有匹配时,对应的字段返回 NULL。全连接是左外连接和右外连接的并集。
5.2 语法格式
SELECT字段列表FROM表1FULLOUTERJOIN表2ON表1.关联字段=表2.关联字段WHERE条件5.3 示例
-- 查询所有学生及其成绩,包括没有成绩的学生和没有对应学生的成绩记录SELECTStudents.StudentId,StudentName,C#成绩 = CSharpFROMStudentsFULLOUTERJOINScoreListONScoreList.StudentId=Students.StudentId5.4 注意事项
- SQL Server 支持
FULL OUTER JOIN,但 MySQL 不直接支持,需要使用UNION实现 - 返回结果 = 左表全部 + 右表全部
六、自连接查询(SELF JOIN)
6.1 概念
自连接是指同一个表自己和自己连接,常用于查询表内的层级关系或对比关系。
6.2 语法格式
SELECTa.字段列表,b.字段列表FROM表名 aINNERJOIN表名 bONa.关联字段=b.关联字段WHERE条件6.3 示例一:查询员工及其直属上级
假设存在Employees表,包含EmployeeId、EmployeeName、ManagerId字段:
-- 查询员工及其直属上级SELECTa.EmployeeId,a.EmployeeName,b.EmployeeNameASManagerNameFROMEmployees aINNERJOINEmployees bONa.ManagerId=b.EmployeeId6.4 示例二:查询同级别的员工
-- 查询同部门的员工(排除自己)SELECTa.EmployeeNameAS员工A,b.EmployeeNameAS员工BFROMEmployees aINNERJOINEmployees bONa.DepartmentId=b.DepartmentIdWHEREa.EmployeeId<>b.EmployeeId--<>为不等于,等同于!=6.5 注意事项
- 必须使用表别名(如 a、b)来区分同一个表的不同引用
- 常用于树形结构数据(如组织结构、分类层级)
七、交叉连接查询(CROSS JOIN)
7.1 概念
交叉连接返回两个表的笛卡尔积,即第一个表的每一行与第二个表的每一行组合。结果行数 = 表1行数 × 表2行数。
7.2 语法格式
-- 显式语法SELECT字段列表FROM表1CROSSJOIN表2-- 隐式语法(不推荐)SELECT字段列表FROM表1,表27.3 示例
-- 查询所有学生与所有课程的组合(生成选课可能性)SELECTStudentName,CourseNameFROMStudentsCROSSJOINCourses7.4 注意事项
- 交叉连接会产生大量数据,使用时需谨慎
- 实际应用中通常与 WHERE 条件结合使用,过滤掉不需要的组合
- 隐式语法(逗号分隔)容易出错,推荐使用显式
CROSS JOIN
八、各种连接方式对比
| 连接类型 | 语法 | 返回结果 | 表顺序影响 |
|---|---|---|---|
| 内连接 | INNER JOIN | 两个表的公共部分(交集) | 无影响 |
| 左外连接 | LEFT OUTER JOIN | 左表全部 + 右表匹配部分 | 有影响 |
| 右外连接 | RIGHT OUTER JOIN | 右表全部 + 左表匹配部分 | 有影响 |
| 全连接 | FULL OUTER JOIN | 两个表的所有记录(并集) | 无影响 |
| 自连接 | JOIN 表名 AS 别名 | 同一表内的关联数据 | 无影响 |
| 交叉连接 | CROSS JOIN | 两个表的笛卡尔积 | 无影响 |
九、第三方工具SQLHelper
9.1 SqlHelper 简介
SqlHelper 是基于 .NET Framework 开发的数据库操作组件,通过封装 ADO.NET 对象简化数据库访问流程。
9.2 核心方法
| 方法 | 功能 | 返回值 |
|---|---|---|
ExecuteNonQuery | 执行增删改操作 | 影响行数(int) |
ExecuteReader | 执行查询,返回数据阅读器 | SqlDataReader |
ExecuteDataset | 执行查询,返回数据集 | DataSet |
ExecuteScalar | 执行查询,返回单行单列 | object |
9.3 多表查询示例
/// <summary>/// 使用SqlHelper执行多表内连接查询/// </summary>/// <param name="connectionString">数据库连接字符串</param>/// <returns>包含查询结果的DataSet</returns>publicstaticDataSetGetStudentScoreWithClass(stringconnectionString){stringsql=@"SELECT Students.StudentId, StudentName, C#成绩 = CSharp, ClassName FROM Students INNER JOIN ScoreList ON ScoreList.StudentId = Students.StudentId INNER JOIN StudentClass ON StudentClass.ClassId = Students.ClassId WHERE CSharp > 75";returnSqlHelper.ExecuteDataset(connectionString,CommandType.Text,sql);}/// <summary>/// 使用SqlHelper执行左外连接查询/// </summary>/// <param name="connectionString">数据库连接字符串</param>/// <returns>包含查询结果的DataSet</returns>publicstaticDataSetGetAllMaleStudentScore(stringconnectionString){stringsql=@"SELECT Students.StudentId, StudentName, C#成绩 = CSharp FROM Students LEFT OUTER JOIN ScoreList ON ScoreList.StudentId = Students.StudentId WHERE Gender = '男'";returnSqlHelper.ExecuteDataset(connectionString,CommandType.Text,sql);}十、ADO.NET 核心对象
10.1 五大核心对象
| 对象 | 功能 | 常用方法/属性 |
|---|---|---|
| SqlConnection | 数据库连接 | Open(),Close(),State |
| SqlCommand | 执行SQL命令 | ExecuteNonQuery(),ExecuteReader(),ExecuteScalar() |
| SqlDataReader | 读取数据(只读向前) | Read(),GetString(),GetInt32() |
| SqlDataAdapter | 填充数据集 | Fill(DataSet) |
| DataSet | 内存中的数据库 | Tables[0],Tables["TableName"] |
10.2 SqlCommand 返回三种数据类型
- 影响行数:
cmd.ExecuteNonQuery() - 结果集:
cmd.ExecuteReader() - 一行一列:
cmd.ExecuteScalar()