MYSQL创建表的约束条件(可选)

Posted 迎风而来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MYSQL创建表的约束条件(可选)相关的知识,希望对你有一定的参考价值。

一、常用的一些约束条件

一、创建表的完整语法
1.创建表的万能模板:
create table 库名.表名(
字段名1 类型[(宽度) 约束条件],
字段名2 类型[(宽度) 约束条件],
字段名3 类型[(宽度) 约束条件]
);

2.约束条件:
是在数据类型之外对字段附加的额外的限制,当然了这种约束条件就是可有可无的啦,那你该问小编了可有可无那没有多好,省着麻烦了,之所以有是为了保证数据的完整性和一致性,毕竟我们结合现实的实际生产场景来做选择


3.创建表注意事项:
1、最后一个字段之后不能加逗号
2、 在同一张表中,字段名是不能相同
3、 宽度和约束条件可选,字段名和类型是必须要有的

4.常用约束条件及简单介绍
primary key (PK)      #标识该字段为该表的主键,可以唯一的标识记录,主键就是不为空且唯一当然其还有加速查询的作用
foreign key (FK)      #标识该字段为该表的外键,用来建立表与表的关联关系
not null              #标识该字段不能为空
unique key (UK)       #标识该字段的值是唯一的
auto_increment        #标识该字段的值自动增长(整数类型,而且为主键)
default               #为该字段设置默认值

unsigned              #将整型设置为无符号即正数
zerofill              #不够使用0进行填充

那么就让我们来一探究竟表的创建一些常用的约束条件的如何使用又有着什么样的作用吧!

 

二、not null与default

create table t1(
    id int primary key auto_increment,                #指定id为主键即不为空且唯一,并将其设置为自动增长
    name varchar(16) not null,                        #将名字设置为varchar类型,并将约束条件设置为不为空
    sex enum(male,female) not null default male #将名字设置为枚举类型即多选一,并将约束条件设置为不为空且设置默认值,如果我们不传名字则以默认的名字进行传入
);

让我们来向表中插入几条记录看看吧!
insert into t1(name) values(星星),(月亮),(太阳);
查看插入结果:
mysql> select * from t1;
+----+--------+------+
| id | name   | sex  |
+----+--------+------+
|  1 | 星星   | male |
|  2 | 月亮   | male |
|  3 | 太阳   | male |    可以看到我没有插入性别会以我们之前创建表时默认的为准,当然如果我们传入性别则会以我们传入的为准,是不是函数传参很像呢,对的知识就是这么灵活哈哈
+----+--------+------+
3 rows in set (0.00 sec)

 

二、unique应用

unique就是限制字段的值唯一用的

create table t2(x int unique);         #将字段x这只为唯一,也就是说不能插入的值不能重复喽
create table t3(
    x int,
    y varchar(5),
    unique key(x)                     #换汤不换药,只是换了件衣服,变换一种形式告诉你,原来设置字段唯一还可以这用,呵呵并没有什么卵用
);
‘‘‘---------------------------------------------------------------------------------‘‘‘
create table t4(
    x int,
    y varchar(5),
    constraint uni_x unique key(x)   #将字段x设置为唯一,并为该键起一个别名,起名字这事也没啥用
);

‘‘‘---------------------------------------------------------------------------------‘‘‘
create table service(
    ip varchar(15),
    port int,
    unique key(ip,port)              #联合主键,也就是说当你插入一条记录不能与之前插入的记录两个同时不能一样,有一个重复是也是可以正常插入滴
);
插入一条记录给你看看吧
mysql> insert into service values
    -> (1.1.1.1,3306),
    -> (1.1.1.1,3306);           #看到了吧我插入两条一样的记录,就是不让我插,哼!
ERROR 1062 (23000): Duplicate entry 1.1.1.1-3306 for key ip

三、primary key应用

从约束角度看primary key字段的值不为空且唯一,那我们直接使用not null+unique不就可以了吗,要它干什么?

主键primary key是innodb存储引擎组织数据的依据,innodb称之为索引组织表,一张表中必须有且只有一个主键。

一个表中可以:

单列做主键
多列做主键(复合主键)

 

但凡创建表,我们就要注意啦:

1、必须有且只要一个主键

2、通常id字段被设置为主键

技术分享图片
============单列做主键===============
#方法一:not null+unique
create table department1(
id int not null unique, #主键
name varchar(20) not null unique,
comment varchar(100)
);

