zoukankan      html  css  js  c++  java
  • mysql 详解02

    参考朱双印的mysql 专题 http://www.zsythink.net/archives/category/%e5%ad%98%e5%82%a8/mysql/page/5/

    本博客仅为笔者个人参考学习使用,推荐通过学习朱双印的mysql专题来全面学习

    本篇包含的内容

    • 约束管理、索引管理、键管理语句
    • 视图管理语句

    (一)约束管理、索引管理、键管理语句

    关系型数据库中的数据约束的概念为:数据约束可以理解为向数据表中插入数据时要遵守的限制规则

    mysql中的常用约束有主键约束、唯一键约束、外键约束、非空约束等,我们先列出其概念。

    • 主键:primary key,表上一个或多个字段的组合,填入主键字段中的数据,必须不同于已经存在的其它行的相同字段上的数据,而且也不能为空;一个表只能存一个主键,一个主键可以由多个字段组成
    • 惟一键:unique key,表上一个或多个字段的组合,填入其中字段中的数据,必须不同于已经存在的其它行的相同字段上的数据,但可以为空;一个表可以有多个唯一键;
    • 外键:foreign key,一个表中的外键字段中所能够插入的数据取值范围,取决于引用的另一个表上主键字段上的已经存在数据集合;

    非空约束

    添加非空约束,设置非空字段。使用如下语句为testtb表中的name字段添加非空约束。

    alter table testtb modify name varchar(100) not null;

    删除非空约束,去除非空约束只要将字段修改为可以为空即可,当然,如果字段有其他约束,不要忘了加载语句的后面。

    alter table testtb modify name varchar(100null;

    自动增长

    添加自动增长,为字段设置自动增长,同样既可以使用change,也可以使用modify

    如下语句表示为testtb表的id字段设置自动增长。

    alter table testtb modify id int auto_increment;

    如下语句表示为testtb表的id字段设置自动增长。

    alter table testtb change id id int auto_increment;

    删除自动增长,去除自动增长的语句可以结合着添加自动增长的语句查看。同样有两种方法,使用change或者modify均可。

    alter table testtb change id id int;
    alter table testtb modify id int;

    使用change 可以修改字段的名称

    主键约束

    添加主键约束

    使用如下两条语句中的任意一条均可为表设置主键,注意,一个表中只能有一个主键。

    如下命令表示将testtb4中的id字段指定为表的主键,通过如下语句设置的主键的主键名称默认为PRIMARY。

    alter table testtb4 add primary key(id);
    alter table testtb4 add constraint primary key(id);

    删除主键约束

    去除主键时需要注意,不能直接删除主键,需要先删除自动增长,然后再删除主键。

    注意:如果对应的主键上存在自动增长,则不能直接删除主键,需先删除自动增长后,再使用如下语句删除主键。同理,如果当前表的主键已经被其他表中的字段当做外键,那么则需要先删除其他表中的主外键关系,才能删除当前主键。

    alter table testtb drop primary key;

    唯一键约束

    添加唯一键约束

    使用如下语句,添加唯一键约束,唯一键的名称默认为字段名称,如果对一个字段重复创建唯一键,唯一键名称将会按照创建时的序号依次向后增加,但是针对同一个字段重复创建唯一键是没有任何意义的,也强烈不建议这样做。

    alter table testtb add unique key(uid);

    使用如下语句在创建唯一键的时候,可以指定唯一键的名称,例如,指定唯一键的名称为uni_test。

    alter table testtb add unique key uni_test(test);

    删除唯一键约束

    使用如下语句删除唯一键uni_test,注意,删除唯一键时使用的是index关键字

    alter table testtb drop index uni_test;

    查看约束

    desc test1

    查看主外键对应关系

    如下语句表示查看test1这张表中引用了哪些表中的主键作为自己的外键。也可以理解为查看test1表的外键。

    select TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME,REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME from information_schema.KEY_COLUMN_USAGE where TABLE_NAME='test01' and REFERENCED_TABLE_NAME is not null;

    如下语句表示查看test2这张表的主键被哪些表引用成为了外键,可以与上一个示例对比查看。

    select REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME,CONSTRAINT_NAME,TABLE_NAME,COLUMN_NAME from information_schema.KEY_COLUMN_USAGE where REFERENCED_TABLE_NAME='test2';

    添加外键约束

    使用如下两条语句设置外键,如下语句表示在testtb表中创建一个新的字段,tid,并且添加了一个外键,外键的名称叫testtb_tid_fk,外键中, testtb表中的tid字段引用了表testtb2表中的id字段

    alter table testtb add column tid int default 0 not null;
    alter table testtb add constraint testtb_tid_fk foreign key(tid) references testtb2(id);

    删除外键约束

    删除外键约束之前需要先查看外键约束的名称

    select TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME,REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME from information_schema.KEY_COLUMN_USAGE where TABLE_NAME = 'md_blogs' and REFERENCED_TABLE_NAME is not null;

    使用如下语句 ,表示删除test4表中的 test_tid_fk 外键。

    alter table test4 drop foreign key test_tid_fk;

    索引管理

    添加一个索引/创建一个纯粹的索引

    这里所说的纯粹的索引指的就是index,不是unique index,只是单纯的index,使用如下语句表示为testtb表的name字段添加一个单纯的索引,索引的名字为ind_name

    alter table testtb add index ind_name(name);

    当我们使用上述语句添加索引以后,使用show index from testtb;可以查看到对应的索引,但是在information_schema.KEY_COLUMN_USAGE 表中将不会存在同名的"约束",而当我们创建一个唯一键或者唯一索引的时候,不仅能在information_schema.KEY_COLUMN_USAGE表中看到对应名称的"约束",同时还能使用show index from testtb;查看到对应名称的索引,这就体现了"键/约束"与"索引"的不同,当我们创建一个约束的时候,会创建对应的索引,但是如果只是创建一个单纯的索引,"纯index",那么它则只是一个"索引"罢了。

    另外一种语法创建索引,语法如下。

    CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name [using index_type] ON tbl_name (index_col_name,...)

    上述语法中,我们可以指定创建哪种特殊索引,也可以只使用index,表示创建一个纯索引,[using index_type]表示索引类型,可省略,省略后默认使用btree类型的索引,并且指明在哪个表的哪个字段上创建索引。index_col_name用于指明字段名称,示例如下,如下语句表示在testtb表的name字段上创建一个索引,索引的名称为ind_name,索引的长度为20(注意,20并不是表示name字段的长度,假如name字段长度为100,此处指定20表示取出name字段的左边开头的头20个字节作为索引),索引为降序排列,不指定desc时默认以升序排序。

    create index ind_name on testtb (name(20) desc);
    create index ind_name on testtb (name(20));
    create index ind_name on testtb (name);

    如下示例语句表示创建一个联合索引

    create index ind_id_name on testtb1 (id,name);
    create index ind_id_name on testtb1 (id,name(20));

    重建索引

    数据库长时间运行后,索引会有损坏的可能,这个时候,重建索引,可以提高数据的检索速度,所以,重建索引的操作在平常的维护工作中可能会被用到,不过mariadb中的innodb存储引擎不支持重建索引。

    repair table table_name quick;

    删除一个索引

    使用如下语句可以删除testtb表中的纯索引以及唯一索引。

    alter table test2 drop index uu_ttt;

    查看索引

    查看testtb表中的所有索引

    show index from testtb;

    根据索引名称,查看testtb表中的部分索引,如下语句表示查看testtb表中以ind开头的索引。

    show index from testtb where key_name like 'ind%';

    (二)视图管理语句

    视图的概念

    视图是一个"虚表",用大白话说,就是从已经存在的表的全部字段或数据中,挑选出来一部分字段或数据,组成另一张"并不存在的表",这张虚表被称之"视图",视图中的字段与对应的数据均来自已经存在的表,对于视图来说,这些已经存在的表就被称为"基表",基表可以是一张表,也可以是多张表, 视图的本质可以理解为一条查询语句,视图中显示的结果,就是这条查询语句查询出的结果。

    使用视图的理由

    这个时候我们可能会有一个问题,既然视图中的字段均来自"基表",为什么还要使用"视图",我们直接使用"基表"就行了,干嘛还要用视图,这是有原因的,我们可以从以下几个方面理解。

    1,简化操作

    我们说过,视图中的数据可能来自于多张基表,如果基表有很多,而且基表之间存在复杂的关系,当我们需要找出某些数据时,可能需要执行一条复杂的sql语句,如果我们把这个复杂的sql语句创建为视图,我们就可以直接从视图的结果中使用简单的sql语句查询出需要的结果,这使我们容易理解和使用。

    2,安全原因

    安全原因往往是使用视图的主要原因,我们能通过视图,限制用户能够查看到的数据,比如我们创建了一张"供货商信息表",这张表里面存放了公司20个大区所有供货商的数据,如果我授权了数据库用户A对这张表有查看权限,那么A用户将有权利查看"供货商信息表"中所有供货商的信息,如果想要限制A用户,让其只能查看前三个大区的供货商信息,我们就可以使用视图,将前三个大区中的供货商信息查询出来,将对应sql语句创建成"前三大区供货商视图",然后授权A用户只能查看"前三大区供货商视图",但是不能查看"供货商信息表",那么数据库用户A则只能查看到前三个大区供货商的信息了,而不是能够看到所有供货商的信息,这就是我们之前所说的,视图是一张虚表,它的字段或者数据可能只是其他表中的一部分。

    不使用视图的理由

    mysql对于视图的优化并不完善,这样说并不准确,准确的说,应该是mysql对于子查询的优化不是很好,而使用视图本身往往就意味着使用子查询,所以,如果我们必须使用视图时,最好将视图中的sql语句尽量优化,或者说,数据量大的时候尽量避免使用视图。

    创建视图

    在创建视图之前,请先确定当前登录的数据库用户是否拥有创建视图的权限。

     查询结果中,create_view_priv的值为Y,表示当前用户拥有创建视图的权利。

    我们来创建一个最简单的视图

    我们可以把上图中创建视图的语句分成两个部分来看。

    create view testvi as 当做第一部分,这部分语句实现的功能就是创建一个名叫testvi的视图,这个视图中的内容从as 后面的查询语句中获得。

    select * from classes where classid <= 3;为上图中语句的第二部分,这部分语句的功能就是从classes表中查询出了classid号小于等于3的数据。

    这两个部分结合在一起,就表示,我们将查询语句查询出的结果创建为一个名叫testvi的视图。

    注意,视图是一种"虚表",所以不能与已经存在的表重名。

    此处我们先查询出classes表中的所有内容,方便与视图中的内容做对比。

    视图创建完了,我们来查看一下视图中的内容,视图是一种"虚表",我们查看视图就像查看表一样即可。

     可以看到,即使我们查询出了testvi视图中的所有信息,也只有3条数据,这3条数据都来自于classes表,还记得我们在概念中提到的"安全原因"吗,这种场景就跟"安全原因"中提到的场景相同。

    我们也可以使用如下语句创建视图

    create or replace view testvi as select * from classes where classid <= 4;

    create or replace view testvi as 表示,如果testvi这个视图如果不存在,那么则按照指定的查询语句创建视图,如果当下已经存在testvi这个视图,那么则使用当前视图覆盖之前的testvi视图,以当前的sql查询语句作为视图的语句。

    我们发现,视图创建后,视图中的字段名与"基表"中的字段名称相同,我们也可以让视图使用自己的字段名,而不是使用基表中的字段名称,我们可以在创建视图时使用如下语句。

     我们在概念中提到过,视图是由其他表中的一部分数据或者字段组成的,我们也可以只查询出"基表"中的部分字段,组成视图,示例如下

    从上述的举例中我们可以看出,创建视图是很简单的,视图中的内容主要取决于我们的查询sql写成什么样。

    所以,我们也可以通过sql语句,从多个表中查询出数据,创建视图。

     其实在创建视图时,还可以指定mysql处理视图的算法,算法会影响MySQL处理视图的方式,mysql可以使用两种算法处理视图,这两种算法为MERGE算法和TEMPTABLE算法,我们可以在创建视图时,使用ALGORITHM指定使用哪种算法处理当前视图,ALGORITHM的值可以设置为MERGE、TEMPTABLE、UNDEFINED。如果没有ALGORITHM子句,默认值为UNDEFINED(表示用户未指定固定的算法,mysql会自动从MERGE、TEMPTABLE中选择一个算法处理视图),那么这些算法有什么不同呢,我们后面再解释,先看看创建时的示例语句。

    上述语句表示指定使用merge算法处理视图。

    那么,每种算法有什么不同呢。

    1、MERGE算法:视图使用这种算法时,如果我们调用了视图,mysql会先将视图的定义转换成sql语句,然后把视图的sql语句与我们调用的语句整合,最后执行整合完毕的sql语句,什么意思呢,就以上图中的创建视图的sql语句为例,如果我们想要查看视图testvi中的所有数据,我们有可能会执行select * from testvi这条sql语句 ,如果testvi使用的是merge算法,那么mysql会先将执行的语句变成 select * from (select name,age from students;) ,然后执行最终改变过的语句,这就是merge算法对视图的处理过程,如果使用这种算法,即使定义视图时的sql语句不包含子查询,在我们调用视图的时候,最终执行的sql语句本身就一定包含子查询,而mysql对子查询的优化是不够的,当数据量大时,往往会影响性能,这就是不使用视图的理由。

    2、TEMPTABLE算法:视图的结果将被置于临时表中,然后使用它执行语句,什么意思呢,还是以上图中的testvi视图为例,如果把上图中的merge改成temptable,当我们执行 select * from testvi时,mysql会先查询到会先将select name,age from students;的查询结果放置到临时表中,然后用户的语句再调用临时表中的数据,当视图使用这种算法时,视图只能用于查询,不能用于更新数据

    3、UNDEFINED:当algorithm设置为此值时,MySQL将选择所要使用的算法。如果可能,它倾向于MERGE而不是TEMPTABLE,这是因为MERGE通常更有效,而且如果使用了临时表,视图是不可更新的

     删除视图

    删除视图很简单,使用如下语句删除testvi视图

    drop view testvi;

    如下语句表示如果视图testvi存在,则删除;

    drop view if exists testvi;

    查看视图

    我们可以查看数据库中存在哪些视图,也可以查看视图的结构,还可以查看视图中的内容,我们一个一个来。

    首先,如果我们想要查看某一数据库中的所有视图,可以使用如下语句查看:

    select * from information_schema.views where table_schema='U_DB_NAME';

    示例如下:

     我们也可以查看视图的结构,就像查看表的结构一样;

     我们也可以查看视图中的数据内容,就像查看表一样

     修改视图

    修改视图的语句如下

     更新视图中的数据

    在大部分情况下,创建视图是为了查看数据的,很少会去更新视图中的数据,即使想要去更新视图中的数据,也需要满足一定的条件,不是所有视图中的的数据都是可更新的。

    如果视图包含下述结构中的情况,那么它将是不可更新的:

    · 当视图设定了 ALGORITHM = TEMPTABLE。

    · 聚合函数(SUM(), MIN(), MAX(), COUNT()等)。

    · 位于选择列表中的子查询。

    · FROM子句中存在不可更新视图。

    · WHERE子句中的子查询,引用FROM子句中的表。

    · 仅引用文字值(此时没有要更新的基表)。

    · 基表中的其他字段中的约束不被满足。

    · DISTINCT

    · GROUP BY

    · HAVING

    · UNION 或 UNION ALL

    · Join

    注意:视图中虽然可以更新数据,但是有很多的限制。所以,一般我们只在查询时使用视图,而不要通过视图更新数据。

  • 相关阅读:
    关于Unity中Mecanim动画的重定向与动画混合
    php远程抓取网站图片并保存
    OpenResty最佳实践
    111
    安装Nginx+Lua+OpenResty开发环境配置全过程实例
    ecshop常用的一些变量
    php 常用的标签比较
    PHP 设计模式
    mysql导入sql脚本
    linux 解压压缩大全
  • 原文地址:https://www.cnblogs.com/faberbeta/p/mysql-02.html
Copyright © 2011-2022 走看看