SQL server学习08-使用索引和视图优化查询

目录

一,创建和管理索引

1,索引的概念

2,索引的分类

3,创建索引的原则

4,创建索引

1)使用SSMS的图形化界面

[2) 使用T-SQL](#2) 使用T-SQL)

二,创建和使用视图

1,视图概念

2,创建视图

1)使用SSMS在图形化界面

2)使用T-SQL语句创建视图

3,通过视图查询数据

4,通过视图修改数据

5,视图的优缺点

6,使用T-SQL管理视图

1)查看视图定义

2)修改视图定义

3)重命名视图

4)删除视图


通过之前的学习,已经能够熟练的操作数据库数据表,并使用相关数据表来查询自己想要的信息。由于在实际业务中,数据表的记录很多,随着时间的推移数据量会更多,会造成查询速度越来慢。因此给表创建索引就是一个能够提高速度,优化查询的有效方法。

就像是给厚厚的字典添加索引可以帮助尽快查找字词一样。SQLserver数据库可以通过适当的索引帮助减少查询工作量,提高查询特定信息的速度

查询数据信息是数据库应用系统的主要功能,可以利用索引和视图对查询进行优化。

一,创建和管理索引

1,索引的概念

索引是一个数据列表,这个列表包含某张表中的一列或若干列值(也叫键值)的有序集合,并记录与这些值相对应的数据行在表中存储的物理地址。

一张表的存储是由两部分组成的:

  1. 数据页:存放表
  2. 索引页:存放索引键值和指向对应记录的指针

通常索引页相对于数据页来说小得多。

在进行数据检索时,系统首先检索索引页,从而找到所需记录的指针,然后通过指针从数据页中读取数据,从而提高查询速度。

例如,由于姓名索引中的姓名按照字母顺序(或其它定义的顺序)排列,是一个有序集合,从有序集合中查找信息一定比从无序集合中查找信息快,因此可以将学生表students中的姓名sne列作为一个索引,即基于学生表中学生姓名字段创建一个姓名索引。

2,索引的分类

索引键值是索引中用于标识和定位记录的字段值。

例如,在一张课程表中,如果"课程名"列被用作索引,那么该列对应的值就是该索引的键值。

根据索引键值有无重复,分为唯一索引和非唯一索引。

  1. 唯一索引(UNIQUE INDEX):

    索引列中的每个值都是唯一的,即没有重复值。可确保数据的完整性,防止插入重复数据。

    由于每个NULL值在唯一索引中只被视为一个实例,因此可以有多个NULL值。

    常用于需要确保数据唯一性的列,例如电子邮件地址、用户名、身份证号等

  2. 非唯一索引:

    允许索引列中的值重复。因为主要用于提高查询性能,所以不强制要求列中的值唯一。

    索引键值可以重复,允许多个记录具有相同的值。也可以包含NULL值。

    常用于提高查询性能的列,例如用于频繁查询的外键列或其他常用的搜索字段

根据存储结构的不同,将索引分为聚集索引和非聚集索引。

  1. 聚集索引:

    根据数据行的键值,在表或视图中排序和存储这些数据行,即,表中数据页会按照该索引的

    顺序来存放,索引顺序和记录的物理顺序一致。

    每张表只有一个聚集索引,看起来,似乎和之前学的主键约束一样?其实不一样:

    1)主键约束用来唯一标识表中的记录,而聚集索引则决定表中记录的存储顺序 。

    2)主键约束不能为空且不能有重复值,而聚集索引可以有重复值。

  2. 非聚集索引:

    具有独立于数据行的结构,索引中包含索引键值,指向包含该键值的数据行的指针。

    非聚集索引的数据表中记录的实际存储顺序可以不一致,每张表可以有多个非聚集索引。

根据索引建立在一列上还是多列上,分为单列索引和复合索引。

如下语句基于学生表students中的学生姓名sne字段创建了一个姓名索引(单列索引):

sql 复制代码
CREATE INDEX ix_students_sne ON students(sne)

接着看复合索引 。由于复合索引的列顺序会影响查询性能,因此通常将选择性高的列放在前面。

如下语句基于学生表students中的学生姓名sne和班级编号cno字段创建了一个复合索引:

sql 复制代码
CREATE INDEX ix_students_sne_cno ON students(sne,cno)

