关于我的数据库——MySQL——第二篇

(叠甲:如有侵权请联系,内容都是自己学习的总结,一定不全面,仅当互相交流(轻点骂)我也只是站在巨人肩膀上的一个小卡拉米,已老实,求放过)。

表的操作

创建表

语法:

sql 复制代码
create table table_name(
    field1 datatype,
    field2 datatype,
    field3 datatype
)character set 字符集 collate 校验规则 engin 存储引擎;

说:

1)field 表示列名;

2)datatype 表示列的类型;

3)character set 字符集,如果没有指定字符集,则以所在数据库的字符集为准;

4)collate 校验规则,如果没有指定校验规则,则以所在数据库的校验规则为准;

例:

sql 复制代码
create table user(
    id int,
    name varchar(20) comment'用户名',
    password char(32) comment'密码',
    birthday date comment'生日'
)character set utf8 engine MyISAM;

注:不建议直接粘贴到自己的sql中,建议手敲。

说明:

不同的存储引擎,创建表的文件不一样,MyISAM,在数据目中有三个不同的文件,分别是:

1).frm:表结构

2).MYD:表数据

3).MYI:表索引

查看表结构
sql 复制代码
desc table_name;

示例:

修改表

在项目实际开发中,经常修改某个表的结构,比如字段名字,字段大小,字段类型,表的字符集类型,表的储存引擎等等,我们还有需求,添加字段,删除字段等等,这时候就需要修改表。

sql 复制代码
ALTER TABLE tablename ADD (column datatype [DEFAULT expr][,column
datatype]...);

ALTER TABLE tablename MODIfy (column datatype [DEFAULT expr][,column
datatype]...);

ALTER TABLE tablename DROP (column);

例:

在users表添加两条记录
sql 复制代码
insert into users values(1,'a','123','2024-10-23'),(2,'b','1234','2024-10-23');
在users表添加一个字段,用于保存图片路径
sql 复制代码
alter table users add assets varchar(100)comment'图片路径'after birthday;
修改name ,将其长度改为60
sql 复制代码
alter table users modify name varchar(60);
删除password列

注:删除字段一定要小心,删除字段及其对应的列数据都没有。

sql 复制代码
alter table users drop password;
修改表名为employee
sql 复制代码
alter table users rename to employee;

注:to可以省略

将name字段改为xingming
sql 复制代码
alter table employee change name xingming varchar(60);--新字段需要完整定义
删除表

语法格式:

sql 复制代码
DROP [TEMPORARY] TABLE [IF EXISTS] tbl_name [, tbl_name] ...

示例:

sql 复制代码
drop table employee;

数据类型

数据类型的分类:数值类型、二进制,文本类型、时间日期、String类型;

数值类型
tinyint类型(带符号的范围-128~127,无符号范围0~255,默认有符号的)

数值越界测试:

sql 复制代码
mysql> create table tt1(num tinyint);
Query OK, 0 rows affected (0.02 sec)
mysql> insert into tt1 values(1);
Query OK, 1 row affected (0.00 sec)
mysql> insert into tt1 values(128); -- 越界插入,报错
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> select * from tt1;

说明:

1)在MySQL中,整数可以指定是有符号和无符号的,默认是有符号的;

2)可以通过unsigned来说明某个字段是无符号的;

无符号例子

sql 复制代码
mysql> create table tt2(num tinyint unsigned);
mysql> insert into tt2 values(-1); -- 无符号,范围是: 0 - 255
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> insert into tt2 values(255);
Query OK, 1 row affected (0.02 sec)

注:尽量不使用unsigned,对于int类型可能存放不下的数据,int unsigned同样可能存放不下。

bit类型

基本语法

sql 复制代码
bit[(M)]:位字段类型,M表示每个值的位数,范围从1~64,如果M被忽略,默认为1。
sql 复制代码
mysql> create table tt3 ( id int, a bit(8));
Query OK, 0 rows affected (0.01 sec)
mysql> insert into tt3 values(10, 10);
Query OK, 1 row affected (0.01 sec)

为什么a的数据10没有出现?

bit字段在显示时,是按照ASSCII对应的值显示。

sql 复制代码
mysql> insert into tt4 values(65, 65);

当需要只存放0或1的值时,这样就可以定义bit(1),这样可以节省空间。

sql 复制代码
alter table tt3 add gender bit(1) after a;