mysql> desc department1;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | NO   | UNI | NULL    |       |
| comment | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.01 sec)

#方法二:在某一个字段后用primary key
create table department2(
id int primary key, #主键
name varchar(20),
comment varchar(100)
);

mysql> desc department2;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | YES  |     | NULL    |       |
| comment | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.00 sec)

#方法三:在所有字段后单独定义primary key
create table department3(
id int,
name varchar(20),
comment varchar(100),
constraint pk_name primary key(id); #创建主键并为其命名pk_name

mysql> desc department3;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | YES  |     | NULL    |       |
| comment | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.01 sec)

单列主键
单列做主键
技术分享图片
==================多列做主键================
create table service(
ip varchar(15),
port char(5),
service_name varchar(10) not null,
primary key(ip,port)
);


mysql> desc service;
+--------------+-------------+------+-----+---------+-------+
| Field        | Type        | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| ip           | varchar(15) | NO   | PRI | NULL    |       |
| port         | char(5)     | NO   | PRI | NULL    |       |
| service_name | varchar(10) | NO   |     | NULL    |       |
+--------------+-------------+------+-----+---------+-------+
rows in set (0.00 sec)

mysql> insert into service values
    -> (172.16.45.10,3306,mysqld),
    -> (172.16.45.11,3306,mariadb)
    -> ;
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into service values (172.16.45.10,3306,nginx);
ERROR 1062 (23000): Duplicate entry 172.16.45.10-3306 for key PRIMARY
多列做主键

存储引擎补充:

create table t12(x int)engine=‘myisam‘;
create table t13(x int)engine=‘innodb‘;
create table t14(x int)engine=‘memory‘;
create table t15(x int)engine=‘blackhole‘;

四、auto_increment应用

约束字段为自动增长,被约束的字段必须同时被key约束

 

 

五、foreign key应用

员工信息表有三个字段:工号  姓名  部门

公司有3个部门,但是有1个亿的员工,那意味着部门这个字段需要重复存储,部门名字越长,越浪费

把所有数据都存放于一张表的弊端

1、表的组织结构复杂不清晰
2、浪费空间
3、扩展性极差

解决方法:

我们完全可以定义一个部门表

然后让员工信息表关联该表,如何关联,即foreign key

 

寻找两张表之间关系的步骤:

寻找表与表之间的关系的套路---------站在左右两张表的角度进行寻找两张表的关系
    举例:emp表   dep表
    步骤一:
        part1:
        1、先站在左表emp的角度--------------员工的部门是唯一的
        2、去找左表emp的多条记录能否对应右表dep的一条记录
        3、翻译2的意义:
            左表emp的多条记录==》多个员工
            右表dep的一条记录==》一个部门

            最终翻译结果:多个员工是否可以属于一个部门?
            如果是则需要进行part2的流程

        part2:
        1、站在右表dep的角度
        2、去找右表dep的多条记录能否对应左表emp的一条记录
        3、翻译2的意义:
            右表dep的多条记录==》多个部门
            左表emp的一条记录==》一个员工

            最终翻译结果:多个部门是否可以包含同一个员工

            如果不可以,则可以确定emp与dep的关系只一个单向的多对一
            如何实现?
                在emp表中新增一个dep_id字段,该字段指向dep表的id字段

举例说明:

#1、约束1:有了foreign key在创建表时,----必须先建被关联的表dep,才能建关联表emp

create table dep(
    id int primary key auto_increment,
    dep_name char(10),
    dep_comment char(60)
);               #要先创建被关联的表,因为关联的表中有被关联表的id,否则先创建关联的表,此时


被关联的字段通常是一个key,
create table emp(
    id int primary key auto_increment,
    name char(16),
    gender enum(male,female) not null default male,
    dep_id int,
    foreign key(dep_id) references dep(id)          #自己表中的dep_id关联到dep中的id
);

#2、约束2:在插入记录时,必须先插被关联的表dep,才能插关联表emp
insert into dep(dep_name,dep_comment) values
(sb教学部,sb辅导学生学习,教授python课程),
(外交部,老男孩上海校区驻张江形象大使),
(nb技术部,nb技术能力有限部门);


insert into emp(name,gender,dep_id)  values
(alex,male,1),
(egon,male,2),
(lxx,male,1),
(wxx,male,1),
(wenzhou,female,3);