与单列索引相比,复合索引在某些情况下能够显著提高查询性能 ,如果一个查询同时使用了多个列作为条件,复合索引可以加速这些查询,而不需要分别对每个列进行索引查找。

3,创建索引的原则

虽然索引可以加快查询,但是索引并不是创建得越多越好,因为创建和维护索引需要时间和资源。因此知道知道创建索引的原则很重要。如下:

  1. 可以创建索引的列

    1)在主键列创建聚集索引

    2)外键或在表连接操作中经常用到的列

    3)经常查询的数据列

  2. 不创建索引的列

    1)很少在查询中被引用的列

    2) 重复值较多的列

    3) 定义为text,ntext或image数据类型的列

  3. 系统会自动为下列字段创建索引

    1) 为唯一性约束字段创建唯一索引

    2) 为主键约束字段创建聚集索引

    例如students表中在主键列学号sno,唯一列联系电话spe:

知道了创建索引的相关原则之后, 就可以开始创建索引。

4,创建索引

任务:在课程表courses上对课程名称cne列创建索引。

可以通过SSMS的图形化界面创建索引,也可以使用T-SQL语句创建索引(推荐)。

1)使用SSMS的图形化界面

由于任务要求在课程表courses上操作,因此,这里需要先展开课程表courses的表节点 ,如下👇

弹出如下界面后,指定索引名,之后点击添加,勾选指定的列,按照任务要求这里是课程名cne。由于课程名cne既不是主键列,也不是唯一列,因此我将该列设置成了不唯一,非聚集索引。

再点击"确定",之后刷新courses表,就可以看到索引栏下多了一个非聚集索引,如下👇:

2) 使用T-SQL

使用T-SQL创建索引的语句为:

sql 复制代码
CREATE [UNIQUE][CLUSTERED | NONCLUSTERED] INDEX 索引名
ON {表名 | 视图名} (索引列[ASC|DESC][,...n])

依旧是之前的任务:在课程表courses上对课程名称cne列创建索引。

由于之前通过SSMS创建了一个单列索引cne,因此如果想要再创建一个cne的单列索引,就需要将之前创建在索引删除,语法如下:

sql 复制代码
DROP INDEX 索引名 ON 数据表名

删除索引:

创建索引:

上面的任务是创建单列索引,接下来开始创建复合索引。

任务:在学生表上对姓名列和班级列创建复合索引(姓名列在前)

编写语句如下:

sql 复制代码
USE StuScore
CREATE INDEX ix_students_sne_cno ON students(sne,cno)

可以看到,如果不指定索引类型,创建的索引默认为不唯一,非聚集索引。

如果想要删除索引,可以使用如下语句:

sql 复制代码
--删除索引
DROP INDEX 表名.索引名

二,创建和使用视图

1,视图概念

视图是从一个多多个表中导出的虚拟表,由一组查询语言定义,数据库仅存有它的定义(索引视图除外),数据由引用视图时动态生成,视图的特点如下(4个):

  1. 视图是查看数据库表中数据的一种方法。
  2. 视图存储了预定义的查询语句,可以重复使用。
  3. 视图是一种逻辑对象,并不存储数据。
  4. 视图中被引用的表称为视图的基表。

创建视图,是为了保证数据的安全性及简化查询。

例如,某单位的员工表包括:员工号,姓名,性别,出生日期,身份证号码,部门,家庭住址,联系电话,工资账号,薪资待遇等信息。

现在有两个两个人:张三和王五,他们两个人分别管理不同的数据。

鉴于张三有前科,出于安全考虑,要求张三只能浏览员工的基本信息:

员工号,姓名,性别,出生日期,部门等。

李四只比张三多了员工薪资这一列的信息。

可以看到,针对不同的用户,同一张表,所展示的内容会有所不同。如果每次展示的时候都需要重新从表格中获取,无疑是重复且没意义的。由于每个视图只有限定的内容且可以像数据表一样分配权限,因此可以通过视图来实现上述要求。