当插入2时,已经越界了

小数类型
float

语法:

sql 复制代码
float[(m,d)][unsigned]:M指定显示长度,d指定小数位数,占用空间4个字节

例:float(4,2)表示的范围是-99.99~99.99,MySQL在保存值时会进行四舍五入。

sql 复制代码
mysql> create table tt4(id int, salary float(4,2));
Query OK, 0 rows affected (0.01 sec)
mysql> insert into tt4 values(100, -99.99);
Query OK, 1 row affected (0.00 sec)
mysql> insert into tt4 values(101, -99.991); #多的这一点被拿掉了
Query OK, 1 row affected (0.00 sec)

例:如果定义的是float(4,2)unsigned这时,因为把它指定为无符号的数,范围是0~99.99

sql 复制代码
create table tt5(id int, salary float(4,2) unsigned);
decimal

语法:

sql 复制代码
decimal(m,d) [unsigned]:定点数m指定长度,d表示小数点的位数

1)decimal(5,2)表示范围是-999.99~999.99;

2)decimal(5,2)表示的范围是0~999.99;

3)decimal和float很相似,但是精度不一样;

sql 复制代码
create table tt6 ( id int, salary float(10,8), salary2
decimal(10,8));
insert into tt6 values(100,23.12345678, 23.12345678);

decimal的精度更准确,float表示的精度大约是7位,decimal整数最大位数m为65,支持小数最大位数d是30,如果d被省略,默认为0,如果m被省略,默认是10.如果希望小数的精度高,推荐使用decimal。

字符类型
char

语法:

sql 复制代码
char(L):固定长度字符串,L是可以储存的长度,单位为字符,最大长度可以为255

例:

sql 复制代码
create table tt7(
    -> id int,
    -> name char(2));
Query OK, 0 rows affected (0.02 sec)

mysql> insert into tt7 values(100,'ab');
Query OK, 1 row affected (0.01 sec)

mysql> insert into tt7 values(101,'四川');
Query OK, 1 row affected (0.01 sec)

mysql> select *from tt7;
+------+--------+
| id   | name   |
+------+--------+
|  100 | ab     |
|  101 | 四川   |
+------+--------+
2 rows in set (0.00 sec)

char(2)表示可以存放两个字符,可以是字母或是汉字,但是不能超过2个,最多只能是255

sql 复制代码
mysql> create table tt8( id int, name char(256));
ERROR 1074 (42000): Column length too big for column 'name' (max = 255); use BLOB or TEXT instead
varvhar

语法:

sql 复制代码
varchar(L):可变长度字符串,L表示字符长度,最大长度是65535个字节

例:

sql 复制代码
mysql> create table tt8(
    -> id int,
    -> name varchar(6));
Query OK, 0 rows affected (0.04 sec)

mysql> insert into tt8 values(100,'hello');
Query OK, 1 row affected (0.01 sec)

mysql> insert into tt8 values(101,'我爱你,中国');
Query OK, 1 row affected (0.00 sec)

关于carchar(len),len到底多大,这个len值,和表的编码密切相关:

1)varchar长度可以指定0~65535之间的值,但是有1~3个字节用于记录数据大小,所以说有效字节是65532.

2)当我们的编码是utf8是,carchar(n)的参数n最大值是65532/3=21844(因此在utf8中,一个字符占用了3个字节),如果是编码gbk,varchar(n)的参数n最大是65532/2 = 32766(因为gbk中,一个字符占用2字节)。

sql 复制代码
mysql> create table tt9(name varchar(21845))charset==utf8;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
mysql> create table tt9(name varchar(21844))charset==utf8;
Query OK, 0 rows affected (0.02 sec)

验证了utf8确实是不能超过21844的;

char和varchar比较(utf8)

|-------|---------|------------|-----------|-------------|
| 实际存储 | char(4) | varchar(4) | char占用字节 | varchar占用字节 |
| abcd | abcd | abcd | 4*3 = 12 | 4*3+1 = 13 |
| a | a | a | 4*3 = 12 | 1*3+1 = 4 |
| abcde | X | X | 数据超过长度 | 数据超过长度 |

如何选择定长或者变长字符串?

1)如果数据确认长度都一样,就使用定长(char),比如身份证、手机号;

2)如果数据长度有变化就使用变成(varchar)比如,名字,地址,但要保证最长的数据可以存进去;