删除是则子相反,删除则是关联的表优先,有限成为被删除的对象
#3、约束3:更新与删除都需要考虑到关联与被关联的关系
解决方案:
1、先删除关联表emp,再删除被关联表dep,准备重建
mysql> drop table emp;
Query OK, 0 rows affected (0.11 sec)

mysql> drop table dep;
Query OK, 0 rows affected (0.04 sec)


2、重建:新增功能,同步更新,同步删除
create table dep(
    id int primary key auto_increment,
    dep_name char(10),
    dep_comment char(60)
);

create table emp(
    id int primary key auto_increment,
    name char(16),
    gender enum(male,female) not null default male,
    dep_id int,
    foreign key(dep_id) references dep(id)
    on update cascade               #更新同步
    on delete cascade               #删除同步
);
insert into dep(dep_name,dep_comment) values
(sb教学部,sb辅导学生学习,教授python课程),
(外交部,老男孩上海校区驻张江形象大使),
(nb技术部,nb技术能力有限部门);


insert into emp(name,gender,dep_id)  values
(alex,male,1),
(egon,male,2),
(lxx,male,1),
(wxx,male,1),
(wenzhou,female,3);


# 同步删除
mysql> select * from dep;
+----+------------------+------------------------------------------------------------------------------------------+
| id | dep_name         | dep_comment                                                                              |
+----+------------------+------------------------------------------------------------------------------------------+
|  1 | sb教学部         | sb辅导学生学习,教授python课程                                                           |
|  2 | 外交部           | 老男孩上海校区驻张江形象大使                                                             |
|  3 | nb技术部         | nb技术能力有限部门                                                                       |
+----+------------------+------------------------------------------------------------------------------------------+
3 rows in set (0.00 sec)

mysql> select * from emp;
+----+------------------+--------+--------+
| id | name             | gender | dep_id |
+----+------------------+--------+--------+
|  1 | alex             | male   |      1 |
|  2 | egon             | male   |      2 |
|  3 | lxx              | male   |      1 |
|  4 | wxx              | male   |      1 |
|  5 | wenzhou          | female |      3 |
+----+------------------+--------+--------+
5 rows in set (0.00 sec)

mysql> delete from dep where id=1;
Query OK, 1 row affected (0.02 sec)

mysql> select * from dep;
+----+------------------+------------------------------------------------------------------------------------------+
| id | dep_name         | dep_comment                                                                              |
+----+------------------+------------------------------------------------------------------------------------------+
|  2 | 外交部           | 老男孩上海校区驻张江形象大使                                                             |
|  3 | nb技术部         | nb技术能力有限部门                                                                       |
+----+------------------+------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> select * from emp;
+----+------------------+--------+--------+
| id | name             | gender | dep_id |
+----+------------------+--------+--------+
|  2 | egon             | male   |      2 |
|  5 | wenzhou          | female |      3 |
+----+------------------+--------+--------+
2 rows in set (0.00 sec)

#同步更新
mysql> select * from emp;
+----+------------------+--------+--------+
| id | name             | gender | dep_id |
+----+------------------+--------+--------+
|  2 | egon             | male   |      2 |
|  5 | wenzhou          | female |      3 |
+----+------------------+--------+--------+
2 rows in set (0.00 sec)

mysql> update dep set id=200 where id =2;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from dep;
+-----+------------------+------------------------------------------------------------------------------------------+
| id  | dep_name         | dep_comment                                                                              |
+-----+------------------+------------------------------------------------------------------------------------------+
|   3 | nb技术部         | nb技术能力有限部门                                                                       |
| 200 | 外交部           | 老男孩上海校区驻张江形象大使                                                             |
+-----+------------------+------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> select * from emp;
+----+------------------+--------+--------+
| id | name             | gender | dep_id |
+----+------------------+--------+--------+
|  2 | egon             | male   |    200 |
|  5 | wenzhou          | female |      3 |
+----+------------------+--------+--------+
2 rows in set (0.00 sec)

 

以上是关于MYSQL创建表的约束条件(可选)的主要内容,如果未能解决你的问题,请参考以下文章

mysql基本数据类型和约束条件

mysql数据库表的基本操作

mysql 表的创建

mysql 表操作

MySQL表的完整性约束

MySQL表的完整性约束