视图的作用如下:

  1. 集中数据。

    将数据集中于视图中,用户可以着重于所负责的特定事物数据。

  2. 对数据提供保护。

    对不同的用户定义不同的视图,使机密数据不出现在不应看到这些数据的用户视图上,这种机制提供了对机密数据的自动安全保护功能。

  3. 简化用户操作。

    简化复杂的结构,方便对数据的操作。

  4. 为数据库重构提供了一定程度的逻辑独立性。

    若用户通过视图访问数据库,当数据库的逻辑结构发生改变时,只需要改变视图的定义,而基于视图的查询不需改变,用户程序不必改变。

知道了视图的作用及好处之后,接下来通过任务来创建视图。

2,创建视图

任务如下:

  1. 创建包含students表的学号,姓名,性别,班级的视图。

    除了这个使用SSMS在图形化界面创建外,其他任务都使用T-SQL语句。

  2. 创建包含学生信息,课程信息和成绩信息的视图。

  3. 查询1班学生的名单(学号,姓名)并按照学号升序排序。

  4. 查询每门课程的平均成绩(课程号,课程名称,平均成绩)。

  5. 查询"SQL Server数据库应用技术"课程不及格的学生信息。

1)使用SSMS在图形化界面

任务1:创建包含学生表students的学号,姓名,性别,班级的视图。

在SSMS下,选择学生成绩管理数据库节点下的"视图"节点,右击,选择"新建视图":

由于任务要求是在学生表students上操作,因此,这里的视图基表为students👇

添加结束后,左击"关闭",进入创建视图的界面👇:

关系图窗格,选择和条件窗格和SQL窗格用于创建查询语句,这三个窗格保持同步,即在任一窗格中所完成的操作都会同时反映在其他两个窗格中。如下,我按照题目,勾选students的学号sno,姓名sne,性别ssx,班级cno:

就可以看到,关系和选择窗格,SQL窗格都发生了变化。

构建好创建视图的查询语句后,单击工具栏上的"执行"按钮:

就可以在结果窗格中看到对应的结果:

使用快捷键"Ctrl+s"或者是点击工具栏上的"保持"按钮,在弹出"选择名称"对话框中输入视图名称:

之后点击"确定"保存。 回到学生成绩管理数据节点下的"视图",可以看到视图创建及保存成功 :

2)使用T-SQL语句创建视图

语法如下:

sql 复制代码
CREATE VIEW[数据库名.][<架构名>.]视图名[(列名1[,...n])]
[WITH ENCRYPTION] --encryption:加密,加密术
AS
SQL
[WITH CHECK OPTION]

说明如下:

列名:视图中的列名(要么全部省略,要么全部指定)。

如果未指定列名表,则视图列将获得与SELECT 语句中的列相同的名称。

如果SELECT 语句中的列有别名,视图中就取列的别名作为视图中的列名。

任务2:创建包含学生信息,课程信息和成绩信息的视图(v_students_score),该视图包含学号,姓名,班级编号,课程号,课程名和成绩。(指定列名)

sql 复制代码
USE StuScore
GO

CREATE VIEW  v_students_score (sno,sne,cla,cno,cne,gets) --cla:class班级
AS 
SELECT st.sno AS 学号,sne AS 学生姓名,st.cno AS 班级编号,co.cno AS 课程编号,cne AS 课程名,gets AS 成绩得分
FROM students AS st,score AS sc,courses AS co
WHERE st.sno=sc.sno AND co.cno=sc.cno

可以看到,即使我在SELECT 语句中给相应的列取了别名,但是,创建视图时,依旧使用列表名里面的列名。

创建视图之后,也可以删除视图,语法如下:

sql 复制代码
DROP VIEW 视图名
sql 复制代码
DROP VIEW v_students_score

接下来我将列表里面的列名全部省略,并在SELECT语句中给列起别名:

sql 复制代码
USE StuScore
GO

CREATE VIEW  v_students_score 
AS 
SELECT st.sno AS 学号,sne AS 学生姓名,st.cno AS 班级编号,co.cno AS 课程编号,cne AS 课程名,gets AS 成绩得分
FROM students AS st,score AS sc,courses AS co
WHERE st.sno=sc.sno AND co.cno=sc.cno

只要在下列情况下,才必须命名CREATE VIEW 中的列(或在SELECT 语句中给列起别名)

  1. 当列是从算术表达式,函数或常量派生来的。

2)两个或更多的列可能会具有相同名称(通常是因为连接)。

3)视图中的某列被赋予了不同于派生来源列的名称。