3)定长的磁盘空间比较浪费,但效率高;变长的磁盘空间比较节省,但效率低;

4)定长的意义是,直接开辟好对应的空间;变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少;

日期和时间类型

常用的日期有如下三个

1)date:日期'yyyy-mm-dd',占用三字节;

2)datetime:时间日期格式'yyyy-mm-dd hh:ii:ss'表示范围从1000~9999,占用八字节;

3)timestamp:时间戳,从1970年开始的'yyyy-mm-dd hh:ii:ss'格式和datetime完全一致,占用四字节;

例子

sql 复制代码
mysql> create table birthday(
    -> t1 date,
    -> t2 datetime,
    -> t3 timestamp);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into birthday(t1,t2)values('2018-8-8','2018-9-9 8:8:8');
Query OK, 1 row affected (0.00 sec)

mysql> select *from birthday;
+------------+---------------------+---------------------+
| t1         | t2                  | t3                  |
+------------+---------------------+---------------------+
| 2018-08-08 | 2018-09-09 08:08:08 | 2024-10-24 11:37:03 |
+------------+---------------------+---------------------+
1 row in set (0.00 sec)

添加数据时,时间戳会自动添加

更新数据

sql 复制代码
mysql> update birthday set t1 = '2022-2-22';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select *from birthday;
+------------+---------------------+---------------------+
| t1         | t2                  | t3                  |
+------------+---------------------+---------------------+
| 2022-02-22 | 2018-09-09 08:08:08 | 2024-10-24 11:39:51 |
+------------+---------------------+---------------------+
1 row in set (0.00 sec)
enum 和set

语法

sql 复制代码
enum:枚举,"单选"类型;
enum{'选择1','选择2','选择3',......};

该设定只是提供了若干个选项的值,最终一个单元格中,实际只存储了其中一个值;而且出于效率考虑,这些值实际存储的是'数字',因为这些选项的每一个选项值依次对应如下数字:1,2,3......65535;当我们添加枚举值时,也可以添加对应的数字编号。

sql 复制代码
set:集合,"多选"类型;
set('选项值1','选项值2','选项值3',......);

该设定只是提供了若干个选项的值,最终一个单元格中设计可存储了其中任意多个值;而且出于效率考虑,这些值实际存储的是"数字",因为这些选项的每个选项值依次对应以下数字,1,2,4,8......,最多64个。

例:有一个调查表votes,需要调查人的喜好,比如(登山、游泳、篮球、武术)中去选择(可以多选)(男,女)(单选)

创建表

sql 复制代码
mysql> create table votes(
    -> username varchar(30),
    -> hobby set('登山','游泳','篮球','武术'),
    -> gender enum('男','女'));
Query OK, 0 rows affected (0.02 sec)

插入数据

