2-13-MySQL字段约束-索引-外键

高版本导出报错问题,是因为高版本对导出文件优化了权限设置,
show variables like '%secure%'; 查看权限是NULL就表明禁止导出
在配置文件my.cnf [mysqld]下加secure_file_priv=指定导出目录
 
 
本节所讲内容:
1.  字段修饰符
2.  清空表记录
3.  索引
4.  外键
5.     视图

一:字段修饰符 (约束)
1 :null和not null修饰符
 
咱们经过这个例子来看看
  1. mysql> create table worker(id int not null,name varchar(8) not null,pass varchar(20) not null);
  2. mysql> insert into worker values(1,'HA','123456');
mysql> insert into worker values(1,'LB',null);
ERROR 1048 (23000): Column 'pass' cannot be null   不能为null
mysql>insert into worker values(2,'HPC','');
注:NOT NULL 的字段是不能插入“NULL”的,只能插入“空值”。
 
咱们可能有这些疑问<null和not null区别>
一、字段类型是not null,为何能够插入空值
二、为何not null的效率比null高
三、判断字段不为空的时候,到底要  select * from table where column <> '' 仍是要用 select * from table where column is not null 呢。

空值” 和 “NULL”有什么不同?
1 、空值是不占用空间的
2 、mysql中的NULL实际上是占用空间的,下面是来自于MYSQL官方的解释
 
“NULL columns require additional space in therow to record whether their values are NULL. For MyISAM tables, each NULLcolumn takes one bit extra, rounded up to the nearest byte.”
#“ 空列须要行中的额外空间来记录其值是否为空。对于MyISAM表,每一个NULL列须要一个额外的位,四舍五入到最接近的字节。
好比:一个杯子,空值''表明杯子是真空的,NULL表明杯子中装满了空气,虽然杯子看起来都是空的,可是里面是有空气的。
 
对于问题2,为何not null的效率比null高?
NULL  其实并非空值,而是要占用空间,因此mysql在进行比较的时候,NULL 会参与字段比较,因此对效率有一部分影响。
并且索引时不会存储NULL值的,因此若是索引的字段能够为NULL,索引的效率会降低不少。
Mysql 难以优化引用可空列查询,它会使索引、索引统计和值更加复杂。可空列须要更多的存储空间,还须要mysql内部进行特殊处理。可空列被索引后,每条记录都须要一个额外的字节,还能致使MyISAM中固定大小的索引变成可变大小的索引--------这也是《高性能mysql第二版》介绍的解读:“可空列须要更多的存储空间”:须要一个额外字节做为判断是否为NULL的标志位“须要mysql内部进行特殊处理”
因此使用not null 比null效率高
 
对于问题3.   判断字段不为空的时候,到底要  select * from table where column <> '' 仍是要用 select * from table where column is not null咱们举例看看
  1. mysql> create table test(col1 varchar(10) not null, col2 varchar(10) null)ENGINE=MyISAM;
  2. mysql> insert into test values('',null);
  3. mysql> insert into test values('1','2');
  4. mysql> insert into test values('','1');


面我分别用这两条语句查询看看
 


为空表示不占空间,null占用空间

2 :default设定字段的默认值


为字段指定默认的值
  1. mysql> create table test2(name varchar(8) not null,dept varchar(25) default 'SOS');
  2. mysql> insert into test2 (name) values ('kko');


总结 :
若是字段没有设定default ,mysql依据这个字段是null仍是not null,若是为能够为null,则为null。若是不能够为null,报错。。
若是时间字段,默认为当前时间 ,插入0时,默认为当前时间。
若是是enum 类型,默认为第一个元素。

3 :auto_increment字段约束

自动增加
只能修饰 int字段。 代表mysql应该自动为该字段生成一个惟一没有用过的数(每次在最大ID值的基础上加1。特例:若是目前最大ID是34,而后删除34,新添加的会是35.)。对于主键,这是很是 有用的。 能够为每条记录建立一个唯一的标识符
  1. mysql> create table items ( id int not null auto_increment primary key , label varchar(20) not null);
  2. mysql>  insert into items (label) values ('aaba');
  3. mysql>  insert into items values (9,'aaba');

再插入一条id将为多少
  1. mysql>  insert into items (label) values ('abc');


Id 为10
 
  1. mysql>  insert into items values (9,'adl');
ERROR1062 (23000): Duplicate entry '9' for key 'PRIMARY'
 
insertinto items (label) values ('abcs');       IDmax =11 max=11
deletefrom items where label='abcs';       IDmax=10max=11
insertinto items (label) values ('abcsw');     Idmax=11max=12
 
