zoukankan      html  css  js  c++  java
  • MySQL之索引与约束条件

    字段约束

    作用

    • 顾名思义就是给字段加以限制
    • 其保证数据库的完整性与一致性
    • 通过约束条件防止数据库产生一些不必要的数据 保证数据库的正确性 相容性 安全性

    null和not null

    mysql> create database test1;
    
    mysql> use test1;
    
    mysql> create table test1(id int not null,name varchar(254) not null);      # 设置约束条件不能为空
    
    mysql> insert into test1 values (1,'SR');
    
    mysql> insert into test1 values (1,'');      # 如果以空字符可以正常插入数据
    
    mysql> insert into test1 values (1,null);            # 为null则报错
    ERROR 1048 (23000): Column 'name' cannot be null
    
    mysql> select * from test1 where name is not null;      # 当查询条件为not null的时候即使数据为空也可以被查询出来
    +----+------+
    | id | name |
    +----+------+
    |  1 | SR   |
    |  1 |      |
    +----+------+
    
    mysql> select * from test1 where name != '';      # 当查询条件不为空的时候 数据为空不能被查询出来
    +----+------+
    | id | name |
    +----+------+
    |  1 | SR   |
    +----+------+
    
    PS:当约束条件为not null的时候可以设置为"" 但是不能插入null
    

    上述现象扩展

    ""和null的区别

    • null在数据库中是占用空间的 为空值不占用空间
    • 对于MyISAM表中null需要一个额外的为 四舍五入到最接近的字节

    null和not null效率

    • not null效率高于null
    • 对于null字段来说其本身占用空间在数据查询的时候会参与字段比较
    • null字段不会被索引 如果参与索引的时候效率会下降很多
    内核优化
    • MySQL 难以优化引用可空列查询,它会使索引、索引统计和值更加复杂。
    • 可空列需要更多的存储空间,还需要一个额外字节作为判断是否为 NULL 的标志位 “需要 MySQL内部进行特殊处理”
    • 可空列被索引后,每条记录都需要一个额外的字节,还能导致 MyISAM 中固定大小的索引变成可变大小的索引

    default

    作用

    • 为指定字段设置默认值
    • 如果在插入数据的时候给默认值赋值则使用赋值的数据
    mysql> create table test2(id int not null,name varchar(255) not null default 'SR');
    
    mysql> insert into test2(id)values(1);      # 不给name字段插入数据
    
    
    mysql> insert into test2(id,name)values(2,'MZ');      # 手动给name字段添加数据
    
    mysql> select * from test2;
    +----+------+
    | id | name |
    +----+------+
    |  1 | SR   |      # 使用默认值
    |  2 | MZ   |      # 使用指定的值
    +----+------+
    
    PS:
    1:如果时间字段,默认为当前时间 ,插入 0 时,默认为当前时间。
    2:如果是 enum 类型,默认为第一个元素
    

    auto_increment

    作用

    • 自动增长
    • 其作用数据类型只能为整形
    • 每次插入一条数据的时候都会在该字段的最大值+1
    
    mysql> create table test3 (id int not null auto_increment primary key ,test int);
    
    mysql> desc test3;
    +-------+---------+------+-----+---------+----------------+
    | Field | Type    | Null | Key | Default | Extra          |
    +-------+---------+------+-----+---------+----------------+
    | id    | int(11) | NO   | PRI | NULL    | auto_increment |
    | test  | int(11) | YES  |     | NULL    |                |
    +-------+---------+------+-----+---------+----------------+
    
    mysql> insert into test3(test) values(1);
    
    mysql> insert into test3(test) values(2);
    
    # id字段自动从1开始插入数据并且自动递增
    mysql> select * from test3;
    +----+------+
    | id | test |
    +----+------+
    |  1 |    1 |
    |  2 |    2 |
    +----+------+
    
    mysql> insert into test3(id,test) values(4,9);
    
    mysql> insert into test3(id,test) values(9,9);	# 跳级插入
    
    mysql> insert into test3(test) values(9);		# 从最大值+1
    
    mysql> select * from test3;
    +----+------+
    | id | test |
    +----+------+
    |  1 |    1 |
    |  2 |    2 |
    |  3 |    9 |
    |  4 |    9 |
    |  9 |    9 |
    | 10 |    9 |
    +----+------+
    

    外键约束

    作用

    '''
    foreign key 就是表与表之间的某种约定的关系,由于这种关系的存在,我们能够让表与表之间的数据,更加的完整, 关联性更强。
    关于完整性, 关联性我们举个例子
    例:
    有二张表,一张是用户表,一张是订单表
    1. 如果我删除了用户表里的用户,那么订单表里面与这个用户有关的数据,就成了无头数据了,不完整了。
    2. 如果我在订单表里面,随便插入了一条数据,这个订单在用户表里面,没有与之对应的用户。这样数据也不完整了。
    3. 如果有外键的话,就方便多了,可以不让用户删除数据,或者删除用户的话,通过外键同样删除订单表里面的数据,这样也能让数据完整。
    '''
    

    参数解释

    • foreign key 当前表的字段
    • references 外部表名
    • on update cascade 是级联更新的意思
    • on update cascade 是级联更新的意思

    约束条件

    • 确保参照的表和字段存在
    • 组成外键的字段被索引。
    • 必须使用 ENGINE 指定存储引擎为: innodb。
    • 外键字段和关联字段,数据类型必须一致。

    外键创建

    mysql> create table orderinfo(o_id int(11) auto_increment, u_id int(11) default '0', username varchar(50), money int(11), primary key(o_id), index(u_id), foreign key order_f_key(u_id) references userinfo(id) on delete cascade on update cascade) ENGINE=innodb;
    
    mysql> create table userinfo(id int(11) not null auto_increment, name varchar(50) not null default '', sex int(1) not null default '0', primary key(id))ENGINE=innodb;
    
    mysql> insert into userinfo(name,sex)values('HA',1),('LB',2),('HPC',1);
    Query OK, 3 rows affected (0.00 sec)
    
    mysql> insert into orderinfo (u_id,username,money)values(1,'HA',234),(2,'LB',146),(3,'HPC',256);
    Query OK, 3 rows affected (0.00 sec)
    

    数据测试

    mysql> select * from orderinfo;
    +------+------+----------+-------+
    | o_id | u_id | username | money |
    +------+------+----------+-------+
    |    1 |    1 | HA       |   234 |
    |    2 |    2 | LB       |   146 |
    |    3 |    3 | HPC      |   256 |
    +------+------+----------+-------+
    
    
    mysql> select id,name,sex,money,o_id from userinfo,orderinfo where id=u_id;
    +----+------+-----+-------+------+
    | id | name | sex | money | o_id |
    +----+------+-----+-------+------+
    |  1 | HA   |   1 |   234 |    1 |
    |  2 | LB   |   2 |   146 |    2 |
    |  3 | HPC  |   1 |   256 |    3 |
    +----+------+-----+-------+------+
    
    # 级联删除
    mysql> delete from userinfo where id=1;      #删除数据
    Query OK, 1 row affected (0.00 sec)
    
    mysql> select * from orderinfo;      # 查看级联表
    
    +------+------+----------+-------+
    | o_id | u_id | username | money |
    +------+------+----------+-------+
    |    2 |    2 | LB       |   146 |
    |    3 |    3 | HPC      |   256 |
    +------+------+----------+-------+
    
    # 级联更新
    mysql> update userinfo set id=6 where id=2;
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> select * from userinfo;
    +----+------+-----+
    | id | name | sex |
    +----+------+-----+
    |  3 | HPC  |   1 |
    |  6 | LB   |   2 |
    +----+------+-----+
    
    
    # 测试数据完整性
    insert into orderinfo (u_id,username,money)values(5,'Find',346);      # 报错此时无u_id=5的用户
    ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test1`.`orderinfo`, CONSTRAINT `orderinfo_ibfk_1` FOREIGN KEY (`u_id`) REFERENCES `userinfo` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
    
    mysql> insert into userinfo values(5,'Find',1);
    Query OK, 1 row affected (0.04 sec)
    
    mysql> insert into orderinfo (u_id,username,money)values(5,'Find',346);
    Query OK, 1 row affected (0.00 sec)
    
    mysql> select * from orderinfo;
    +------+------+----------+-------+
    | o_id | u_id | username | money |
    +------+------+----------+-------+
    |    2 |    6 | LB       |   146 |
    |    3 |    3 | HPC      |   256 |
    |    7 |    5 | Find     |   346 |
    +------+------+----------+-------+
    

    索引

    作用

    • 索引是一种特殊的文件( InnoDB 数据表上的索引是表空间的一个组成部分)
    • 它们包含着对数据表里所有记录的引用指针

    [索引详解]https://www.cnblogs.com/SR-Program/p/12008958.html

    优缺点

    优点

    • 加快查询速度 增加查询效率

    缺点

    • 索引需要单独的文件来存放索引 如果索引量比较大占用存储空间
    • 索引与数据库中的数据相互对应 如果数据量较大 当有数据增加的时候 索引需要同步更新 降低效率

    普通索引

    作用

    • 最基础的索引 只是用来加快查询速度
    • 其不具备唯一性

    普通索引创建

    # 使用index或者key指定索引字段
    # 索引名称可以添加也可以省略 如果省略默认以字段名字作为索引名称
    mysql> create table test4(id int,name varchar(254),index(id));
    
    mysql> desc test4;
    +-------+--------------+------+-----+---------+-------+
    | Field | Type         | Null | Key | Default | Extra |
    +-------+--------------+------+-----+---------+-------+
    | id    | int(11)      | YES  | MUL | NULL    |       |
    | name  | varchar(254) | YES  |     | NULL    |       |
    +-------+--------------+------+-----+---------+-------+
    
    mysql> show create table test4;
    +-------+--------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table                                                                                                                                     |
    +-------+--------------------------------------------------------------------------------------------------------------------------------------------------+
    | test4 | CREATE TABLE `test4` (
      `id` int(11) DEFAULT NULL,
      `name` varchar(254) DEFAULT NULL,
      KEY `id` (`id`)     # 索引名称 
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
    +-------+--------------------------------------------------------------------------------------------------------------------------------------------------+
    
    mysql> create table test4(id int,name varchar(254),index name_index(name));      # 指定索引名称index_name
    
    
    mysql> show create table test5;
    +-------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table                                                                                                                                               |
    +-------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | test5 | CREATE TABLE `test5` (
      `id` int(11) DEFAULT NULL,
      `name` varchar(254) DEFAULT NULL,
      KEY `name_index` (`name`)      # 指定索引名称
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
    +-------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
    
    
    • key为MUL表示普通索引 该列值可以重复
    • 该列是一个非唯一索引的前导列(第一列)或者是一个唯一性索引的组成部分但是可以含有空值 NULL

    索引删除与添加

    mysql> alter table test5 drop key name_index;
    mysql> desc test5;
    +-------+--------------+------+-----+---------+-------+
    | Field | Type         | Null | Key | Default | Extra |
    +-------+--------------+------+-----+---------+-------+
    | id    | int(11)      | YES  |     | NULL    |       |
    | name  | varchar(254) | YES  |     | NULL    |       |      #  无索引字段
    +-------+--------------+------+-----+---------+-------+
    mysql> alter table test5 add key name_index(name);
    
    mysql> desc test5;
    +-------+--------------+------+-----+---------+-------+
    | Field | Type         | Null | Key | Default | Extra |
    +-------+--------------+------+-----+---------+-------+
    | id    | int(11)      | YES  |     | NULL    |       |
    | name  | varchar(254) | YES  | MUL | NULL    |       |      # 添加成功
    +-------+--------------+------+-----+---------+-------+
    

    唯一索引

    作用

    • 其与普通索引类似
    • 但是在索引列所在的字段中插入的数据值必须唯一
    • 唯一性索引允许有空值允许为null

    唯一索引创建

    mysql> create table test6(id int auto_increment primary key,name varchar(254), unique index(name));
    
    mysql> desc test6;
    +-------+--------------+------+-----+---------+----------------+
    | Field | Type         | Null | Key | Default | Extra          |
    +-------+--------------+------+-----+---------+----------------+
    | id    | int(11)      | NO   | PRI | NULL    | auto_increment |
    | name  | varchar(254) | YES  | UNI | NULL    |                |
    +-------+--------------+------+-----+---------+----------------+
    
    mysql> insert into test6 values(1,'SR');
    
    mysql> insert into test6 values(2,null);
    
    mysql> insert into test6 values(3,'SR');      # 报错含有重复值
    ERROR 1062 (23000): Duplicate entry 'SR' for key 'name'      
    

    唯一索引添加与删除

    mysql> alter table test6 drop  index name;
    Query OK, 0 rows affected (0.05 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    mysql> desc test6;
    +-------+--------------+------+-----+---------+----------------+
    | Field | Type         | Null | Key | Default | Extra          |
    +-------+--------------+------+-----+---------+----------------+
    | id    | int(11)      | NO   | PRI | NULL    | auto_increment |
    | name  | varchar(254) | YES  |     | NULL    |                |
    +-------+--------------+------+-----+---------+----------------+
    2 rows in set (0.00 sec)
    
    mysql> alter table test6 add unique index(name);
    Query OK, 0 rows affected (0.06 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    

    主键索引

    作用

    • 使用主键索引查询速度最快
    • 主键索引所在的字段数据必须唯一
    • 主键索引不许为空

    主键索引创建

    mysql> create table test7(id int auto_increment not null, name varchar(254),primary key (id));
    Query OK, 0 rows affected (0.06 sec)
    
    mysql> desc test7;
    +-------+--------------+------+-----+---------+----------------+
    | Field | Type         | Null | Key | Default | Extra          |
    +-------+--------------+------+-----+---------+----------------+
    | id    | int(11)      | NO   | PRI | NULL    | auto_increment |
    | name  | varchar(254) | YES  |     | NULL    |                |
    +-------+--------------+------+-----+---------+----------------+
    2 rows in set (0.00 sec)
    
    mysql> insert into test7 values('','SR');      # 数据不能为空
    ERROR 1366 (HY000): Incorrect integer value: '' for column 'id' at row 1
    mysql>
    mysql> insert into test7 values(1,'SR');
    Query OK, 1 row affected (0.00 sec)
    
    mysql> insert into test7 values(1,'SR');
    ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
    

    主键索引删除与添加

    # 不建议当有生产数据的时候在来创建主键索引 因为此时有数据 无法保证数据唯一 如果不唯一则无法创建主键索引
    alter table test7 drop primary key ;      # 此时报错的原因因为自增长
    ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
    
    mysql> alter table test7 change id id int not null;      # 去掉auto_increment
    
    mysql> alter table test7 drop primary key ;      # 删除主键
    
    mysql> alter table test7 change id id int not null primary key auto_increment;
    

    复合索引

    作用

    • 索引可以包含一个、两个或更多个列
    • 两个或更多个列上的索引被称作复合索引

    复合索引创建

    mysql> create table test8( host varchar(15) not null ,port smallint(4) not null ,access enum('deny','allow') not null, primary key (host,port));
    
    mysql> desc test8;
    +--------+----------------------+------+-----+---------+-------+
    | Field  | Type                 | Null | Key | Default | Extra |
    +--------+----------------------+------+-----+---------+-------+
    | host   | varchar(15)          | NO   | PRI | NULL    |       |
    | port   | smallint(4)          | NO   | PRI | NULL    |       |
    | access | enum('deny','allow') | NO   |     | NULL    |       |
    +--------+----------------------+------+-----+---------+-------+
    
    mysql> insert into test8 values('10.96.52.46',22,'deny');
    Query OK, 1 row affected (0.00 sec)
    
    mysql> insert into test8 values('10.96.52.46',21,'allow');
    Query OK, 1 row affected (0.05 sec)
    
    mysql> insert into test8 values('10.96.52.46',21,'allow');      # 数据重复
    ERROR 1062 (23000): Duplicate entry '10.96.52.46-21' for key 'PRIMARY'
    
    

    全文索引

    作用

    • 全文索引( 也称全文检索) 是目前搜索引擎使用的一种关键技术。它能够利用「分词技术「等多种算法智能分析出文本文字中关键字词的频率及重要性,然后按照一定的算法规则智能地筛选出我们索结果。
    • MySQL 在数据量较大的情况下,高并发连接的情况下。select 语句 where bName like '%网%'使用% _ 通配符,不通过索引,直接全表扫描。ABSUWU LIKE ‘%U_U’数据库压力大。
    • MySQL 的解决方案:全文索引: 3.2 开始支持全文索引。 无法正确支持中文。从 MySQL 5.7.6 开始 MySQL 内置了 ngram 全文检索插件,用来支持中文分词

    创建

    # 全文索引字段必须是varchar text
    # 存储引擎必须是myisam
    # mysql自带的全文搜索引擎只能作用于myisam存储引擎
    
    mysql> create table test10 (id int,article text, fulltext key(article)) engine=myisam;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> show index from test10G;
    *************************** 1. row ***************************
            Table: test10
       Non_unique: 1
         Key_name: article
     Seq_in_index: 1
      Column_name: article
        Collation: NULL
      Cardinality: NULL
         Sub_part: NULL
           Packed: NULL
             Null: YES
       Index_type: FULLTEXT      # 全文引擎
          Comment:
    Index_comment:
    1 row in set (0.00 sec)
    
  • 相关阅读:
    How to convert VirtualBox vdi to KVM qcow2
    (OK)(OK) adb -s emulator-5554 shell
    (OK)(OK) using adb with a NAT'ed VM
    (OK) How to access a NAT guest from host with VirtualBox
    (OK) Creating manually one VMs from an existing VDI file in CLI (VBoxManage) in Fedora 23
    (OK)(OK) Creating VMs from an existing VDI file in CLI (VBoxManage) in Fedora 23
    (OK) Creating_VMs_from_an_existing_VDI_file.txt
    (OK) Creating VMs from an existing VDI file —— in OS X
    (OK) install_IBM_SERVER.txt
    (OK) install chrome & busybox in android-x86_64 —— uninstall chrome
  • 原文地址:https://www.cnblogs.com/SR-Program/p/13363286.html
Copyright © 2011-2022 走看看