sql 复制代码
mysql> insert into votes values('lisi','登山,武术',''男');
Query OK, 1 row affected (0.01 sec)

mysql> insert into votes values('juse','登山,武术',''2');
Query OK, 1 row affected (0.01 sec)

mysql> insert into votes values('lilei','登山','1');
;
Query OK, 1 row affected (0.00 sec)

mysql> insert into votes values('王五','篮球','1');

Query OK, 1 row affected (0.00 sec)

mysql> insert into votes values('翠花','游泳','2'); 
Query OK, 1 row affected (0.01 sec)

查询想要登山的人

sql 复制代码
mysql> select *from votes where hobby = '登山';
+----------+--------+--------+
| username | hobby  | gender |
+----------+--------+--------+
| lilei    | 登山   | 男     |
+----------+--------+--------+
1 row in set (0.00 sec)

不能查询出所有,爱好为登山的人。

集合查询使用find_in_set函数,find_in_set(sub,str_list),如果sub在str_list,则返回下标,如果不在,返回0,str_list用逗号分隔的字符串。

sql 复制代码
mysql> select find_in_set('a','a,b,c');
+--------------------------+
| find_in_set('a','a,b,c') |
+--------------------------+
|                        1 |
+--------------------------+
1 row in set (0.00 sec)

mysql> select find_in_set('d','a,b,c');
+--------------------------+
| find_in_set('d','a,b,c') |
+--------------------------+
|                        0 |
+--------------------------+
1 row in set (0.00 sec)

所有,查询爱好登山的人

sql 复制代码
mysql> select *from votes where find_in_set('登山',hobby);
+----------+---------------+--------+
| username | hobby         | gender |
+----------+---------------+--------+
| lisi     | 登山,武术     | 男     |
| juse     | 登山,武术     | 女     |
| lilei    | 登山          | 男     |
+----------+---------------+--------+
3 rows in set (0.00 sec)

表的约束

真正约束字段的是数类型,但是数据类型约束很单一,需要一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性,比如有一个字段email,要求是唯一的。

表的约束很多,这里主要介绍如下几个:null/not null,default,comment,zerofill,primary key,auto_increment,unique key。

空属性

两个值:null(默认的)和not null(不为空)

数据库默认字段都是字段为空,但实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算。

sql 复制代码
mysql> select null+1;
+--------+
| null+1 |
+--------+
|   NULL |
+--------+
1 row in set (0.00 sec)

mysql> select null;
+------+
| NULL |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

例:创建一个班级表,包含班级名和班级所在教室,站在正常角度来说,如果班级没有名字,你不知道你在哪个班级,如果教师名字可以为空,就不知道在哪里上课。所以在设计数据库表的时候,一定要在表中进行限制,满足上面条件的数据就不能插入到表中。这就是"约束"。

sql 复制代码
mysql> create table myclass( class_name varchar(20) not null, class_room varchar(10) not null);
Query OK, 0 rows affected (0.02 sec)

mysql> desc myclass;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(20) | NO   |     | NULL    |       |
| class_room | varchar(10) | NO   |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

插入数据时,没有给教室数据就会插入失败

sql 复制代码
mysql> insert into myclass(class_name)values('class1');
ERROR 1364 (HY000): Field 'class_room' doesn't have a default value
默认值(缺省值)

某一种数据会经常性的出现某个具体的值,可以在一开始就指定好,在需要真实数据的时候,用户可以选择性的使用默认值。

sql 复制代码
mysql> create table tt10( name varchar(20) not null, age tinyint unsigned default 0, sex char(2) default '男');
Query OK, 0 rows affected (0.03 sec)

mysql> desc tt10;
+-------+---------------------+------+-----+---------+-------+
| Field | Type                | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| name  | varchar(20)         | NO   |     | NULL    |       |
| age   | tinyint(3) unsigned | YES  |     | 0       |       |
| sex   | char(2)             | YES  |     | 男      |       |
+-------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

默认值的生效:数据在插入的时候不给该字段赋值,就使用默认值

sql 复制代码
mysql> insert into tt10(name)values('zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> select *from tt10;
+----------+------+------+
| name     | age  | sex  |
+----------+------+------+
| zhangsan |    0 | 男   |
+----------+------+------+
1 row in set (0.00 sec)
列描述:comment,没有实际含义,专门用来描述字段,会根据表创建语句保存,用来给程序员或者DBA来进行了解。
sql 复制代码
mysql> create table tt11(
    -> name varchar(20) not null comment '姓名',
    -> age tinyint unsigned default 0 comment '年龄',
    -> sex char(2) default '男' comment '性别');
Query OK, 0 rows affected (0.02 sec)

注:not null和default一般不需要同时出现,因为default本身有默认值,不会为空。

sql 复制代码
mysql> desc tt11;
+-------+---------------------+------+-----+---------+-------+
| Field | Type                | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| name  | varchar(20)         | NO   |     | NULL    |       |
| age   | tinyint(3) unsigned | YES  |     | 0       |       |
| sex   | char(2)             | YES  |     | 男      |       |
+-------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

通过show可以看到

sql 复制代码
mysql> show create table tt11\G;
*************************** 1. row ***************************
       Table: tt11
Create Table: CREATE TABLE `tt11` (
  `name` varchar(20) NOT NULL COMMENT '姓名',
  `age` tinyint(3) unsigned DEFAULT '0' COMMENT '年龄',
  `sex` char(2) DEFAULT '男' COMMENT '性别'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
zerofill

在学习 数据库时,很多人对数字类型后面的长度有疑问,通过show查看以下表的建表语句:

sql 复制代码
mysql> show create table tt12\G
*************************** 1. row ***************************
       Table: tt12
Create Table: CREATE TABLE `tt12` (
  `a` int(10) unsigned DEFAULT NULL,
  `b` int(10) unsigned DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

可以看到int(10),这个代表什么意思呢?整形不是4个字节吗?这个10又代表什么呢?其实没有zerofill这个属性,括号内的数据是没有意义的。

没有zerofill属性

sql 复制代码
mysql> insert into tt12 values(1,2);
Query OK, 1 row affected (0.00 sec)

mysql> select *from tt12;
+------+------+
| a    | b    |
+------+------+
|    1 |    2 |
+------+------+
1 row in set (0.00 sec)

添加了zerofill属性

sql 复制代码
mysql> alter table tt12 modify a int(5) unsigned zerofill;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> select *from tt12;
+-------+------+
| a     | b    |
+-------+------+
| 00001 |    2 |
+-------+------+
1 row in set (0.00 sec)

可以看到原来的a的值由原来的1变成了00001,这就是zerofill属性的作用,如果宽度小于设定的宽度(这里设置的5),自动填充0.要注意的是,这只是最后显示的结果,在MySQL中实际存储的还是1,为什么会是这样呢?我们可以hex函数来证明。

sql 复制代码
mysql> select a,hex(a) from tt12;
+-------+--------+
| a     | hex(a) |
+-------+--------+
| 00001 | 1      |
+-------+--------+
1 row in set (0.00 sec)

可以看出数据库内部还是存储的1,00001只是设置了zerofill属性后的一种格式化输出而已。

主键

主键:primary key用来唯一的约束字段里面的数据,不能重复,不能为空,一张表最多只能有一个主键;主键所在的列表通常是整数类型。

例子:在创建表的时候直接在字段上指定主键

sql 复制代码
mysql> create table tt13( id int unsigned primary key comment '学号不能为空', name varchar(20) not nulll);
Query OK, 0 rows affected (0.02 sec)

mysql> desc tt13;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   | PRI | NULL    |       |
| name  | varchar(20)      | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

主键约束:主键对应中的字段不能重复,一旦重复,操作失败。

sql 复制代码
mysql> insert into tt13 values(1,'aaa');
Query OK, 1 row affected (0.00 sec)

mysql> insert into tt13 values(1,'bbb');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

当表创建以后但是没有主键的时候,可以再次追加主键;

sql 复制代码
alter table table_name add primary key(字段列表)

删除主键

sql 复制代码
alter table table_name drop primary key;
sql 复制代码
mysql> alter table tt13 drop primary key;
Query OK, 1 row affected (0.05 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> desc tt13;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   |     | NULL    |       |
| name  | varchar(20)      | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
复合主键

在创建表的时候,在所有字段之后,使用primary key(主键字段列表)来创建主键,如果有多个字段,作为主键,可以使用复合主键。

sql 复制代码
mysql> create table tt14(
    -> id int unsigned,
    -> course char(10) comment '课程代码',
    -> socre tinyint unsigned default 60 comment '成绩',
    -> primary key(id,course));
Query OK, 0 rows affected (0.03 sec)

mysql> desc tt14;
+--------+---------------------+------+-----+---------+-------+
| Field  | Type                | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| id     | int(10) unsigned    | NO   | PRI | NULL    |       |
| course | char(10)            | NO   | PRI | NULL    |       |
| socre  | tinyint(3) unsigned | YES  |     | 60      |       |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> insert into tt14(id,course)values(1,'123');
Query OK, 1 row affected (0.00 sec)

mysql> insert into tt14(id,course)values(1,'123');
ERROR 1062 (23000): Duplicate entry '1-123' for key 'PRIMARY'
自增长

auto_increment:当前对应的字段,不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值+1操作,得到一个新的不同值,通常搭配主键使用,作为逻辑主键。

自增长的特点:

1)任何一个字段要做自增长,前提是本身是一个索引(key一栏有值);

2)自增长字段必须是整数;

3)一张表最多只能有一个自增长;

例子:

sql 复制代码
mysql> create table tt15(
    -> id int unsigned primary key auto_increment,
    -> name varchar(10) not null default '');
Query OK, 0 rows affected (0.02 sec)

mysql> insert into tt15(name) values('a');
Query OK, 1 row affected (0.00 sec)

mysql> insert into tt15(name) values('b');
Query OK, 1 row affected (0.01 sec)

mysql> select *from tt15;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
+----+------+
2 rows in set (0.00 sec)

在插入后获取上次插入的auto_increment的值(批量插入获取的第一个值)

sql 复制代码
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
|                2 |
+------------------+
1 row in set (0.00 sec)
索引(以后细讲):

在关系数据库中,索引是一种单独的、物理的对数据库表中对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。

索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序,数据库使用索引可以找到特定值,然后顺指针找到包含该值的行,这样可以使对应于表的SQL语句执行的更快,可快速访问数据库表中的特定信息。

唯一键

一张表中有往往很多字段需要唯一性,数据不能重复,但是一张表中中只能有一个主键;唯一键就可以解决表中有多个字段需要唯一性约束的问题。唯一键的本质和主键差不多,唯一键允许为空,而且可以多个为空,空字段不做唯一性比较。

唯一键和主键的区别:

我们可以简单理解成,主键更多是表示唯一性的,而唯一键更多的是保证在业务上,不要和别的信息重复。

例子:

sql 复制代码
mysql> create table student(
    -> id char(10)unique comment '学号,不能重复,但可以为空',
    -> name varchar(10)
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> insert into student values('01','aaa');
Query OK, 1 row affected (0.00 sec)

mysql> insert into student values('01','bbb');
ERROR 1062 (23000): Duplicate entry '01' for key 'id'
mysql> insert into student values(null,'bbb');
Query OK, 1 row affected (0.00 sec)

mysql> select *from student;
+------+------+
| id   | name |
+------+------+
| 01   | aaa  |
| NULL | bbb  |
+------+------+
2 rows in set (0.00 sec)
外键

外键用于定义主表和从表之间的关系,外键约束主要定义在从表上,主表必须要有主键约束或unique约束,当定义外键后,要求外键列数据必须在主表的主键列存在或者为null.

语法

sql 复制代码
foreign key (字段名) reference 主表(列)

例:

先创建主键表

sql 复制代码
mysql> create table myclass(
    -> id int primary key,
    -> name varchar(30) not null comment '班级名'); 
Query OK, 0 rows affected (0.02 sec)

再创建从表

sql 复制代码
mysql> create table stu(
    -> id int primary key,
    -> name varchar(30) not null comment '学生名',
    -> class_id int,
    -> foreign key (class_id) references myclass(id));
Query OK, 0 rows affected (0.02 sec)

插入数据

sql 复制代码
mysql> insert into myclass values(10,'实验班'),(20,'小尖班');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into stu values(100,'张三',10),(101,'李四',20);
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

插入一个班级号为30的学生,因为没有这个班级,所以不能插入成功

sql 复制代码
mysql> insert into stu values(102,'王五',30);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test_4`.`stu`, CONSTRAINT `stu_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `myclass` (`id`))

插入班级id为null,比如来了一个学生,目前还没有分配班级

sql 复制代码
mysql> insert into stu values(103,'二麻子',null);
Query OK, 1 row affected (0.01 sec)

mysql> select *from stu;
+-----+-----------+----------+
| id  | name      | class_id |
+-----+-----------+----------+
| 100 | 张三      |       10 |
| 101 | 李四      |       20 |
| 103 | 二麻子    |     NULL |
+-----+-----------+----------+
3 rows in set (0.00 sec)

ok,本章结束,谢谢学习(撒花撒花)

相关推荐
Mr_Xuhhh16 分钟前
程序地址空间
android·java·开发语言·数据库
大明湖的狗凯.25 分钟前
MySQL 中的乐观锁与悲观锁
java·数据库·mysql
真上帝的左手25 分钟前
数据库-MySQL-MybatisPlus整合多数据源
数据库·mysql·mybatis
奈斯ing25 分钟前
【MySQL篇】持久化和非持久化统计信息的深度剖析(第一篇,总共六篇)
数据库·mysql
真上帝的左手26 分钟前
数据库-MySQL-Mybatis源码解析-设计模式角度
数据库·mysql·mybatis
shiming88791 小时前
C/C++链接数据库(MySQL)超级详细指南
c语言·数据库·c++
前端白袍1 小时前
C语言:C语言实现对MySQL数据库表增删改查功能
c语言·数据库·mysql
Elastic 中国社区官方博客1 小时前
Elasticsearch:Retrievers 介绍
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
蓝桉柒71 小时前
安装数据库客户端工具
数据库
南城花随雪。2 小时前
Redis(非关系型数据库)详细介绍
数据库·redis·nosql