MySQL之索引与约束条件

字段约束#

作用#

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

null和not null#

Copy
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#

作用#

  • 为指定字段设置默认值
  • 如果在插入数据的时候给默认值赋值则使用赋值的数据
Copy
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
Copy
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 | +----+------+

外键约束#

作用#

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

参数解释#

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

约束条件#

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

外键创建#

Copy
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)

数据测试#

Copy
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

优缺点#

优点#

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

缺点#

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

普通索引#

作用#

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

普通索引创建#

Copy
# 使用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

索引删除与添加#

Copy
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

唯一索引创建#

Copy
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'

唯一索引添加与删除#

Copy
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

主键索引#

作用#

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

主键索引创建#

Copy
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'

主键索引删除与添加#

Copy
# 不建议当有生产数据的时候在来创建主键索引 因为此时有数据 无法保证数据唯一 如果不唯一则无法创建主键索引 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;

复合索引#

作用#

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

复合索引创建#

Copy
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 全文检索插件,用来支持中文分词

创建#

Copy
# 全文索引字段必须是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 test10\G; *************************** 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)
posted @   SR丶  阅读(259)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示
CONTENTS