zoukankan      html  css  js  c++  java
  • mysql基础之视图、事务、索引、外键

    一、视图

      视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。对其中所引用的基础表来说,视图的作用类似于筛选。定义视图的筛选可以来自当前或其它数据库的一个或多个表,或者其它视图。通过视图进行查询没有任何限制,通过它们进行数据修改时的限制也很少。视图是存储在数据库中的查询的SQL 语句,它主要出于两种原因:安全原因, 视图可以隐藏一些数据;简化操作。

    查看当前用户是否拥有创建视图的权限:

    MariaDB [ren]> select user();
    +----------------+
    | user()         |
    +----------------+
    | root@localhost |
    +----------------+
    1 row in set (0.00 sec)
    
    MariaDB [ren]> select create_view_priv,select_priv from mysql.user where user='root' and host='localhost';
    +------------------+-------------+
    | create_view_priv | select_priv |
    +------------------+-------------+
    | Y                | Y           |
    +------------------+-------------+
    1 row in set (0.00 sec)

    1、创建视图

    格式:CREATE VIEW 视图名称 AS SQL语句

    MariaDB [ren]> create view v_class_stu as select s.name,c.name as class_name from students as s inner join classes as c on s.cls_id=c.id order by c.name;

    2、查看视图

    MariaDB [ren]> show tables;
    +---------------+
    | Tables_in_ren |
    +---------------+
    | areas         |
    | classes       |
    | create_index  |
    | students      |
    | t1            |
    | t2            |
    | test          |
    | v_class_stu   |
    +---------------+
    8 rows in set (0.00 sec)
    
    MariaDB [ren]> select * from v_class_stu;
    +--------------+--------------+
    | name         | class_name   |
    +--------------+--------------+
    | 黄蓉         | 运维一班     |
    | 钱小豪       | 运维一班     |
    | 彭于晏       | 运维一班     |
    | 周杰         | 运维一班     |
    | 小明         | 运维一班     |
    | 周杰伦儿     | 运维一班     |
    | 陈冠希       | 运维一班     |
    | 王祖贤       | 运维一班     |
    | 谢霆锋       | 运维一班     |
    | 刘亦菲       | 运维三班     |
    |              | 运维三班     |
    | 刘德华       | 运维二班     |
    | 小月月       | 运维二班     |
    | 和珅         | 运维二班     |
    | 程坤         | 运维二班     |
    | 凤姐         | 运维二班     |
    +--------------+--------------+
    16 rows in set (0.00 sec)

    3、修改视图

    MariaDB [ren]> alter view v_class_stu as select c.name as class_name ,s.name,s.age,s.high from students as s inner join classes as c on s.cls_id=c.id order by c.name,s.age asc;
    Query OK, 0 rows affected (0.00 sec)
    
    MariaDB [ren]> select * from v_class_stu;
    +--------------+--------------+------+--------+
    | class_name   | name         | age  | high   |
    +--------------+--------------+------+--------+
    | 运维一班     | 小明         |   18 | 180.00 |
    | 运维一班     | 彭于晏       |   28 | 185.00 |
    | 运维一班     | 周杰         |   33 | 178.00 |
    | 运维一班     | 周杰伦儿     |   34 |   NULL |
    | 运维一班     | 陈冠希       |   38 | 175.00 |
    | 运维一班     | 谢霆锋       |   38 | 175.00 |
    | 运维一班     | 王祖贤       |   52 | 170.00 |
    | 运维一班     | 钱小豪       |   56 | 178.00 |
    | 运维一班     | 黄蓉         |  108 | 160.00 |
    | 运维三班     |              |    0 |   NULL |
    | 运维三班     | 刘亦菲       |   29 | 162.00 |
    | 运维二班     | 小月月       |   19 | 180.00 |
    | 运维二班     | 程坤         |   44 | 181.00 |
    | 运维二班     | 凤姐         |   44 | 150.00 |
    | 运维二班     | 和珅         |   55 | 166.00 |
    | 运维二班     | 刘德华       |   58 | 175.00 |
    +--------------+--------------+------+--------+
    16 rows in set (0.00 sec)

    4、删除视图

    DROP VIEW 视图名称

    5、使用:视图的用途就是查询(虚拟表,无法使用视图对真实表进行创建、更新和删除操作)

    SELECT * FROM VIEW

    二、事务

      事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性。事务广泛的运用于订单系统、银行系统等多种场景。例如:当两张银行卡之间进行转账,甲方钱转出去了,突然光缆坏了,乙方还没收到钱,钱跑哪里去了,就为了防止这种情况,事务就出来了,事务可以防止这种事情发生。

      事务具有ACID特性:原子性(A,atomicity)、一致性(C,consistency)、隔离性(I,isolation)、持久性(D,durability)。

      原子性:整个事务中的所有操作要么全部执行成功,要么全部执行失败后回滚到最初状态,它是一个不可分割的工作单位。

      一致性:数据库总是从一个一致性的状态转换到另一个一致性的状态。

      隔离性:一个事物所做的修改在最终提交之前,对其他事物是不可见的。

      持久性:事务完成后,该事务内涉及的数据必须持久性的写入磁盘保证其持久性。当然,这是从事务的角度来考虑的的持久性,从操作系统故障或硬件故障来说,这是不一定的。

    事务命令
      要求:表的引擎类型必须是innodb类型才可以使用事务,这是mysql表的默认引擎
      查看表的创建语句,可以看到engine=innodb

    MariaDB [ren]> show create table studentsG;
    *************************** 1. row ***************************
           Table: students
    Create Table: CREATE TABLE `students` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `name` varchar(20) DEFAULT '',
      `age` tinyint(3) unsigned DEFAULT 0,
      `high` decimal(5,2) DEFAULT NULL,
      `gender` enum('','','中性','保密') DEFAULT '保密',
      `cls_id` int(10) unsigned DEFAULT 0,
      `is_delete` bit(1) DEFAULT b'0',
      PRIMARY KEY (`id`),
      KEY `fk` (`cls_id`),
      CONSTRAINT `fk` FOREIGN KEY (`cls_id`) REFERENCES `classes` (`id`) ON DELETE CASCADE
    ) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8
    修改数据的命令会触发事务,包含insert,update,delete

    开启事务(开启事务后执行修改命令,变更会维护到本地缓存中,而不维护到物理表中)
      begin或者start transaction;
    关闭事务(提交--将缓存中的数据变更维护到物理表中)或者(回滚事务--放弃缓存中变更的数据)
      commit或者rollback;

    三、索引

       索引是对数据库表中一个或多个列(例如,students表的姓名 (name) 列)的值进行排序的结构。如果想按特定职员的姓来查找他或她,则与在表中搜索所有的行相比,索引有助于更快地获取信息。

      例如这样一个查询:select * from test1 where id=10000。如果没有索引,必须遍历整个表,直到ID等于10000的这一行被找到为止;有了索引之后(必须是在ID这一列上建立的索引),即可在索引中查找。由于索引是经过某种算法优化过的,因而查找次数要少的多。可见,索引插叙的速度要比没有索引的速度要快很多。

      索引可以加快查询速度,但并不是越多越好,因为如果数据库有大量增删改的话,修改数据的同时对应的索引也要被修改,因此会大大降低数据库性能。

    MySQL中常见索引有:

    • 普通索引
    • 唯一索引
    • 主键索引
    • 组合索引

     1、普通索引(index)

    普通索引只有一个功能,就是加快查找速度

    (1)创建索引

    方法一:在创建表的时候创建索引
        create table create_index(
        id int primary key,
        name varchar(10) unique,
        age int,
        key (age)
        );
    方法二:在已经存在的表上创建索引
        create index 索引名称 on 表名(字段名称)
        例:
        create index age_index on create_index(age);

    (2)查看索引

    show index from 表名;
    MariaDB [ren]> create index age_index on students(age);
    Query OK, 0 rows affected (0.05 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    MariaDB [ren]> show index from studentsG;
    *************************** 1. row ***************************
            Table: students
       Non_unique: 0
         Key_name: PRIMARY
     Seq_in_index: 1
      Column_name: id
        Collation: A
      Cardinality: 15
         Sub_part: NULL
           Packed: NULL
             Null: 
       Index_type: BTREE
          Comment: 
    Index_comment: *************************** 2. row ***************************
            Table: students
       Non_unique: 1
         Key_name: age_index
     Seq_in_index: 1
      Column_name: age
        Collation: A
      Cardinality: 15
         Sub_part: NULL
           Packed: NULL
             Null: YES
       Index_type: BTREE
          Comment: 
    Index_comment: 
    3 rows in set (0.00 sec)
    
    ERROR: No query specified

    (3)删除索引

    drop index 索引名称 on 表名;

    (4)注意事项(对于创建索引时如果是BLOB和TEXT类型,必须指定length)

    create index index_name on tab1(extra(32));

    时间测试:

    show variable like 'profiling';
    set profiling=1;#打开sql语句执行时间
    show profiles;#查看sql执行时间

    2、唯一索引(unique)

      唯一性索引unique index和一般索引normal index最大的差异就是在索引列上增加了一层唯一约束。添加唯一性索引的数据列可以为空,但是只要存在数据值,就必须是唯一的。

    (1)创建表+唯一索引

    MariaDB [ren]> create table test2 (
        -> id int not null auto_increment primary key,
        -> name varchar(32) not null,
        -> extra text,
        -> unique index_name (name)
        -> );
    Query OK, 0 rows affected (0.00 sec)
    MariaDB [ren]> show index from test2G;
    *************************** 1. row ***************************
            Table: test2
       Non_unique: 0
         Key_name: PRIMARY
     Seq_in_index: 1
      Column_name: id
        Collation: A
      Cardinality: 0
         Sub_part: NULL
           Packed: NULL
             Null: 
       Index_type: BTREE
          Comment: 
    Index_comment: 
    *************************** 2. row ***************************
            Table: test2
       Non_unique: 0
         Key_name: index_name
     Seq_in_index: 1
      Column_name: name
        Collation: A
      Cardinality: 0
         Sub_part: NULL
           Packed: NULL
             Null: 
       Index_type: BTREE
          Comment: 
    Index_comment: 
    2 rows in set (0.00 sec)

    (2)创建索引

    create unique index 索引名 on 表名(列名)

    (3)删除索引

    drop unique index 索引名 on 表名

    3、主键索引

      在数据库关系图中为表定义一个主键将自动创建主键索引,主键索引是唯一索引的特殊类型。主键索引要求主键中的每个值是唯一的。当在查询中使用主键索引时,它还允许快速访问数据。数据不能为空

    (1)创建表+主键索引

    MariaDB [ren]> create table test3 (
        -> id int not null auto_increment,
        -> name varchar(32) not null,
        -> extra text,
        -> primary key(id),
        -> index index_name (name)
        -> );
    Query OK, 0 rows affected (0.00 sec)
    
    MariaDB [ren]> show index from test3G;
    *************************** 1. row ***************************
            Table: test3
       Non_unique: 0
         Key_name: PRIMARY
     Seq_in_index: 1
      Column_name: id
        Collation: A
      Cardinality: 0
         Sub_part: NULL
           Packed: NULL
             Null: 
       Index_type: BTREE
          Comment: 
    Index_comment: 
    *************************** 2. row ***************************
            Table: test3
       Non_unique: 1
         Key_name: index_name
     Seq_in_index: 1
      Column_name: name
        Collation: A
      Cardinality: 0
         Sub_part: NULL
           Packed: NULL
             Null: 
       Index_type: BTREE
          Comment: 
    Index_comment: 
    2 rows in set (0.00 sec)

    (2)创建主键

    alter table 表名 add primary key(列名);

    (3)删除主键

    alter table 表名 drop primary key;
    alter table 表名  modify  列名 int, drop primary key;

    4、组合索引

    组合索引,就是组合查询的意思,将两列或者多列组合成一个索引进行查询

    其应用场景为:频繁的同时使用n列来进行查询,如:where name = '谢霆锋' and age=38;

    创建表:
    MariaDB [ren]> create table test4 ( -> id int not null auto_increment primary key, -> name varchar(32) not null, -> phone int(11) unsigned, -> extra text -> ); Query OK, 0 rows affected (0.03 sec) 创建组合索引: MariaDB [ren]> create index index_na_ph on test4(name,phone); Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 MariaDB [ren]> show index from test4G; *************************** 1. row *************************** Table: test4 Non_unique: 0 Key_name: PRIMARY Seq_in_index: 1 Column_name: id Collation: A Cardinality: 0 Sub_part: NULL Packed: NULL Null: Index_type: BTREE Comment: Index_comment: *************************** 2. row *************************** Table: test4 Non_unique: 1 Key_name: index_na_ph Seq_in_index: 1 Column_name: name Collation: A Cardinality: 0 Sub_part: NULL Packed: NULL Null: Index_type: BTREE Comment: Index_comment: *************************** 3. row *************************** Table: test4 Non_unique: 1 Key_name: index_na_ph Seq_in_index: 2 Column_name: phone Collation: A Cardinality: 0 Sub_part: NULL Packed: NULL Null: YES Index_type: BTREE Comment: Index_comment: 3 rows in set (0.00 sec)

    5、注意事项

      数据库表中添加索引后能够让查询数据库速度飞快,但前提必须是正确的使用索引来查询,如果以错误的方式使用,则即使建立索引也会不奏效。

    下面这些情况不会使用到索引:

    1like '%xx'
        select * from tb1 where name like '%cn';
    
    2、使用函数
        select * from tb1 where reverse(name) = '张岩林';
    
    3or
        select * from tb1 where nid = 1 or email='zhangyanlin@live.com';
        特别的:当or条件中有未建立索引的列才失效,以下会走索引
                select * from tb1 where nid = 1 or name = 'zhangyanlin';
                select * from tb1 where nid = 1 or email = 'zhangyanlin@live.com' and name = 'aylin'
    
    4、类型不一致
        如果列是字符串类型,传入条件是必须用引号引起来,不然...
        select * from tb1 where name = 999;
    
    5!=
        select * from tb1 where name != 'aylin'
        特别的:如果是主键,则还是会走索引
            select * from tb1 where nid != 123
    
    6>
        select * from tb1 where name > 'alex'
        特别的:如果是主键或索引是整数类型,则还是会走索引
            select * from tb1 where nid > 123
            select * from tb1 where num > 123
    
    7order by
        select email from tb1 order by name desc;
        当根据索引排序时候,选择的映射如果不是索引,则不走索引
        特别的:如果对主键排序,则还是走索引:
            select * from tb1 order by nid desc;
     
    8、 组合索引最左前缀
        如果组合索引为:(name,email)
        name and email       -- 使用索引
        name                 -- 使用索引
        email                -- 不使用索引

    其它注意事项:

    1、避免使用select *
    2、count(1)或count(列) 代替 count(*)
    3、创建表时尽量时 char 代替 varchar
    4、表的字段顺序固定长度的字段优先
    5、组合索引代替多个单列索引(经常使用多个条件查询时)
    6、尽量使用短索引
    7、使用连接(JOIN)来代替子查询(Sub-Queries)
    8、连表时注意条件类型需一致
    9、索引散列值(重复少)不适合建索引,例:性别不适合

    四、外键(foreign key)

      如果一个实体的某个字段指向另一个实体的主键,就称为外键。被指向的实体,称之为主实体(主表),也叫父实体(父表)。负责指向的实体,称之为从实体(从表),也叫子实体(子表)
      添加外键(创建外键时从表和主表相关联的字段要一一对应,否则的话无法创建成功)
      (同时,从表的字段类型需要和主表的主键字段的类型保持一致)

      对关系字段进行约束,当为从表中的关系字段填写值时,会到关联的主表中查询此值是否存在,如果存在则填写成功,如果不存在则填写失败并报错

    (1)添加外键

    MariaDB [testdb]> alter table students add constraint 外键名字 foreign key (字段) references 表名(字段) on delete cascade;
    constraint(/kən'strent/,约束,约束条件,强制)references(/'rɛfərənsɪz/,参考文献,把...引作参考)cascade(/'sked/,级联,串联,瀑布)
    note:
        如果加上on delete cascade那么在删除父表中的数据时,也会删除子表中的数据
        如果不加on delete cascade那么如果子表不为空,不能删除父表数据

    (2)查看外键

    MariaDB [ren]> show create table studentsG;
    *************************** 1. row ***************************
           Table: students
    Create Table: CREATE TABLE `students` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `name` varchar(20) DEFAULT '',
      `age` tinyint(3) unsigned DEFAULT 0,
      `high` decimal(5,2) DEFAULT NULL,
      `gender` enum('','','中性','保密') DEFAULT '保密',
      `cls_id` int(10) unsigned DEFAULT 0,
      `is_delete` bit(1) DEFAULT b'0',
      PRIMARY KEY (`id`),
      KEY `fk` (`cls_id`),
      KEY `age_index` (`age`),
      CONSTRAINT `fk` FOREIGN KEY (`cls_id`) REFERENCES `classes` (`id`) ON DELETE CASCADE
    ) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8
    1 row in set (0.00 sec)

    (3)删除外键

    alter table students drop foreign key 外键名字
  • 相关阅读:
    个人总结13
    构建之法阅读笔记一
    个人总结12
    个人总结11
    地铁时光机第一阶段冲刺十
    地铁时光机第一阶段冲刺九
    地铁时光机第一阶段冲刺八
    单词 统计续
    地铁时光机第一阶段冲刺七
    个人总结10
  • 原文地址:https://www.cnblogs.com/renyz/p/11442292.html
Copyright © 2011-2022 走看看