目录
[2) 使用T-SQL](#2) 使用T-SQL)
通过之前的学习,已经能够熟练的操作数据库数据表,并使用相关数据表来查询自己想要的信息。由于在实际业务中,数据表的记录很多,随着时间的推移数据量会更多,会造成查询速度越来慢。因此给表创建索引就是一个能够提高速度,优化查询的有效方法。
就像是给厚厚的字典添加索引可以帮助尽快查找字词一样。SQLserver数据库可以通过适当的索引帮助减少查询工作量,提高查询特定信息的速度。
查询数据信息是数据库应用系统的主要功能,可以利用索引和视图对查询进行优化。
一,创建和管理索引
1,索引的概念
索引是一个数据列表,这个列表包含某张表中的一列或若干列值(也叫键值)的有序集合,并记录与这些值相对应的数据行在表中存储的物理地址。
一张表的存储是由两部分组成的:
- 数据页:存放表
- 索引页:存放索引键值和指向对应记录的指针
通常索引页相对于数据页来说小得多。
在进行数据检索时,系统首先检索索引页,从而找到所需记录的指针,然后通过指针从数据页中读取数据,从而提高查询速度。
例如,由于姓名索引中的姓名按照字母顺序(或其它定义的顺序)排列,是一个有序集合,从有序集合中查找信息一定比从无序集合中查找信息快,因此可以将学生表students中的姓名sne列作为一个索引,即基于学生表中学生姓名字段创建一个姓名索引。
2,索引的分类
索引键值是索引中用于标识和定位记录的字段值。
例如,在一张课程表中,如果"课程名"列被用作索引,那么该列对应的值就是该索引的键值。
根据索引键值有无重复,分为唯一索引和非唯一索引。
-
唯一索引(UNIQUE INDEX):
索引列中的每个值都是唯一的,即没有重复值。可确保数据的完整性,防止插入重复数据。
由于每个NULL值在唯一索引中只被视为一个实例,因此可以有多个NULL值。
常用于需要确保数据唯一性的列,例如电子邮件地址、用户名、身份证号等
-
非唯一索引:
允许索引列中的值重复。因为主要用于提高查询性能,所以不强制要求列中的值唯一。
索引键值可以重复,允许多个记录具有相同的值。也可以包含NULL值。
常用于提高查询性能的列,例如用于频繁查询的外键列或其他常用的搜索字段
根据存储结构的不同,将索引分为聚集索引和非聚集索引。
-
聚集索引:
根据数据行的键值,在表或视图中排序和存储这些数据行,即,表中数据页会按照该索引的
顺序来存放,索引顺序和记录的物理顺序一致。
每张表只有一个聚集索引,看起来,似乎和之前学的主键约束一样?其实不一样:
1)主键约束用来唯一标识表中的记录,而聚集索引则决定表中记录的存储顺序 。
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)在主键列创建聚集索引
2)外键或在表连接操作中经常用到的列
3)经常查询的数据列
-
不创建索引的列
1)很少在查询中被引用的列
2) 重复值较多的列
3) 定义为text,ntext或image数据类型的列
-
系统会自动为下列字段创建索引
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个):
- 视图是查看数据库表中数据的一种方法。
- 视图存储了预定义的查询语句,可以重复使用。
- 视图是一种逻辑对象,并不存储数据。
- 视图中被引用的表称为视图的基表。
创建视图,是为了保证数据的安全性及简化查询。
例如,某单位的员工表包括:员工号,姓名,性别,出生日期,身份证号码,部门,家庭住址,联系电话,工资账号,薪资待遇等信息。
现在有两个两个人:张三和王五,他们两个人分别管理不同的数据。
鉴于张三有前科,出于安全考虑,要求张三只能浏览员工的基本信息:
员工号,姓名,性别,出生日期,部门等。
李四只比张三多了员工薪资这一列的信息。
可以看到,针对不同的用户,同一张表,所展示的内容会有所不同。如果每次展示的时候都需要重新从表格中获取,无疑是重复且没意义的。由于每个视图只有限定的内容且可以像数据表一样分配权限,因此可以通过视图来实现上述要求。
视图的作用如下:
-
集中数据。
将数据集中于视图中,用户可以着重于所负责的特定事物数据。
-
对数据提供保护。
对不同的用户定义不同的视图,使机密数据不出现在不应看到这些数据的用户视图上,这种机制提供了对机密数据的自动安全保护功能。
-
简化用户操作。
简化复杂的结构,方便对数据的操作。
-
为数据库重构提供了一定程度的逻辑独立性。
若用户通过视图访问数据库,当数据库的逻辑结构发生改变时,只需要改变视图的定义,而基于视图的查询不需改变,用户程序不必改变。
知道了视图的作用及好处之后,接下来通过任务来创建视图。
2,创建视图
任务如下:
-
创建包含students表的学号,姓名,性别,班级的视图。
除了这个使用SSMS在图形化界面创建外,其他任务都使用T-SQL语句。
-
创建包含学生信息,课程信息和成绩信息的视图。
-
查询1班学生的名单(学号,姓名)并按照学号升序排序。
-
查询每门课程的平均成绩(课程号,课程名称,平均成绩)。
-
查询"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 语句中给列起别名)
- 当列是从算术表达式,函数或常量派生来的。
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语句在表中修改数据一样,实质都是转换为对基表的操作。
需要注意:
-
任何通过视图的数据修改都只能修改一张基表的列,不能同时影响多张表。
-
通过视图修改的列必须是直接引用基表中的列。
对于通过使用集合函数得到或使用表达式由多个字段得到的列,不能进行修改操作。
-
如果在视图定义中使用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为空,就会违反唯一约束的规定。
有两种方法:
- 删除联系电话spe的唯一约束。
- 为视图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,视图的优缺点
通过以上对视图的学习和使用,可以总结出视图的优缺点,如下。
优点:
- 数据保密。对不同的用户定义不同的视图,使其只能看到与自己有关的数据。
- 简化查询操作。为复杂的查询建立一个视图,针对此视图做简单的查询。
- 保证数据的逻辑独立性。构成视图的基本表改变时,只需改变视图的定义,而基于视图的查询不需改变。
缺点:
- 性能降低。
- 修改受限。
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重命名对象。 而是删除对象,然后使用新名称重新创建该对象。具体详情可点击下面链接查看:
4)删除视图
语法如下:
sql
DROP VIEW 视图名
例如在创建视图部分,我就已经学会了删除视图:
有问题请在评论区留言或者是私信我,回复时间不超过一天。