定义视图的SELECT 语句

可以用具有任意复杂性SELECT 子句,使用多张表或其他视图来创建视图。在视图中被查询的表称为基表。

对于视图定义中的SELECT子句,有以下几个限制|:

1)不能包含COMPUTE 或 COMPUTE BY 子句。

2)不能包含ORDER BY 子句,除非在SELECT语句的选择列表中有TOP子句。

3)不能包含SELECT INTO关键字。

WITH CHECK OPTION

强制视图上执行的所有数据修改语句,都必须符合定义视图的WHERE子句设置的条件。

WITH ENCRYPTION

表示对CREATE VIEW语句文本的项进行加密,加密后无法浏览视图的定义。

上面已经创建好视图,之后使用SSMS打开视图:

可以看到视图中的三张表:学生表students st,成绩表 score sc 和 课程表courses co 中,成绩表有学生表和课程表的外键👇:

3,通过视图查询数据

创建好视图之后,可以应用视图进行数据查询,就像对表的查询一样,同事在满足一定条件下,可以应用视图进行数据添加,更新和删除。最终所有对视图的操作都转换成对基表的操作。

使用视图查询数据和使用表进行查询一样,其实是转换成对基表的查询。

下面利用前面创建好的视图查询数据。

任务3:查询1班学生的名单(学号,姓名)并按照学号升序排序。

sql 复制代码
USE StuScore
GO
SELECT sno AS 学号,sne AS 学生名 FROM v_students_list WHERE cno='1' ORDER BY sno

SELECT sno AS 学号,sne AS 学生名 FROM v_students_list  -- 包含2班的songjiang

如果要查询学生的联系电话spe,就会报错,如下:

可以看到,视图v_students_list中没有联系电话spe列,用户无法访问该信息。

这样就能保证用户只能看到学号和姓名,而不能看到其他列,所以使用视图能起到一定的数据保密作用。

任务4:查询每门课程的平均成绩(课程号,课程名称,平均成绩)

sql 复制代码
USE StuScore
GO
SELECT 课程编号,课程名,Avg(成绩得分) AS 平均成绩 FROM v_students_score 
GROUP BY 课程编号,课程名

任务5:查询"SQLserver DataBase Application principle"课程不及格的学生信息。

sql 复制代码
USE StuScore
GO
SELECT 学号,学生姓名,课程编号,课程名,成绩得分
FROM v_students_score
WHERE 课程名='SQLserver DataBase Application principle' 
AND 成绩得分<60

4,通过视图修改数据

用户可以通过视图修改基表的数据,其方法与使用UPDATE,INSERT,DELETE语句在表中修改数据一样,实质都是转换为对基表的操作。

需要注意:

  1. 任何通过视图的数据修改都只能修改一张基表的列,不能同时影响多张表。

  2. 通过视图修改的列必须是直接引用基表中的列。

    对于通过使用集合函数得到或使用表达式由多个字段得到的列,不能进行修改操作。

  3. 如果在视图定义中使用WITH CHECK OPTION字句,则所有在视图上执行的修改操作都必须符合定义视图的SELECT 语句中所设置的检索条件。

任务1:建立一个包含女生信息的视图(包含学号,学生姓名,性别,所属班级),并要求通过视图修改的数据仍是女生。

编写语句:

sql 复制代码
USE StuScore
GO
CREATE VIEW v_female
AS
SELECT sno AS 学号,sne AS 学生姓名,ssx AS 性别,cno AS 所属班级
FROM students
WHERE ssx='female'
WITH CHECK OPTION

结果图:

任务2:利用任务1建立的视图v_female,插入一条记录:

学号 7 ,姓名 红果果 hongguoguo,性别 女,所属班级 2 班。

编写语句如下:

sql 复制代码
USE StuScore
GO
INSERT INTO v_female(学号,学生姓名,性别,所属班级)
VALUES('7','hongguoguo','female','2')

查看视图的数据:

查看学生表students:

可以看到, hongguoguo红果果的出生日期和联系电话都为空NULL,由于国籍snn(student nation)设置了默认约束,所以会自动填充。

如果我再插入一条联系电话为空的女生信息,就会报错:

究其原因是因为联系电话spe设置了唯一约束,只能有一个空值,如果再添加另外一条记录的电话spe为空,就会违反唯一约束的规定。

