30461索引与视图

匿名 (未验证) 提交于 2019-12-02 23:45:01

第8章 索引与视图



为了提高对数据表或视图的搜索效率。





8.1.2 何种情况下创建索引







8.1.3 索引的原理――B_树




(1)树中每个节点最多有m棵子树。
(2)根节点除外,所有非叶子节点至少都包含m/2棵子树。
(3)若根节点不是叶子节点,则根节点至少两棵子树。
(4)所有非叶子节点都包含相应的关键信息,一个包含k+1棵子树的非叶节点恰好包含k个关键字。


k表示关键字的个数。Ki(i=1,2,…,k)为关键字,且Ki < Ki+1。Ai(i=0,2,…,k)为指向相应子树根节点的指针,且指针Ai-1所指子树中所有节点的关键字均小于Ki(i=1,2,…,k),而Ai+1所指子树中所有节点的关键字均大于Ki(i=1,2,…,k-1)


(5)所有的叶子节点都出现在同一层次上,并且叶子节点不包含任何关键字信息。

8.2.1 聚集索引和非聚集索引


1. 聚集索引(Clustered Index)








    使用BETWEEN、>=、>、<=、<等运算符的查询
    使用JOIN子句的查询
    使用GROUP BY子句的查询
    返回大结果集的查询

    字段值唯一的字段(特别是标识字段),或绝大部分字段值都不重复的字段,如90%字段值都不重复的字段
    按顺序被访问的字段


    更新频繁的字段。因为在数据更新时,为保持与聚集索引的一致性必须移动表中的记录。对数据量大的数据表而言这种移动过程是耗时的,因而是不可取的。
    宽度比较长的字段。因为非聚集索引键值都包含聚集索引键,这会导致所有非聚集索引的“膨胀”,增加非聚集索引的长度,降低查询效率。



2. 非聚集索引(Non-Clustered Index)



【例子】 我们考虑表student中对s_no字段创建的非聚集索引。其可能的非聚集索引结果如图8.3所示。




非聚集索引的索引指针是允许“相交”的(这是非聚集索引的主要特点),这是因为在非聚集索引中B_树的叶子结点保存的是记录的指针,索引顺序与数据记录的物理顺序不需要保持一致,只要索引指针正确指向相应的记录即可。

















8.2.2唯一索引与非唯一索引








8.2.3 组合索引









8.3.1 聚集索引




CREATE CLUSTERED INDEX index_name ON table_name(col_list [DESC | ASC]);  





【例8.1】 创建一个聚集索引。

