diff --git "a/34\351\231\210\346\264\213/\347\254\224\350\256\260/0905\345\217\230\351\207\217.md" "b/34\351\231\210\346\264\213/\347\254\224\350\256\260/0905\345\217\230\351\207\217.md" index a07bb6c2823acfb1a85cc2cdae4e927943d0dae1..1d9ced23d63d8fc0cc89c81e076f8b1ae5da3bb9 100644 --- "a/34\351\231\210\346\264\213/\347\254\224\350\256\260/0905\345\217\230\351\207\217.md" +++ "b/34\351\231\210\346\264\213/\347\254\224\350\256\260/0905\345\217\230\351\207\217.md" @@ -1,94 +1,110 @@ -### 一 **变量与逻辑控制** +一 子查询 -掌握变量的定义和使用 +**子查询**是一个嵌套在**select**、**insert**、**update**、**delete**语句的其他查询中的查询。==任何允许使用表达式的地方都可以使用子查询==。子查询也称为内部查询或内部选择,而包含子部查询的语句也称为外部查询或外部选择 -掌握输出语句 -掌握逻辑控制语句 -理解批处理的概念 +==子查询的注意事项:== -### 二 **变量** +1. 子查询语法中的小括号 -局部变量 +2. 可以使用子查询的位置:**where,select,having,==from(要用as取别名)==** -局部变量必须以标记@作为前缀,如@old +3. 不可以使用子查询的位置:group by ,order by -局部变量的使用是先声明,再赋值 +4. 主查询和子查询可以不是同一张表 -局部变量只在定义它的局部范围内有效 +5. 一般不在子查询中使用排序(但是在top-n问题分析中必须对子查询使用排序) +6. 一般先执行子查询,再执行主查询(相关子查询除外) +7. 单行子查询只能使用单行操作符;多行子查询只能使用多行操作符 -声明一个局部变量:**declare @变量名 数据类型** + 注意:当子查询为null值的问题 -```sql ---例: - declare @id int --声明一个名为id的整型变量 - declare @name varchar(50) --声明一个可变长度为50的存放姓名的字符串变量 -``` + 子查询也可以作为赋值语句的一部分 + +### 1 使用in 和 not in完成子查询 -赋值: +in[在] not in[不在] -set @变量名 = 值 +**in 和 not in==通常在where子句中使用==,在 in 或 not in后接的子查询中==可以有多个值出现==** -select @变量名 = 值 +例:查询出所有选修课程都及格的学生的信息 -```sql ---例: - select @id = 1001 - set @name = '周飘' +``` +select * from StudentInfo +where stuNO in (select stuid + from stuMarks + group by stuid + having min(Score) >= 60 + ) ``` +------ +### 2.使用some、any、all进行查询 -set与select赋值的区别: +some[一些] any[任意的] all[全部] -set赋值给变量指定的值,select一般用于表中查询出的数据赋值给变量,如果查询结果有多条,取最后一条赋值给变量 +**在SQL查询中,`some`、`any`、`all` 后必须跟子查询** +- **==some和any的查询功能是一样的==,where条件能够满足some和any所接的子查询中的==任意一个值==,就表示where条件成立** +- **all表示的是能够==满足==all所接的子查询中的==所有值==才成立** +- = any 等值于in +例:查询出某同学某一门考试成绩比“张秋利”同学所有分数都高的学生基本信息 -### 三 全局变量 +``` +select sti.* from stuMarks smk +inner join StudentInfo sti on sti.stuNo = smk.stuID +where score > all(select score + from stuMarks stm +inner join StudentInfo st on stm.stuID = st.stuNo +where stuName = '张秋利') +``` -全局变量必须以标记**@@**作为前缀,如@@version +查询出某同学某一门考试成绩只需要比“张秋利”同学某个分数高的学生基本信息(stuMarks) -全局变量由系统定义和维护,我们只能读取,不能修改全局变量的值 +``` +select distinct sti.* from stuMarks smk +inner join StudentInfo sti on sti.stuNo = smk.stuID +where stuName <> '张秋利' and score > any(select score + from stuMarks stm +inner join StudentInfo st on stm.stuID = st.stuNo + where stuName = '张秋利') +``` -全局变量在整个SQL环境下都可以被访问或调用 +------ -```sql ---@@ERROR:返回执行的上一个语句的错误号 ---@@IDENTITY:返回最后插入的标识值 ---@@MAX_CONNECTIONS:返回允许同时进行的最大用户连接数 ---@@ROWCOUNT:返回受上一语句影响的行数 ---@@SERVERNAME:返回运行 SQL Server 的本地服务器的名称 ---@@SERVICENAME:返回 SQL Server 正在其下运行的注册表项的名称 ---@@TRANCOUNT:返回当前连接的活动事务数 ---@@LOCK_TIMEOUT:返回当前会话的当前锁定超时设置(毫秒) +### 3.使用exists 和not exists完成子查询 -``` +**exists[存在]: 如果子查询结果非空,即记录条数1条以上,则exsts(子查询)返回true 或 false**,==可配合if语句使用if exists(条件)== +**`exists` 和 `not exists`表示存在和不存在的意思。在语句中会==判断`exists` 或 `not exists`后接的子句是否存在和是否不存在==** +示例:查询出参加考试的学生的信息 -## 输出语句 +``` +select * from StudentInfo st +where exists (select stuid from stuMarks stm where st.stuNo = stm.stuID) --如果该条件成立就显示,上一行的查询结果 +``` -1. print变量或表达式 -2. select变量或表达式 +也可以和if配合使用 -```sql ---例: - print '数据库服务器名:' + @@servicename - select 15*8 +``` +if exists(子查询) +语句 ``` -#### 使用convert函数 +------ -​ 由于PRINT 命令向客户端返回一个结果的字符串的信息。如果变量值不是字符串的话必 +### 4.使用compute和compute by进行汇总查询 -```sql -须先用数据类型转换函数 CONVERT 将其转换为字符串。 cast(变量 as 数据类型 ) +**compute 和 compute by子句使您得以用同一select语句即查看明细行,有查看汇总行。可以计算子组的汇总值,也可以计算整个结果集的汇总值** ---显示自动编号 -print '当前自动编号的值:' + convert(varchar(10),@@IDENTITY) -``` +当compute不带可选的by子句时,select语句有两个结果集: ● 每个组的第一个结果集是包含选择列表信息的所有明细行 ● 第二个结果集有一行,其中包含compute子句中所指定的聚合函数的合计 + +compute子句需要下列信息: ● 可选by关键字。它基于每一列计算指定的行聚合 ● 行聚合函数名称 SUM、AVG、MIN、MAX、或 COUNT ● 要对其执行行聚函数的列 +对结果先进行分组然后进行汇总计算时使用:compute by进行分组汇总查询 diff --git "a/34\351\231\210\346\264\213/\347\254\224\350\256\260/0907\345\255\220\346\237\245\350\257\242.md" "b/34\351\231\210\346\264\213/\347\254\224\350\256\260/0907\345\255\220\346\237\245\350\257\242.md" index b6f080a8ce506cd9f890867d1ec51bb78fe09748..a7933c33fdffc1ad149326abbb3385d5cc40e418 100644 --- "a/34\351\231\210\346\264\213/\347\254\224\350\256\260/0907\345\255\220\346\237\245\350\257\242.md" +++ "b/34\351\231\210\346\264\213/\347\254\224\350\256\260/0907\345\255\220\346\237\245\350\257\242.md" @@ -1,25 +1,424 @@ -一 子查询 +7. 一 子查询 -**子查询**是一个嵌套在**select**、**insert**、**update**、**delete**语句的其他查询中的查询。==任何允许使用表达式的地方都可以使用子查询==。子查询也称为内部查询或内部选择,而包含子部查询的语句也称为外部查询或外部选择 + **子查询**是一个嵌套在**select**、**insert**、**update**、**delete**语句的其他查询中的查询。==任何允许使用表达式的地方都可以使用子查询==。子查询也称为内部查询或内部选择,而包含子部查询的语句也称为外部查询或外部选择 - - -==子查询的注意事项:== - -1. 子查询语法中的小括号 - -2. 可以使用子查询的位置:**where,select,having,==from(要用as取别名)==** - -3. 不可以使用子查询的位置:group by ,order by - -4. 主查询和子查询可以不是同一张表 - -5. 一般不在子查询中使用排序(但是在top-n问题分析中必须对子查询使用排序) - -6. 一般先执行子查询,再执行主查询(相关子查询除外) - -7. 单行子查询只能使用单行操作符;多行子查询只能使用多行操作符 - - 注意:当子查询为null值的问题 - - 子查询也可以作为赋值语句的一部分 \ No newline at end of file + + + ==子查询的注意事项:== + + 1. 子查询语法中的小括号 + + 2. 可以使用子查询的位置:**where,select,having,==from(要用as取别名)==** + + 3. 不可以使用子查询的位置:group by ,order by + + 4. 主查询和子查询可以不是同一张表 + + 5. 一般不在子查询中使用排序(但是在top-n问题分析中必须对子查询使用排序) + + 6. 一般先执行子查询,再执行主查询(相关子查询除外) + + 7. 单行子查询只能使用单行操作符;多行子查询只能使用多行操作符 + + 注意:当子查询为null值的问题 + + 子查询也可以作为赋值语句的一部分 + + ### 1 使用in 和 not in完成子查询 + + in[在] not in[不在] + + **in 和 not in==通常在where子句中使用==,在 in 或 not in后接的子查询中==可以有多个值出现==** + + 例:查询出所有选修课程都及格的学生的信息 + + ``` + select * from StudentInfo + where stuNO in (select stuid + from stuMarks + group by stuid + having min(Score) >= 60 + ) + ``` + + ------ + + ### 2.使用some、any、all进行查询 + + some[一些] any[任意的] all[全部] + + **在SQL查询中,`some`、`any`、`all` 后必须跟子查询** + + - **==some和any的查询功能是一样的==,where条件能够满足some和any所接的子查询中的==任意一个值==,就表示where条件成立** + - **all表示的是能够==满足==all所接的子查询中的==所有值==才成立** + - = any 等值于in + + 例:查询出某同学某一门考试成绩比“张秋利”同学所有分数都高的学生基本信息 + + ``` + select sti.* from stuMarks smk + inner join StudentInfo sti on sti.stuNo = smk.stuID + where score > all(select score + from stuMarks stm + inner join StudentInfo st on stm.stuID = st.stuNo + where stuName = '张秋利') + ``` + + 查询出某同学某一门考试成绩只需要比“张秋利”同学某个分数高的学生基本信息(stuMarks) + + ``` + select distinct sti.* from stuMarks smk + inner join StudentInfo sti on sti.stuNo = smk.stuID + where stuName <> '张秋利' and score > any(select score + from stuMarks stm + inner join StudentInfo st on stm.stuID = st.stuNo + where stuName = '张秋利') + ``` + + ------ + + ### 3.使用exists 和not exists完成子查询 + + **exists[存在]: 如果子查询结果非空,即记录条数1条以上,则exsts(子查询)返回true 或 false**,==可配合if语句使用if exists(条件)== + + **`exists` 和 `not exists`表示存在和不存在的意思。在语句中会==判断`exists` 或 `not exists`后接的子句是否存在和是否不存在==** + + 示例:查询出参加考试的学生的信息 + + ``` + select * from StudentInfo st + where exists (select stuid from stuMarks stm where st.stuNo = stm.stuID) --如果该条件成立就显示,上一行的查询结果 + ``` + + 也可以和if配合使用 + + ``` + if exists(子查询) + 语句 + ``` + + ------ + + ### 4.使用compute和compute by进行汇总查询 + + **compute 和 compute by子句使您得以用同一select语句即查看明细行,有查看汇总行。可以计算子组的汇总值,也可以计算整个结果集的汇总值** + + 当compute不带可选的by子句时,select语句有两个结果集: ● 每个组的第一个结果集是包含选择列表信息的所有明细行 ● 第二个结果集有一行,其中包含compute子句中所指定的聚合函数的合计 + + compute子句需要下列信息: ● 可选by关键字。它基于每一列计算指定的行聚合 ● 行聚合函数名称 SUM、AVG、MIN、MAX、或 COUNT ● 要对其执行行聚函数的列 + + 对结果先进行分组然后进行汇总计算时使用:compute by进行分组汇总查询 + + + + + + **东哥的** + + ## 回顾 + + 1. 变量的使用。要先用DECLARE 关键字声明,然后用SET或SELECT赋值。局部变量前必须有 “@” 作前缀,全局变量必须有 “@@” 作前缀。 + 2. 变量的输出可以用:PRINT或SELECT语句。 + 3. 逻辑控制语句提供了条件操作所需的顺序和逻辑。 + 4. 批处理可以提高语句执行的效率,使用“GO”作为结束标志。 + + + + ## 嵌套/子查询 + + #### 什么是子查询? + + **问题:编写T-SQL语句,查询“黄炜杰”同学的分数大于80 分的考试成绩记录?** + + ```sql + --实现方式1:连接查询 + --实现方式2: 子查询 + ``` + + + + #### 子查询的特点和优势 + + 1)使用灵活。 + + 1. 可以成为SQL 语句的多个部分。 + 2. **子查询作为查询条件使用**。 + + ```sql + --练习:查询学号在曾鹏前面的同学信息 + ``` + + 1. **子查询作为临时表使用**。 from () + + ```sql + --练习:查询所有学生的HTML成绩,如果学生没有成绩显示null + ``` + + 1. **子查询作为列使用**。 + + ```sql + --练习:查询所有学生的HTML成绩,如果学生没有成绩显示null + ``` + + 2)降低SQL 的语句的复杂度,提高SQL 语句的可读性。 + + #### 子查询 + + ![image-20220906173620206](E:\SQL高级\03-子查询\image-20220906173620206.png) + + ##### 按结果分类 + + ###### 标量子查询 : + + **通常可以使用连接查询替代** + + 标量子查询是指子查询返回的是**单一值**,如一个数字或一个字符串。 + + ```sql + --1.查询书目表(tb_bibliography)中,条码号(barcode)为"TP311.13"图书(需要在图书表中先查找"TP31L13"的ISBN号)的图书名称(name)和作者(author) + + + --2.查询借阅表(tb-record)中姓名为"邓承明"(需要在学生表中先查找"邓承明'的学号)的学生的借阅信息,显示学号(stu-num)和条码号(barcode) + ``` + + + + ###### 列子查询 + + **列子查询是指子查询返回的结果集是N行1列**,该结果通常来自对表某个字段的查询结果,带in关键字的子查询是最常用的一类子查询,在使用in关键字进行查询时,子查询语句返回的结果应该是一个数据列中的多个值,如果仅返回1个数值,则可用标量子查询代替。 + + ```sql + --in习题 + --查询学生表(tb-student)中和黄弘相同专业学生读者的学号(stu-num)姓名(name)和专业(major) + --先查询 黄宏的 专业 + select major from tb_student where name='黄弘' + --in代表:只要符合后面的条件就筛选出来 + select * from tb_student where major in (select major from tb_student where name='黄弘') + + + --查询学生表(tb-student)中还未还书的读者的学号(stu-num)和姓名(name) + --查询未还书学生的学号 + select stu_num from tb_record where return_time is null + --通过学号查询学生姓名 + select * from tb_student where stu_num in (select stu_num from tb_record where return_time is null) + + + --all any some 习题 + --1.查询学生表(tb-student)中,比信息学院出生日期最大的还要大的所有学生记录,即比信息学院年龄最小的还要小的所有记录,使用ALL关键字,显示学生的姓名(name)、出生日期(birth)和所属学院(school),同样的结果尝试用max()函数再实现一次。 + --信息学院学生最小年龄 + select birth from tb_student where school='信息学院' + select max(birth) from tb_student where school='信息学院' + + select * from tb_student where birth>(select max(birth) from tb_student where school='信息学院' ) + + --all关键字:>,<,= + select * from tb_student where birth>all(select birth from tb_student where school='信息学院') + --2.查询学生表(tb-student)中,比信息学院出生日期最小的还要大的所有学生记录,即比信息学院年龄最大的还要小的所有记录,使用ANY关键字,显示学生的姓名(name)、出生日期(birth)和所属学院(school)。尝试用SOME关键字代替ANY,重新执行后观察查询结果。 + select * from tb_student where birth>any(select birth from tb_student where school='信息学院') + select * from tb_student where birth>some(select birth from tb_student where school='信息学院') + --3.查询书目表(tb-bibliography)中,使用ANY关键字,每种类型中最贵的图 书名称(name)和价格(price) + -- =any 与 in 等价 + select max(price) 最贵的价格 from tb_bibliography group by category + select name 图书名称,price 价格 from tb_bibliography + where price in (select max(price) 最贵的价格 from tb_bibliography group by category) + + ``` + + + + ###### 行子查询 + + 行子查询是指子查询返回的结果集是1行N列,该子查询的结果通常是对表的某行数据进行查询而返回的结果集。 + + ```sql + --(1)查询书目表(tb_bibliography)中与《管理信息系统实用教程(第3版)》同作者(author),同类型(category)的书。 + --(2)查询学生表(tb_student)中与"邹睿睿'在同一个学院(school)且同一年级(学号头两位相同则表明在同一年级)学生的学号、姓名和学院。 + ``` + + + + ###### 表子查询(from子查询) + + 表子查询是指子查询返回是M行N列的结果集,查询语句可嵌套在FROM关 + 键字后,且需要定义别名。 + + ```sql + --查询每种图书在馆的本数,显示ISBN号(ISBN)、图书名称(name)和该图书的在馆数量。 + ``` + + + + ##### 按位置分类 + + ###### exists子查询 + + 关键字EXISTS构造子查询时,当子查询的结果集不为空时,则EXISTS返回的结果为TRUE,外层查询语句进行查询;当子查询的结果集为空时,则EXISTS返回的结果为FALSE,外层查询语句不进行查询。 + + ```sql + --(1)查询学生表(tb-student)中,是否有学生读者的姓名是"黄弘" + if exists(select stu_num from tb_record where stu_num in (select stu_num from tb_student where name='黄弘') and return_time is null) + print '有' + else + print '没有' + + --(2)查询书目表(tb-bibliography)中,库存数为0的书目名称(name) + ``` + + ## 排序函数 + + **排序函数 OVER( [分组子句] 排序子句[DESC][ASC] )** + + **排序子句 :ORDER BY 排序列,排序列…** + + 练习:使用各个排名函数对学员的Java 成绩进行排名,并仔细体会其中排序函数的具体用法与其中的区别。 + + ```sql + + ``` + + - ROW_NUMBER()函数生成的排序根据排序子句给出**递增连续的序号** + - RANK()函数生成的排序根据排序子句给出**递增的序号,但是存在并列并且跳空** + - DENSE_RANK() 函数生成的排序根据排序子句给出**递增的序号,但是存在并列不跳空** + + 根据上面三个函数,我们可以增加一个序列,但是有时候我们需要对数据进行分组,然后对分组后的数据进行增加序列,PARTITION BY可以与以上三个函数联合使用 + + ```sql + --学生的Java成绩,并根据成绩排名 + --row_number() + select StuName 姓名,ROW_NUMBER() over(order by score desc) 排名,score 分数 from StuScore + join stuinfo on StuInfo.StuID = StuScore.StuID + where subject = 'Java' + + --rank() + select StuName 姓名,rank() over(order by score desc) 排名,score 分数 from StuScore + join stuinfo on StuInfo.StuID = StuScore.StuID + where subject = 'Java' + + --DENSE_RANK() + select StuName 姓名,dense_rank() over(order by score desc) 排名,score 分数 from StuScore + join stuinfo on StuInfo.StuID = StuScore.StuID + where subject = 'Java' + + ``` + + + + + + ## 分页查询 + + #### 分页方案一 + + **使用top分页** + + ```sql + declare @PageSize int = 5 -- 每页5条 + declare @PageIndex int = 2 --第2页 + select top(@PageSize) * from Student + where Stuid not in (select top(@PageSize)*(@PageIndex-1)) StuId from Student + ``` + + + + #### 分页方案二 + + **使用row_number分页** + + ```sql + declare @PageSize int = 5 + declare @PageIndex int = 3 + select * from + (select ROW_NUMBER() over(order by StuId) RowId,*from Student) as Temp + where RowId between (@PageIndex-1)*@PageSize+1 and @PageIndex*PageSize + ``` + + + + + + + + ## 作业 + + #### 子查询练习 + + 1. 关羽的银行卡号为"6225547858741263",查询出余额比关羽多的银行卡信息,显示卡号,身份证,姓名,余额。 + 2. 从所有账户信息中查询出余额最高的交易明细(存钱取钱信息)。 + + ```sql + select * from BankCard + select * from CardExchange + declare @Cardno varchar(30) + select @Cardno = CardNo from BankCard where CardMoney = (select max(CardMoney) from BankCard) + + select * from CardExchange where CardNo = @Cardno + ``` + + + + 1. 查询有取款记录的银行卡及账户信息,显示卡号,身份证,姓名,余额。 + 2. 查询出没有存款记录的银行卡及账户信息,显示卡号,身份证,姓名,余额。 + 3. 关羽的银行卡号为"6225547858741263",查询当天是否有收到转账。 + 4. 查询出交易次数(存款取款操作)最多的银行卡账户信息,显示:卡号,身份证,姓名,余额,交易次数。 + + ```sql + select * from accountinfo + select top 1 * from (select cardno,count(*) 交易次数 from CardExchange group by cardno) c1 + inner join BankCard on c1.CardNo = BankCard.CardNo + inner join AccountInfo on BankCard.AccountId = AccountInfo.AccountId + order by 交易次数 desc + ``` + + + + 1. 查询出没有转账交易记录的银行卡账户信息,显示卡号,身份证,姓名,余额。 + + + + #### 分页查询练习 + + ```sql + --数据结构和数据如下: + create table Student + ( + StuId int primary key identity(1,2), --自动编号 + StuName varchar(20), + StuSex varchar(4) + ) + insert into Student(StuName,StuSex) values('刘备','男') + insert into Student(StuName,StuSex) values('关羽','男') + insert into Student(StuName,StuSex) values('张飞','男') + insert into Student(StuName,StuSex) values('赵云','男') + insert into Student(StuName,StuSex) values('马超','男') + insert into Student(StuName,StuSex) values('黄忠','男') + insert into Student(StuName,StuSex) values('魏延','男') + insert into Student(StuName,StuSex) values('简雍','男') + insert into Student(StuName,StuSex) values('诸葛亮','男') + insert into Student(StuName,StuSex) values('徐庶','男') + insert into Student(StuName,StuSex) values('周仓','男') + insert into Student(StuName,StuSex) values('关平','男') + insert into Student(StuName,StuSex) values('张苞','男') + insert into Student(StuName,StuSex) values('曹操','男') + insert into Student(StuName,StuSex) values('曹仁','男') + insert into Student(StuName,StuSex) values('曹丕','男') + insert into Student(StuName,StuSex) values('曹植','男') + insert into Student(StuName,StuSex) values('曹彰','男') + insert into Student(StuName,StuSex) values('典韦','男') + insert into Student(StuName,StuSex) values('许褚','男') + insert into Student(StuName,StuSex) values('夏侯敦','男') + insert into Student(StuName,StuSex) values('郭嘉','男') + insert into Student(StuName,StuSex) values('荀彧','男') + insert into Student(StuName,StuSex) values('贾诩','男') + insert into Student(StuName,StuSex) values('孙权','男') + insert into Student(StuName,StuSex) values('孙坚','男') + insert into Student(StuName,StuSex) values('孙策','男') + insert into Student(StuName,StuSex) values('太史慈','男') + insert into Student(StuName,StuSex) values('大乔','女') + insert into Student(StuName,StuSex) values('小乔','女') + ``` + + **方式一:使用row_number** + + **方式二:使用top分页** + + \ No newline at end of file diff --git "a/34\351\231\210\346\264\213/\347\254\224\350\256\260/0914\347\264\242\345\274\225.md" "b/34\351\231\210\346\264\213/\347\254\224\350\256\260/0914\347\264\242\345\274\225.md" new file mode 100644 index 0000000000000000000000000000000000000000..060a1294cd4177654d200139ead88e30ea7775c8 --- /dev/null +++ "b/34\351\231\210\346\264\213/\347\254\224\350\256\260/0914\347\264\242\345\274\225.md" @@ -0,0 +1,88 @@ +## 索引 + +#### 什么是索引? + +汉语字典中的汉字按页存放,一般都有汉语拼音目录(索引)、偏旁部首目录等我们可以根据拼音或偏旁部首,快速查找某个字词。 + +![](https://gitee.com/snailclass/tuchuang/raw/master/img/book1-2022-9-1310:41:20.png) + +索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的特殊数据库结构,它是某个表中一列或若干列值的[集合](https://so.csdn.net/so/search?q=集合&spm=1001.2101.3001.7020)和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到需要的内容。 + +**建立索引的作用如下**: + +- 提高查询速度 + +- 保证数据记录的唯一性 + +- 查询优化靠索引起作用 + +- 提高order by, group by 执行速度 + +#### 索引分类 + +**索引主要分为两类**: + +- **聚集索引(clustered)**:根据数据行的键值在表或视图中的排序存储这些数据行,每个表只有一个聚集索引。聚集索引是一种对磁盘上实际数据重新组织以按指定的一列或多列值排序(类似字典中的拼音索引)(物理存储顺序)。 + + ![img](https://gitee.com/snailclass/tuchuang/raw/master/img/%E5%9B%BE%E7%89%872-2022-9-1316:27:08.png) + +- **非聚集索引 (nonclusterted)**:具有独立于数据行的结构,包含非聚集索引键值,且每个键值项都有指向包含该键值的数据行的指针。(类似字典中的偏旁部首索引)(逻辑存储顺序)。 + + ![img](https://gitee.com/snailclass/tuchuang/raw/master/img/%E5%9B%BE%E7%89%872-2022-9-1316:27:08.png) + +**其它类型的索引**: + +- 按照数据唯一性分类:唯一索引、非唯一索引 +- 按键列个数区分:单列索引,多列索引 + +- 其他分类:索引视图、包含性列索引、全文索引、XML索引等 + +#### 索引的创建与使用 + +- 索引的创建 + +```sql +--01创建索引基本语法 +CREATE [UNIQUE] [CLUSTERED | NONCLUSTERED] +INDEX ON ( [ASC|DESC][,...n]) + +--练习:为DBSTUDENT创建score字段索引 + +--练习:查找姓名为MikeSullivan、年龄17岁用户的peopleid +--分别使用单列索引和多列索引 +``` + +- 索引的使用 + +```sql +--使用索引进行查询 +``` + +- 索引的删除 + +```sql +--删除索引 +``` + + + +TIPS: + +- 索引信息存储在系统视图sys.indexes中 +- 可以使用系统存储过程:exec sp_helpindex查看当前表的索引 +- 填充因子:一页需要填充多少数据。 + + + +#### 使用索引的注意事项 + +- 使用聚集索引的查询效率要比非聚集索引的效率要高,但是如果需要频繁去改变聚集索引的值,写入性能并不高,因为需要移动对应数据的物理位置。 +- 非聚集索引在查询的时候可以的话就避免二次查询,这样性能会大幅提升。 +- 不是所有的表都适合建立索引,只有数据量大表才适合建立索引,且建立在选择性高的列上面性能会更好 +- 在where后使用or,导致索引失效(尽量少用or) +- 使用like ,like查询是以%开头,以%结尾不会失效 +- 不符合最左原则(多列索引) +- 如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引 +- 使用in导致索引失效 + +## 视图 \ No newline at end of file