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)
原文地址:https://www.cnblogs.com/SR-Program/p/13363286.html