CREATE TABLE student2(     s_no char(8)         ,     s_name char(8)         NOT NULL,     s_sex char(2)         CHECK(s_sex = '男' OR s_sex = '女’),     s_birthday smalldatetime    CHECK(s_birthday>='1970-1-1' AND s_birthday<='2000-1-1’),     s_speciality varchar(50)     DEFAULT  '计算机软件与理论’,     s_avgrade numeric(3,1)     CHECK(s_avgrade >= 0 AND s_avgrade <= 100),     s_dept varchar(50)                       DEFAULT  '计算机科学系' );




INSERT student2 VALUES('20170205','贾簿','男','1994-09-03','计算机软件与理论',43.0,'计算机系'); INSERT student2 VALUES('20170206','李思思','女','1996-05-05','计算机应用技术',67.3,'计算机系'); INSERT student2 VALUES('20170207','蒙恬','男','1995-12-02','大数据技术',78.8,'大数据技术系'); INSERT student2 VALUES('20170208','张宇','女','1997-03-08','大数据技术',59.3,'大数据技术系'); INSERT student2 VALUES('20170201','刘洋','女','1997-02-03','计算机应用技术',98.5,'计算机系'); INSERT student2 VALUES('20170202','王晓珂','女','1997-09-20','计算机软件与理论',88.1,'计算机系'); INSERT student2 VALUES('20170203','王伟志','男','1996-12-12','智能科学与技术',89.8,'智能技术系'); INSERT student2 VALUES('20170204','岳志强','男','1998-06-01','智能科学与技术',75.8,'智能技术系');


SELECT * FROM student2; 









CREATE CLUSTERED INDEX myIndex1        -- 创建聚集索引myIndex1 ON student2(s_no DESC); 









8.3.2 非聚集索引



CREATE [CLUSTERED] INDEX index_name ON table_name(col_list [DESC | ASC]);  



【例8.2】 创建一个非聚集索引。

CREATE NONCLUSTERED INDEX myIndex2  -- 创建非聚集索引myIndex2 ON student(s_name);


上述代码中,关键字NONCLUSTERED可以省略。





【例8.3】 强制引用指定的非聚集索引。

SELECT * FROM student WITH (INDEX (myIndex2))   -- 强制引用索引myIndex2 WHERE s_name='刘洋';



8.3.3 唯一索引


CREATE UNIQUE INDEX index_name ON table_name(col_list [DESC | ASC]);  


【例8.4】 创建一个唯一非聚集索引。
在本例中,对表student的s_avgrade列创建一个唯一非聚集索引,使索引列降序排序。相应代码如下:

CREATE UNIQUE INDEX myIndex3      -- 创建唯一非聚集索引myIndex3 ON student(s_avgrade DESC)  






CREATE UNIQUE INDEX myIndex5 ON SC(s_no DESC, c_name ASC);





8.4.1 查看索引


sp_helpindex [ @objname = ] 'name‘;



index_name:返回索引名;
index_description:返回索引说明,如是否是聚集索引、唯一索引等信息,其中包括索引所在的文件组;
index_keys:返回对其生成索引的列。



sp_helpindex 'student';








    USE MyDatabase;     GO     SELECT * FROM sys.indexes;




8.4.2 删除索引


DROP INDEX index_name ON table_name;


DROP INDEX table_namet.index_name;



DROP INDEX myIndex2 ON student;     --也可以写成: DROP INDEX student.myIndex2





【例8.9】 删除定义PRIMARY KEY约束时创建的索引。

ALTER TABLE student DROP CONSTRAINT PK__student__2F36BC5B91406173




8.5.1 视图的概念








8.5.2 视图的优缺点












(3)自组织数据


(4)组合分区数据


(5)便于数据共享


(6)提高安全性





(1)相对低效


(2)有限的更新操作



8.6.1 创建视图


CREATE VIEW view_name [(column [,...n])] AS select_statement;



【例8.10】 创建与基表完全相同的视图。

CREATE VIEW myView1 AS SELECT * FROM student;



SELECT * FROM myView1



可以看到,视图myView1中的数据与表student中的数据是完全一样的


【例8.11】 创建包含基表中部分数据的视图,并给视图设定新的中文字段名。


CREATE VIEW myView2(学号,姓名,专业,平均成绩,系别) AS SELECT s_no, s_name, s_speciality, s_avgrade, s_dept FROM student WHERE s_avgrade>=60;


SELECT * FROM myView2



--注意,视图myView2包含的字段名为“学号”、“姓名”、“专业”、“平均成绩”和“系别”, --而s_no, s_name, s_speciality, s_avgrade, s_dept不是该视图的字段名了, --因此下列的SELECT语句都是错误的: SELECT s_no, s_name, s_speciality, s_avgrade, s_dept FROM myView2 SELECT s_no, s_name FROM myView2 --而下列的SELECT则是正确的: SELECT 学号,姓名,专业,平均成绩,系别 FROM myView2




【例8.12】 创建带有两个基表的视图。

CREATE VIEW myView3 AS SELECT student.s_no 学号, s_name 姓名, s_sex 性别, s_speciality 专业, s_dept 系别, c_name 课程名称, c_grade 课程成绩 FROM student, SC WHERE student.s_no = SC.s_no





【例8.13】 用视图更新数据表。

CREATE VIEW tmp_view AS SELECT s_no, AVG(c_grade) as s_avgrade FROM SC GROUP BY s_no


其次,表student和视图tmp_view的联系是基于字段s_no的(1:1)联系,因此我们可以用视图tmp_view中的平均成绩字段s_avgrade去更新表student中的平均成绩字段s_avgrade:

UPDATE student SET s_avgrade = b.s_avgrade FROM  student as a JOIN tmp_view as b ON a.s_no = b.s_no 





CREATE FUNCTION myFunView(@a float, @b float) RETURNS TABLE AS   RETURN   (     SELECT *     FROM student         WHERE s_avgrade >= @a and s_avgrade <= @b   );


  SELECT * FROM myFunView(60,90)


UPDATE myFunView(60,90) SET s_dept= '智能技术系‘






8.6.2 更新视图





UPDATE myView2 SET 平均成绩 = 80;






       UPDATE myView3               SET 性别 = '女', 课程成绩 = 99




        UPDATE myView3 SET 性别 = '女’         UPDATE myView3 SET 课程成绩 = 99





8.6.3 删除视图


DROP VIEW [ schema_name . ] view_name [ ...,n ] [ ; ]





DROP VIEW myView1, myView2;




8.7.1 视图的定义代码


如果视图的定义代码没有被加密,我们可以查看它的定义代码。


查看视图myView1的定义代码,可以利用系统存储过程sp_helptext来实现。其实现代码如下:

sp_helptext myView1;


执行上述存储过程,结果如图8.10所示。


8.7.2 视图的结构信息





本例将查看视图myView1,使用系统存储过程sp_help的代码如下:

sp_help myView1;


执行上述代码,结果如图8.11所示。




8.7.3 数据库中的视图





【例8.19】 查看当前数据库中所有用户定义的视图。

USE MyDatabase; GO SELECT name '视图名称(当前数据库)' FROM sys.views; GO

执行上述代码,结果如图8.12所示。


SELECT name '视图名称(所有数据库)' FROM sys.all_views;




易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!