主键约束惟一
二:清除表中的记录
清空表中全部记录
方法一:delete 不加where条件,清空全部表记录。可是delete不会清零auto_increment 值
 
  1. mysql> delete from items;


  1. mysql> insert into items (label) values ("aaaa");


方法二:删除表中全部记录,清auto_increment 值。

truncate
做用: 删除表的全部记录,并清零auto_increment 值。新插入的记录从1开始。
语法: truncate  table name;
  1. mysql> truncate table items;

mysql> insert into items values(null,'abv');php



  1. mysql> insert into items(label)values('hkuyb');
 
三:索引
 
索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里全部记录的引用指针。更通俗的说,数据库索引比如是一本书前面的目录,能加快数据库的查询速度。
点:为了加快搜索速度,减小查询时间。
缺点:
索引是以文件存储的。若是索引过多,占磁盘空间较大。并且他影响: insert ,update ,delete 执行时间。
2 索引中数据必须与数据表数据同步:若是索引过多,当表中数据更新的时候后,索引也要同步更新,这就下降了效率。

索引的类型
1 、普通索引
2 、惟一性索引
3 、主键索引(主索引)
4 、复合索引
普通索引
最基本的索引,不具有惟一性,就是加快查询速度
建立普通索引:
方法一:建立表时添加索引
createtable  表名(
        列定义
       index  索引名称(字段)
       index  索引名称(字段)
注:可使用key,也可使用index 。index索引名称 (字段)  ,索引名称,能够加也能够不加,不加使用字段名做为索引名。。
mysql>create table demo( id int(4), name varchar(20), pwd varchar(20), index(pwd) );
注意:index和 key 是相同的
mysql>create table demo1( id int(4), name varchar(20), pwd varchar(20), key(pwd) );
mysql>create table demo2( id int(4), name varchar(20), pwd varchar(20), key index_pwd(pwd) );  # 加上名称
方法二: 当表建立完成后,使用alter为表添加索引:
altertable  表名 addindex 索引名称 (字段1,字段2.....);

查看索引


注:若是Key是MUL, 就是通常性索引,该列的值能够重复, 该列是一个非惟一索引的前导列(第一列)或者是一个惟一性索引的组成部分可是能够含有空值NULL。就是表示是一个普通索引。
咱们先删除索引
mysql>alter table demo drop key pwd;  注意此处的pwd指的是索引的名称,而不是表中pwd的那个字段
再用alter添加
mysql>alter table demo add key(pwd);
 
惟一索引
与普通索引基本相同,但有一个区别:索引列的全部值都只能出现一次,即必须惟一,用来约束内容,字段值只能出现一次。应该加惟一索引。惟一性容许有NULL值<容许为空>。
建立惟一索引:
方法一:建立表时加惟一索引
createtable  表名(
        列定义:
       unique key  索引名 (字段);
)
注意:经常使用在值不能重复的字段上,好比说用户名,电话号码,身份证号。

  1. mysql> create table demo3(id int(4) auto_increment primary key, uName varchar(20), uPwd varchar(20), unique  index  (uName));

方法二:修改表时加惟一索引
altertable  表名 addunique 索引名 (字段);
  1. mysql> alter table demo3 drop key uName;
  2. mysql> alter table demo3 add unique(uName);

主键索引
查询数据库,按主键查询是最快的,每一个表只能有一个主键列,能够有多个普通索引列。主键列要求列的全部内容必须惟一,而索引列不要求内容必须惟一,不容许为空
建立主键索引
方法一:建立表建立主键索引
  1. mysql> create table demo4 (id int(4) not null auto_increment primary key,name varchar(4) not null );
  2. mysql> create table demo5( id int(4) not null auto_increment, name varchar(20) default null,primary key(id));

  1. mysql> show create table demo5;
  2. show index from demo5 \G


方法二:建立表后添加 < 不推荐> 若是生产的数据没法保证惟一,建立主键报错
再添加

先删除测试

删除遇到这种状况是auto_increment的缘由
  1. mysql> alter table demo5 change id id int(4) not null; 先取消自增加
  2. mysql> alter table demo5 drop primary key;  再删除主键
  3. mysql> alter table demo5 change id id int(4) not null primary key auto_increment;

总结:主键索引,惟一性索引区别:主键索引不能有NULL,惟一性索引能够有空值
复合索引
索引能够包含一个、两个或更多个列。两个或更多个列上的索引被称做复合索引
例: 建立一个表存放服务器容许或拒绝的IP和port,要记录中IP和port要惟一。

  1. mysql> create table firewall ( host varchar(15) not null ,port smallint(4) not null ,access enum('deny','allow') not null, primary key (host,port)); 联合主键
 

  1. mysql> insert into firewall values('10.96.52.46',22,'deny');
  2. mysql> insert into firewall values('10.96.52.46',21,'allow');
  3. mysql> insert into firewall values('10.96.52.46',21,'allow');
  4. ERROR 1062 (23000): Duplicate entry '10.96.52.46-21' for key 'PRIMARY'

插入同样就报错,惟一
总结:
建表的时候若是加各类索引,顺序以下:
create table  表名(字段定义,PRIMARYKEY (`bId`),UNIQUE KEY `bi` (`bImg`),KEY `bn` (`bName`),KEY `ba` (`author`))
 
 
全文索引(FULLTEXT INDEX)
全文索引(也称全文检索)是目前搜索引擎使用的一种关键技术。它可以利用「分词技术「等多种算法智能分析出文本文字中关键字词的频率及重要性,而后按照必定的算法规则智能地筛选出咱们想要的搜索结果
mysql  在数据量较大的状况下,高并发链接的状况下。
select  语句  where bName like '%网%'
使用% _ 通配符,不经过索引,直接全表扫描。
ABSUWU LIKE ‘%U_U’
 
数据库压力大。
mysql 的解决方案:全文索引:3.2开始支持全文索引。没法正确支持中文。
从MySQL 5.7.6开始 MySQL内置了ngram全文检索插件,用来支持中文分词
你的表当前默认的存储引擎:
mysql> show create table  表名;
 
全文索引只能用在 varchar text
建立全文索引:
方法一:建立表时建立
create table  表名(
        列定义,
       fulltext key  索引名 (字段);
方法二:修改表时添加
alter table  表名 add fulltext 索引名 (字段);
       ALTER TABLE`books` ADD FULLTEXT  [ 索引名](`author` )
强烈注意 :MySQL自带的全文索引只能用于数据库引擎为MyISAM的数据表,若是是其余数据引擎,则全文索引不会生效
通常交给第三方软件进行全文索引
http://sphinxsearch.com/
 
索引设计原则:
一、  索引并不是越多越好
二、  数据量不大不须要创建索引
三、  列中的值变化很少不须要创建索引 row id
四、  常常排序(order by 字段)和分组(group by 字段)的列须要创建索引
selecta.bTypeId,(select b.bTypeName from category b where a.bTypeId = b.bTypeId)bn,count(*) from books a group by bTypeId;
五、  惟一性约束对应使用惟一性索引
Table (id pri,use,nameindex,pass)


四:外键约束


什么是外键约束:
foreignkey 就是表与表之间的某种约定的关系,因为这种关系的存在,咱们可以让表与表之间的数据,更加的完整,关连性更强。
关于完整性,关连性咱们举个例子
有二张表,一张是用户表,一张是订单表:
1 》若是我删除了用户表里的用户,那么订单表里面与这个用户有关的数据,就成了无头数据了,不完整了。
2 》若是我在订单表里面,随便插入了一条数据,这个订单在用户表里面,没有与之对应的用户。这样数据也不完整了。
若是有外键的话,就方便多了,能够不让用户删除数据,或者删除用户的话,经过外键一样删除订单表里面的数据,这样也能让数据完整。

建立外键约束:
外键: 每次插入或更新时,都会检查数据的完整性。
方法一:经过createtable建立外键
语法:
create table  数据表名称(
...,
[CONSTRAINT [ 约束名称]] FOREIGN KEY [外键字段] 
    REFERENCES [外键表名](外键字段,外键字段2…..)
    [ON DELETE  C
AS CADE ]
    [ON UPDATE CASCADE  ]
)
关于参数的解释:
RESTRICT: 拒绝对父表的删除或更新操做。
CASCADE: 从父表删除或更新且自动删除或更新子表中匹配的行。ON DELETE CASCADE和ON UPDATE CASCADE均可用
注意:on update cascade是级联更新的意思 ,ondelete cascade是级联删除的意思,意思就是说当你更新或删除主键表,那外键表也会跟随一块儿更新或删除。
 
精简化后的语法:
语法:foreign key 当前表的字段  references  外部表名  (关联的字段)   ENGINE  =innodb
 
注:建立成功,必须知足如下4个条件:
1 、确保参照的表和字段存在。
2 、组成外键的字段被索引。
3 、必须使用 ENGINE 指定存储引擎为:innodb.
4 、外键字段和关联字段,数据类型必须一致。
例子:咱们建立一个数据库,包含用户信息表和订单表
  1. mysql> create database market;  
  2. mysql> use market;
  3. mysql> create table `user`(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;
# 建立时,若是表名是sql关键字,使用时,须要使用反引号``
  1. mysql> create table `order`(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 user(id) on delete cascade on update cascade) ENGINE=innodb;
注:
1:on delete cascade on update cascade 添加级联删除和更新:
2::确保参照的表user中id字段存在。 组成外键的字段u_id被索引。必须使用type指定存储引擎为:innodb。
外键字段和关联字段,数据类型必须一致。
插入测试数据
  1. mysql> insert into user(name,sex)values('HA',1),('LB',2),('HPC',1);
  2. mysql> insert into `order` (u_id,username,money)values(1,'HA',234),(2,'LB',146),(3,'HPC',256);


 

测试级联删除:
mysql>delete from user where id=1;  删除user表中id为1的数据

再查看order表


测试级联更新:

更新前数据状态

  1. mysql> update user set id=6 where id=2;

 
测试数据完整性
 

外键约束,order表受user表的约束
在order里面插入一条数据u_id为5用户,在user表里面根本没有,因此插入不进去
  1. mysql> insert into user values(5,'Find',1);
  2. mysql> insert into `order` (u_id,username,money)values(5,'Find',346); 这里u_id 只能是5

 
方法二:经过altertable 建立外键和级联更新,级联删除
语法:
alter table  数据表名称 add
[constraint [ 约束名称] ] foreign key (外键字段,..) references 数据表(参照字段,...)
[on update cascade|set null|no action]
[on delete cascade|set null|no action]
)
  1. mysql> create table order1(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)) ENGINE=innodb;
  2. mysql> alter table order1 add foreign key(u_id) references user(id) on delete cascade on update cascade, ENGINE =innodb;
  3. mysql> alter table order1 add constraint `bk`foreign key(u_id) references user(id) on delete cascade on update cascade,type=innodb;  指定外键名称

必定要记得带上innodb

  1. mysql> show create table order1;

 
删除外键:
语法
alter table  数据表名称 drop foreign key 约束(外键)名称
  1. mysql> alter table order1 drop foreign key order1_ibfk_1;
  2. mysql> show create table order1;


五:视图
什么是视图
视图就是一个存在于数据库中的虚拟表。
视图自己没有数据,只是经过执行相应的select语句完成得到相应的数据。
 
咱们在怎样的场景使用它,为何使用视图
若是某个查询结果出现的很是频繁,也就是,要常常拿这个查询结果来作子查询这种
1.    视图可以简化用户的操做
视图机制用户能够将注意力集中在所关心的数据上。若是这些数据不是直接来自基本表,则能够经过定义视图,使数据库看起来结构简单、清晰,而且能够简化用户的数据查询操做
2.    视图是用户能以不一样的角度看待一样的数据。
对于固定的一些基本表,咱们能够给不一样的用户创建不一样的视图,这样不一样的用户就能够看到本身须要的信息了。
3.    视图对重构数据库提供了必定程度的逻辑性。
好比原来的A表被分割成了B表和C表,咱们仍然能够在B表和C表的基础上构建一个视图A,而使用该数据表的程序能够不变。
4.    视图可以对机密数据提供安全保护
好比说,每门课的成绩都构成了一个基本表,可是对于每一个同窗只能够查看本身这门课的成绩,所以能够为每一个同窗创建一个视图,隐藏其余同窗的数据,只显示该同窗本身的
5.    适当的利用视图能够更加清晰的表达查询数据。
有时用现有的视图进行查询能够极大的减少查询语句的复杂程度。
建立视图
语法:createview视图名称(即虚拟的表名) as select 语句。
咱们在book数据库中操做
  1. mysql>  create view bc as select b.bName ,b.price ,c.bTypeName from books as b left join category as c  on b.bTypeId=c.bTypeId ;

能够按照普通表去访问。
另外视图表中的数据和原数据表中数据是同步的。
查看视图建立信息:

  1. mysql> show create view bc \G

 
查询视图中的数据


更新或修改视图
语法:
alter view 视图名称(即虚拟的表名) as select 语句。
update view 视图名称(即虚拟的表名)set

  1. mysql> alter view bc as select b.bName ,b.publishing ,c.bTypeId from books as b left join category as c  on b.bTypeId=c.bTypeId ;

 
  1. 更新
  2. mysql> update bc set bName='HA' where price=34;

删除视图
drop view  视图名。
  1. mysql> drop view bc;

学习mysql 先搞懂它的概念原理,慢慢作实验理解它真正的用法,而后结合实际为何要用这个sql写法。



 

16.png
相关文章
相关标签/搜索