有两种方法:

  1. 删除联系电话spe的唯一约束。
  2. 为视图v_female添加一个列"联系电话"spe。(推荐)

使用第2中方法,修改视图:

sql 复制代码
USE StuScore
GO
ALTER VIEW v_female 
AS 
SELECT sno AS 学号,sne AS 学生姓名,ssx AS 性别,cno AS 所属班级,spe AS 联系电话
FROM students WHERE ssx='female'
WITH CHECK OPTION

修改之后,记得刷新视图。

接着将刘艳liuyan的信息添加进去:

sql 复制代码
INSERT INTO v_female(学号,学生姓名,性别,所属班级,联系电话)
VALUES('8','liuyan','female','2','163xxxxxxxx')

如果我想要在存放了女生信息的视图v_female中,插入一条男生记录,就会报错:

是因为在我在创建v_female视图时,带有WITH CHECK OPTION 选项,因此在利用视图修改数据时,任必须满足性别ssx='female'的检索条件。

查看视图v_female及学生表students的信息,可以看到,没有将不符合检索条件的记录添加进去。

5,视图的优缺点

通过以上对视图的学习和使用,可以总结出视图的优缺点,如下。

优点:

  1. 数据保密。对不同的用户定义不同的视图,使其只能看到与自己有关的数据。
  2. 简化查询操作。为复杂的查询建立一个视图,针对此视图做简单的查询。
  3. 保证数据的逻辑独立性。构成视图的基本表改变时,只需改变视图的定义,而基于视图的查询不需改变。

缺点:

  1. 性能降低。
  2. 修改受限。

6,使用T-SQL管理视图

1)查看视图定义

使用系统存储过程SP_HELPTEXT(个人记忆:store process help text:存储过程帮助文本)

语法如下:

sql 复制代码
SP_HELPTEXT 视图名

例如,查看视图v_students_score的定义:

sql 复制代码
USE StuScore
GO
SP_HELPTEXT v_students_score

2)修改视图定义

语法如下:

sql 复制代码
ALTER VIEW 视图名[列表名]
[WITH ENCRYPTION]
AS
SQL 语句
[WITH CHECK OPTION]

例如前面在向视图v_female插入输入时,对视图进行的修改

3)重命名视图

尽管可以使用 SP_RENAME 更改视图的名称,但是建议删除现有视图,然后使用新名称重新创建视图。使用 SP_RENAME重命名存储过程、函数、视图或触发器时,sys.sql_modules 目录视图的定义列中相应对象的名称不会更改。 这可能会在以后造成混淆。 因此,不建议使用 SP_RENAME重命名对象。 而是删除对象,然后使用新名称重新创建该对象。具体详情可点击下面链接查看:

重命名视图 - SQL Server | Microsoft Learn有关如何重命名视图的教程。https://learn.microsoft.com/zh-cn/SQL/relational-databases/views/rename-views?view=sql-server-linux-ver16

4)删除视图

语法如下:

sql 复制代码
DROP VIEW 视图名

例如在创建视图部分,我就已经学会了删除视图:

有问题请在评论区留言或者是私信我,回复时间不超过一天。

相关推荐
2401_8576363912 分钟前
SSM 寝室管理系统:为住宿生活保驾护航
android·数据库·生活
大乔乔布斯1 小时前
MySQL批量删除字段跑路?
数据库·sql·mysql
TDengine (老段)1 小时前
TDengine 新功能 通过 UID 删除不可见表
大数据·数据库·物联网·时序数据库·tdengine
娶个名字趴1 小时前
Redis(2)常用命令
java·数据库·redis·缓存
明月清了个风1 小时前
数据结构与算法学习笔记----Floyd算法
笔记·学习·算法
编码浪子2 小时前
构建一个rust生产应用读书笔记7-确认邮件1
数据库·rust·php
Riching52 小时前
对BG兼并点的理解-不断刷新版
经验分享·学习
buyue__2 小时前
MacOS安装MySQL
数据库·mysql
YZW01233 小时前
QT之QML学习:QFileDialog 报错log4cplus:ERROR解决方案
开发语言·qt·学习
南宫生3 小时前
力扣-图论-15【算法学习day.65】
java·学习·算法·leetcode·图论