Mysql库,表的详细操作

一 库操作

  1、创建数据库

    1.1 语法

      CREATE DATABASE 数据库名 charset utf8;

    1.2 数据库命名规则

      可以由字母、数字、下划线、@、#、$

      区分大小写

      唯一性

      不能使用关键字如 create select

      不能单独使用数字

      最长128位

      # 基本上跟python或者js的命名规则一样

   2、数据库相关操作

    也是一些基本操作,和我们之前说的差不多。

1 查看数据库
show databases;
show create database db1;
select database();

2 选择数据库
USE 数据库名

3 删除数据库
DROP DATABASE 数据库名;

4 修改数据库
alter database db1 charset utf8;

二 表操作

  1、存储引擎

    了解地址:https://www.cnblogs.com/clschao/articles/9953550.html

   2、表介绍

     表相当于文件,表中的一条记录就相当于文件的一行内容,表中的一条记录有对应的标题,称为表的字段

     

    第一行的id、name2、age是字段,,其余的,一行内容称为一条记录。

   3、创建表

    3.1 建表语法    

#语法:
create table 表名(
字段名1 类型[(宽度) 约束条件],
字段名2 类型[(宽度) 约束条件],
字段名3 类型[(宽度) 约束条件]
);

#注意:
1. 在同一张表中,字段名是不能相同 2. 宽度和约束条件可选、非必须,宽度指的就是字段长度约束,例如:char(10)里面的10 3. 字段名和类型是必须的
mysql> create database db1 charset utf8;

mysql> use db1;

mysql> create table t1(  
    -> id int, 
    -> name varchar(50),
    -> sex enum('male','female'),
    -> age int(3)
    -> );

mysql> show tables; #查看db1库下所有表名

mysql> desc t1;
+-------+-----------------------+------+-----+---------+-------+
| Field | Type                  | Null | Key | Default | Extra |
+-------+-----------------------+------+-----+---------+-------+
| id    | int(11)               | YES  |     | NULL    |       |
| name  | varchar(50)           | YES  |     | NULL    |       |
| sex   | enum('male','female') | YES  |     | NULL    |       |
| age   | int(3)                | YES  |     | NULL    |       |
+-------+-----------------------+------+-----+---------+-------+

mysql> select id,name,sex,age from t1;
Empty set (0.00 sec)

mysql> select * from t1;
Empty set (0.00 sec)

mysql> select id,name from t1;
Empty set (0.00 sec)
代码示例
mysql> insert into t1 values
    -> (1,'chao',18,'male'),
    -> (2,'sb',81,'female')
    -> ;
mysql> select * from t1;
+------+------+------+--------+
| id   | name | age  | sex    |
+------+------+------+--------+
|    1 | chao |   18 | male   |
|    2 | sb |   81 | female |
+------+------+------+--------+



mysql> insert into t1(id) values 
    -> (3),
    -> (4);
mysql> select * from t1;
+------+------+------+--------+
| id   | name | age  | sex    |
+------+------+------+--------+
|    1 | chao |   18 | male   |
|    2 | sb |   81 | female |
|    3 | NULL | NULL | NULL   |
|    4 | NULL | NULL | NULL   |
+------+------+------+--------+
插入数据

  4、查看表结构

mysql> describe t1; #查看表结构,可简写为:desc 表名
+-------+-----------------------+------+-----+---------+-------+
| Field | Type                  | Null | Key | Default | Extra |
+-------+-----------------------+------+-----+---------+-------+
| id    | int(11)               | YES  |     | NULL    |       |
| name  | varchar(50)           | YES  |     | NULL    |       |
| sex   | enum('male','female') | YES  |     | NULL    |       |
| age   | int(3)                | YES  |     | NULL    |       |
+-------+-----------------------+------+-----+---------+-------+


mysql> show create table t1\G; #查看表详细结构,可加\G
查看表结构的方法

  5、MySQL的基础数据类型

  数值类型

    5.1、整数类型

    整数类型:TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT

    作用:存储年龄,等级,id,各种号码等

 tinyint[(m)] [unsigned] [zerofill]

            小整数,数据类型用于保存一些范围的整数数值范围:
            有符号:
                -128 ~ 127
            无符号:
                0 ~ 255

            PS: MySQL中无布尔值,使用tinyint(1)构造。



        int[(m)][unsigned][zerofill]

            整数,数据类型用于保存一些范围的整数数值范围:
            有符号:
                    -2147483648 ~ 2147483647
            无符号:
                    0 ~ 4294967295



        bigint[(m)][unsigned][zerofill]
            大整数,数据类型用于保存一些范围的整数数值范围:
            有符号:
                    -9223372036854775808 ~ 9223372036854775807
            无符号:
                    0  ~  18446744073709551615
整数类型分类
有符号和无符号tinyint
    1.tinyint默认为有符号
        mysql> create table t1(x tinyint); #默认为有符号,即数字前有正负号
        mysql> desc t1;
        mysql> insert into t1 values
            -> (-129),
            -> (-128),
            -> (127),
            -> (128);
        mysql> select * from t1;
        +------+
        | x    |
        +------+
        | -128 | #-129存成了-128
        | -128 | #有符号,最小值为-128
        |  127 | #有符号,最大值127
        |  127 | #128存成了127
        +------+



    2.设置无符号tinyint
        mysql> create table t2(x tinyint unsigned);
        mysql> insert into t2 values
            -> (-1),
            -> (0),
            -> (255),
            -> (256);
        mysql> select * from t2;
        +------+
        | x    |
        +------+
        |    0 | -1存成了0
        |    0 | #无符号,最小值为0
        |  255 | #无符号,最大值为255
        |  255 | #256存成了255
        +------+



有符号和无符号int
    1.int默认为有符号
        mysql> create table t3(x int); #默认为有符号整数
        mysql> insert into t3 values
            -> (-2147483649),
            -> (-2147483648),
            -> (2147483647),
            -> (2147483648);
        mysql> select * from t3;
        +-------------+
        | x           |
        +-------------+
        | -2147483648 | #-2147483649存成了-2147483648
        | -2147483648 | #有符号,最小值为-2147483648
        |  2147483647 | #有符号,最大值为2147483647
        |  2147483647 | #2147483648存成了2147483647
        +-------------+



    2.设置无符号int
        mysql> create table t4(x int unsigned);
        mysql> insert into t4 values
            -> (-1),
            -> (0),
            -> (4294967295),
            -> (4294967296);
        mysql> select * from t4;
        +------------+
        | x          |
        +------------+
        |          0 | #-1存成了0
        |          0 | #无符号,最小值为0
        | 4294967295 | #无符号,最大值为4294967295
        | 4294967295 | #4294967296存成了4294967295
        +------------+




有符号和无符号bigint
    1.有符号bigint
        mysql> create table t6(x bigint);
        mysql> insert into t5 values  
            -> (-9223372036854775809),
            -> (-9223372036854775808),
            -> (9223372036854775807),
            -> (9223372036854775808);

        mysql> select * from t5;
        +----------------------+
        | x                    |
        +----------------------+
        | -9223372036854775808 |
        | -9223372036854775808 |
        |  9223372036854775807 |
        |  9223372036854775807 |
        +----------------------+


    2.无符号bigint
        mysql> create table t6(x bigint unsigned);
        mysql> insert into t6 values  
            -> (-1),
            -> (0),
            -> (18446744073709551615),
            -> (18446744073709551616);

        mysql> select * from t6;
        +----------------------+
        | x                    |
        +----------------------+
        |                    0 |
        |                    0 |
        | 18446744073709551615 |
        | 18446744073709551615 |
        +----------------------+




用zerofill测试整数类型的显示宽度
    mysql> create table t7(x int(3) zerofill);
    mysql> insert into t7 values
        -> (1),
        -> (11),
        -> (111),
        -> (1111);
    mysql> select * from t7;
    +------+
    | x    |
    +------+
    |  001 |
    |  011 |
    |  111 |
    | 1111 | #超过宽度限制仍然可以存
    +------+
整数类型范围验证

注意:对于整型来说,数据类型后面的宽度并不是存储长度限制,而是显示限制,假如:int(8),那么显示时不够8位则用0来填充,够8位则正常显示,通过zerofill来测试,存储长度还是int的4个字节长度。默认的显示宽度就是能够存储的最大的数据的长度,比如:int无符号类型,那么默认的显示宽度就是int(10),有符号的就是int(11),因为多了一个符号,所以我们没有必要指定整数类型的数据,没必要指定宽度,因为默认的就能够将你存的原始数据完全显示

    

    int的存储宽度是4个Bytes,即32个bit,即2**32  

    无符号最大值为:4294967296-1

    有符号最大值:2147483648-1

    有符号和无符号的最大数字需要的显示宽度均为10,而针对有符号的最小值则需要11位才能显示完全,所以int类型默认的显示宽度为11是非常合理的

    最后:整形类型,其实没有必要指定显示宽度,使用默认的就ok

  5.2、浮点型

    定点数类型  DEC,等同于DECIMAL  

    浮点类型:FLOAT DOUBLE

    作用:存储薪资、身高、温度、体重、体质参数等

1.FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]

    定义:
            单精度浮点数(非准确小数值),m是整数部分+小数部分的总个数,d是小数点后个数。m最大值为255,d最大值为30,例如:float(255,30)

    有符号:
               -3.402823466E+38 to -1.175494351E-38,
               1.175494351E-38 to 3.402823466E+38
    无符号:
               1.175494351E-38 to 3.402823466E+38


    精确度: 
               **** 随着小数的增多,精度变得不准确 ****



2.DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]

    定义:
               双精度浮点数(非准确小数值),m是整数部分+小数部分的总个数,d是小数点后个数。m最大值也为255,d最大值也为30

    有符号:
               -1.7976931348623157E+308 to -2.2250738585072014E-308
               2.2250738585072014E-308 to 1.7976931348623157E+308

    无符号:
               2.2250738585072014E-308 to 1.7976931348623157E+308
                
    精确度:
               ****随着小数的增多,精度比float要高,但也会变得不准确 ****


3.decimal[(m[,d])] [unsigned] [zerofill]

    定义:
              准确的小数值,m是整数部分+小数部分的总个数(负号不算),d是小数点后个数。 m最大值为65,d最大值为30。比float和double的整数个数少,但是小数位数都是30位


    精确度:
               **** 随着小数的增多,精度始终准确 ****
               对于精确数值计算时需要用此类型
               decimal能够存储精确值的原因在于其内部按照字符串存储。
精度从高到低:decimal、double、float
    decimal精度高,但是整数位数少
    float和double精度低,但是整数位数多
float已经满足绝大多数的场景了,但是什么导弹、航线等要求精度非常高,所以还是需要按照业务场景自行选择,如果又要精度高又要整数位数多,那么你可以直接用字符串来存。

浮点型分类
浮点类型分类
mysql> create table t1(x float(256,31));
ERROR 1425 (42000): Too big scale 31 specified for column 'x'. Maximum is 30.
mysql> create table t1(x float(256,30));
ERROR 1439 (42000): Display width out of range for column 'x' (max = 255)
mysql> create table t1(x float(255,30)); #建表成功
Query OK, 0 rows affected (0.02 sec)

mysql> create table t2(x double(255,30)); #建表成功
Query OK, 0 rows affected (0.02 sec)

mysql> create table t3(x decimal(66,31));
ERROR 1425 (42000): Too big scale 31 specified for column 'x'. Maximum is 30.
mysql> create table t3(x decimal(66,30));
ERROR 1426 (42000): Too-big precision 66 specified for 'x'. Maximum is 65.
mysql> create table t3(x decimal(65,30)); #建表成功
Query OK, 0 rows affected (0.02 sec)

mysql> show tables;
+---------------+
| Tables_in_db1 |
+---------------+
| t1            |
| t2            |
| t3            |
+---------------+
rows in set (0.00 sec)



mysql> insert into t1 values(1.1111111111111111111111111111111); #小数点后31个1
Query OK, 1 row affected (0.01 sec)

mysql> insert into t2 values(1.1111111111111111111111111111111);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t3 values(1.1111111111111111111111111111111);
Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> select * from t1; #随着小数的增多,精度开始不准确
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111164093017600000000000000 |
+----------------------------------+
row in set (0.00 sec)

mysql> select * from t2; #精度比float要准确点,但随着小数的增多,同样变得不准确
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111111111111200000000000000 |
+----------------------------------+
row in set (0.00 sec)

mysql> select * from t3; #精度始终准确,d为30,于是只留了30位小数
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111111111111111111111111111 |
+----------------------------------+
row in set (0.00 sec)

浮点型测试
浮点类型测试

  日期类型

  类型:DATE,TIME,DATETIME ,IMESTAMP,YEAR 

  作用:存储用户注册时间,文章发布时间,员工入职时间,出生时间,过期时间等

YEAR
            YYYY(范围:1901/2155)2018

        DATE
            YYYY-MM-DD(范围:1000-01-01/9999-12-31)例:2018-01-01 

        TIME
            HH:MM:SS(范围:'-838:59:59'/'838:59:59')例:12:09:32

        DATETIME

            YYYY-MM-DD HH:MM:SS(范围:1000-01-01 00:00:00/9999-12-31 23:59:59    Y)例: 2018-01-01 12:09:32

        TIMESTAMP

            YYYYMMDD HHMMSS(范围:1970-01-01 00:00:00/2037 年某时)
日期类型分类
year:
    mysql> create table t10(born_year year); #无论year指定何种宽度,最后都默认是year(4)
    mysql> insert into t10 values  
        -> (1900),
        -> (1901),
        -> (2155),
        -> (2156);
    mysql> select * from t10;
    +-----------+
    | born_year |
    +-----------+
    |      0000 |
    |      1901 |
    |      2155 |
    |      0000 |
    +-----------+


date,time,datetime:
    mysql> create table t11(d date,t time,dt datetime);
    mysql> desc t11;
    +-------+----------+------+-----+---------+-------+
    | Field | Type     | Null | Key | Default | Extra |
    +-------+----------+------+-----+---------+-------+
    | d     | date     | YES  |     | NULL    |       |
    | t     | time     | YES  |     | NULL    |       |
    | dt    | datetime | YES  |     | NULL    |       |
    +-------+----------+------+-----+---------+-------+

    mysql> insert into t11 values(now(),now(),now());
    mysql> select * from t11;
    +------------+----------+---------------------+
    | d          | t        | dt                  |
    +------------+----------+---------------------+
    | 2017-07-25 | 16:26:54 | 2017-07-25 16:26:54 |
    +------------+----------+---------------------+



timestamp:
    mysql> create table t12(time timestamp);
    mysql> insert into t12 values();
    mysql> insert into t12 values(null);
    mysql> select * from t12;
    +---------------------+
    | time                |
    +---------------------+
    | 2017-07-25 16:29:17 |
    | 2017-07-25 16:30:01 |
    +---------------------+



============注意啦,注意啦,注意啦===========
    1. 单独插入时间时,需要以字符串的形式,按照对应的格式插入
    2. 插入年份时,尽量使用4位值
    3. 插入两位年份时,<=69,以20开头,比如50,  结果2050      
                    >=70,以19开头,比如71,结果1971
    mysql> create table t12(y year);
    mysql> insert into t12 values  
        -> (50),
        -> (71);
    mysql> select * from t12;
    +------+
    | y    |
    +------+
    | 2050 |
    | 1971 |
    +------+



============综合练习===========
    mysql> create table student(
        -> id int,
        -> name varchar(20),
        -> born_year year,
        -> birth date,
        -> class_time time,
        -> reg_time datetime);

    mysql> insert into student values
        -> (1,'sb1',"1995","1995-11-11","11:11:11","2017-11-11 11:11:11"),
        -> (2,'sb2',"1997","1997-12-12","12:12:12","2017-12-12 12:12:12"),
        -> (3,'sb3',"1998","1998-01-01","13:13:13","2017-01-01 13:13:13");  

    mysql> select * from student;
    +------+------+-----------+------------+------------+---------------------+
    | id   | name | born_year | birth      | class_time | reg_time            |
    +------+------+-----------+------------+------------+---------------------+
    |    1 | sb1 |      1995 | 1995-11-11 | 11:11:11   | 2017-11-11 11:11:11 |
    |    2 | sb2 |      1997 | 1997-12-12 | 12:12:12   | 2017-12-12 12:12:12 |
    |    3 | sb3 |      1998 | 1998-01-01 | 13:13:13   | 2017-01-01 13:13:13 |
    +------+------+-----------+------------+------------+---------------------+
日期类型测试

  mysql的日期格式对字符串采用的是'放松'政策,可以以字符串的形式插入。

在实际应用的很多场景中,MySQL的这两种日期类型都能够满足我们的需要,存储精度都为秒,但在某些情况下,会展现出他们各自的优劣。下面就来总结一下两种日期类型的区别。

1.DATETIME的日期范围是1001——9999年,TIMESTAMP的时间范围是1970——2038年。

2.DATETIME存储时间与时区无关,TIMESTAMP存储时间与时区有关,显示的值也依赖于时区。在mysql服务器,操作系统以及客户端连接都有时区的设置。

3.DATETIME使用8字节的存储空间,TIMESTAMP的存储空间为4字节。因此,TIMESTAMP比DATETIME的空间利用率更高。

4.DATETIME的默认值为null;TIMESTAMP的字段默认不为空(not null),默认值为当前时间(CURRENT_TIMESTAMP),如果不做特殊处理,并且update语句中没有指定该列的更新值,则默认更新为当前时间。
datetime与timestamp的区别

  工作中一般都用datetime就可以了。

  字符串类型

  类型:char,varchar

  作用:名字,信息等等

#官网:https://dev.mysql.com/doc/refman/5.7/en/char.html
#注意:char和varchar括号内的参数指的都是字符的长度

#char类型:定长,简单粗暴,浪费空间,存取速度快
    字符长度范围:0-255(一个中文是一个字符,是utf8编码的3个字节)
    存储:
        存储char类型的值时,会往右填充空格来满足长度
        例如:指定长度为10,存>10个字符则报错(严格模式下),存<10个字符则用空格填充直到凑够10个字符存储

    检索:
        在检索或者说查询时,查出的结果会自动删除尾部的空格,如果你想看到它补全空格之后的内容,除非我们打开pad_char_to_full_length SQL模式(SET sql_mode = 'strict_trans_tables,PAD_CHAR_TO_FULL_LENGTH';)

#varchar类型:变长,精准,节省空间,存取速度慢
    字符长度范围:0-65535(如果大于21845会提示用其他类型 。mysql行最大限制为65535字节,字符编码为utf-8:https://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html)
    存储:
        varchar类型存储数据的真实内容,不会用空格填充,如果'ab  ',尾部的空格也会被存起来
        强调:varchar类型会在真实数据前加1-2Bytes的前缀,该前缀用来表示真实数据的bytes字节数(1-2Bytes最大表示65535个数字,正好符合mysql对row的最大字节限制,即已经足够使用)
        如果真实的数据<255bytes则需要1Bytes的前缀(1Bytes=8bit 2**8最大表示的数字为255)
        如果真实的数据>255bytes则需要2Bytes的前缀(2Bytes=16bit 2**16最大表示的数字为65535)
    
    检索:
        尾部有空格会保存下来,在检索或者说查询时,也会正常显示包含空格在内的内容
char和varchar的介绍

  下面我们来进行一些测试,在测试之前,我们需要学一下mysql给我们提供的两个方法:

    length(字段):查看该字段数据的字节长度

    char_length(字段):查看该字段数据的字符长度

创建一个t1表,包含一个char类型的字段
create table t1(id int,name char(4));
            超过长度:
                严格模式下(报错):
                    mysql> insert into t1 values('xiaoshabi');
                    ERROR 1406 (22001): Data too long for column 'name' at row 1
                非严格模式下(警告):
                    mysql> set sql_mode='NO_ENGINE_SUBSTITUTION';
                    Query OK, 0 rows affected (0.00 sec)

                    mysql> create table t1(id int,name char(4));
                    Query OK, 0 rows affected (0.40 sec)

                    mysql> insert into t2 values('xiaoshabi');
                    Query OK, 1 row affected, 1 warning (0.11 sec)
                    查看一下结果:
                    mysql> select * from t1;
                    +------+------+
                    | id   | name |
                    +------+------+
                    |    1 | xiao | #只有一个xiao
                    +------+------+
                    1 row in set (0.00 sec)
                varchar类型和上面的效果是一样的,严格模式下也会报错。
            
            如果没有超过长度,那么char类型时mysql会使用空格来补全自己规定的char(4)的4个字符,varchar不会,我们来做个对比
            例如:
                #再创建一个含有varchar类型的表t2
                然后插入几条和t1里面相同的数据
                mysql>insert into t1 values(2,'a'),(3,'bb'),(4,'ccc'),(5,'d');
                
                mysql>create table t2(id int,name varchar(4));
                
                mysql> insert into t2 values(1,'xiao'),(2,'a'),(3,'bb'),(4,'ccc'),(5,'d');
                查看一下t1表和t2表的内容
                mysql> select * from t1;
                +------+------+
                | id   | name |
                +------+------+
                |    1 | xiao |
                |    2 | a    |
                |    3 | bb   |
                |    4 | ccc  |
                |    5 | d    |
                +------+------+
                5 rows in set (0.00 sec)

                mysql> select * from t2;
                +------+------+
                | id   | name |
                +------+------+
                |    1 | xiao |
                |    2 | a    |
                |    3 | bb   |
                |    4 | ccc  |
                |    5 | d    |
                +------+------+
                5 rows in set (0.00 sec)
                
            好,两个表里面数据是一样的,每一项的数据长度也是一样的,那么我们来验证一下char的自动空格在后面补全的存储方式和varchar的不同
            
            通过mysql提供的一个char_length()方法来查看一下所有数据的长度
            mysql> select char_length(name) from t1;
            +-------------------+
            | char_length(name) |
            +-------------------+
            |                 4 |
            |                 1 |
            |                 2 |
            |                 3 |
            |                 1 |
            +-------------------+
            5 rows in set (0.00 sec)
            
            mysql> select char_length(name) from t2;
            +-------------------+
            | char_length(name) |
            +-------------------+
            |                 4 |
            |                 1 |
            |                 2 |
            |                 3 |
            |                 1 |
            +-------------------+
            5 rows in set (0.00 sec)
            通过查看结果可以看到,两者显示的数据长度是一样的,不是说好的char会补全吗,我设置的字段是char(4),那么长度应该都是4才对啊?这是因为mysql在你查询的时候自动帮你把结果里面的空格去掉了,如果我们想看到它存储数据的真实长度,需要设置mysql的模式,通过一个叫做PAD_CHAR_TO_FULL_LENGTH的模式,就可以看到了,所以我们把这个模式加到sql_mode里面:
                mysql> set sql_mode='PAD_CHAR_TO_FULL_LENGTH';
                Query OK, 0 rows affected (0.00 sec)
                
                然后我们在查看一下t1和t2数据的长度:
                mysql> select char_length(name) from t1;
                +-------------------+
                | char_length(name) |
                +-------------------+
                |                 4 |
                |                 4 |
                |                 4 |
                |                 4 |
                |                 4 |
                +-------------------+
                5 rows in set (0.00 sec)
                
                mysql> select char_length(name) from t2;
                +-------------------+
                | char_length(name) |
                +-------------------+
                |                 4 |
                |                 1 |
                |                 2 |
                |                 3 |
                |                 1 |
                +-------------------+
                5 rows in set (0.00 sec)
                通过结果可以看到,char类型的数据长度都是4,这下看到了两者的不同了吧,至于为什么mysql会这样搞,我们后面有解释的,先看现象就可以啦。
                
            现在我们再来看一个问题,就是当你设置的类型为char的时候,我们通过where条件来查询的时候会有一个什么现象:
                mysql> select * from t1 where name='a';
                +------+------+
                | id   | name |
                +------+------+
                |    2 | a    |
                +------+------+
                1 row in set (0.00 sec)
            ok,结果没问题,我们在where后面的a后面加一下空格再来试试:
                mysql> select * from t1 where name='a ';
                +------+------+
                | id   | name |
                +------+------+
                |    2 | a    |
                +------+------+
                1 row in set (0.00 sec)
            ok,能查到,再多加一些空格试试,加6个空格,超过了设置的char(4)的4:
                mysql> select * from t1 where name='a      ';
                +------+------+
                | id   | name |
                +------+------+
                |    2 | a    |
                +------+------+
                1 row in set (0.00 sec)
            ok,也是没问题的
            总结:通过>,=,>=,<,<=作为where的查询条件的时候,char类型字段的查询是没问题的。
            但是,当我们将where后面的比较符号改为like的时候,(like是模糊匹配的意思,我们前面见过,show variables like '%char%';来查看mysql字符集的时候用过)
                其中%的意思是匹配任意字符(0到多个字符都可以匹配到),还有一个符号是_(匹配1个字符),这两个字符其实就像我们学的正则匹配里面的通配符,那么我们通过这些符号进行一下模糊查询,看一下,char类型进行模糊匹配的时候,是否还能行,看例子:
                mysql> select * from t1 where name like 'a';
                Empty set (0.00 sec)
                发现啥也没查到,因为char存储的数据是4个字符长度的,不满4个是以空格来补全的,你在like后面就只写了一个'a',是无法查到的。
                我们试一下上面的通配符来查询:
                mysql> select * from t1 where name like 'a%';
                +------+------+
                | id   | name |
                +------+------+
                |    2 | a    |
                +------+------+
                1 row in set (0.00 sec)
                这样就能看到查询结果了
                
                试一下_是不是匹配1个字符:
                mysql> select * from t1 where name like 'a_';
                Empty set (0.00 sec)
                发现一个_果然不行,我们试试三个_。
                mysql> select * from t1 where name like 'a___';
                +------+------+
                | id   | name |
                +------+------+
                |    2 | a    |
                +------+------+
                1 row in set (0.00 sec)
                发现果然能行,一个_最多匹配1个任意字符。
                如果多写了几个_呢?
                mysql> select * from t1 where name like 'a_____';
                Empty set (0.00 sec)
                查不到结果,说明_匹配的是1个字符,但不是0-1个字符。
char和varchar测试

测试结果总结:
  针对char类型,mysql在存储的时候会将不足规定长度的数据使用后面(右边补全)补充空格的形式进行补全,然后存放到硬盘中,但是在读取或者使用的时候会自动去掉它给你补全的空格内容,因为这些空格并不是我们自己存储的数据,所以对我们使用者来说是无用的。

  char和varchar性能对比:
    以char(5)和varchar(5)来比较,加入我要存三个人名:sb,ssb1,ssbb2
    char:
      优点:简单粗暴,不管你是多长的数据,我就按照规定的长度来存,5个5个的存,三个人名就会类似这种存储:sb ssb1 ssbb2,中间是空格补全,取数据的时候5个5个的取,简单粗暴速度快
      缺点:貌似浪费空间,并且我们将来存储的数据的长度可能会参差不齐

    varchar:
      varchar类型不定长存储数据,更为精简和节省空间
      例如存上面三个人名的时候类似于是这样的:sbssb1ssbb2,连着的,如果这样存,请问这三个人名你还怎么取出来,你知道取多长能取出第一个吗?(超哥,我能看出来啊,那我只想说:滚犊子!)
      不知道从哪开始从哪结束,遇到这样的问题,你会想到怎么解决呢?还记的吗?想想?socket?tcp?struct?把数据长度作为消息头。

      
      所以,varchar在存数据的时候,会在每个数据前面加上一个头,这个头是1-2个bytes的数据,这个数据指的是后面跟着的这个数据的长度,1bytes能表示2**8=256,两个bytes表示2**16=65536,能表示0-65535的数字,所以varchar在存储的时候是这样的:1bytes+sb+1bytes+ssb1+1bytes+ssbb2,所以存的时候会比较麻烦,导致效率比char慢,取的时候也慢,先拿长度,再取数据。

      优点:节省了一些硬盘空间,一个acsii码的字符用一个bytes长度就能表示,但是也并不一定比char省,看一下官网给出的一个表格对比数据,当你存的数据正好是你规定的字段长度的时候,varchar反而占用的空间比char要多。

Value CHAR(4) Storage Required VARCHAR(4) Storage Required
'' '    ' 4 bytes '' 1 byte
'ab' 'ab  ' 4 bytes 'ab' 3 bytes
'abcd' 'abcd' 4 bytes 'abcd' 5 bytes
'abcdefgh' 'abcd' 4 bytes 'abcd' 5 bytes

        
      缺点:存取速度都慢

  总结:
    所以需要根据业务需求来选择用哪种类型来存
    其实在多数的用户量少的工作场景中char和varchar效率差别不是很大,最起码给用户的感知不是很大,并且其实软件级别的慢远比不上硬件级别的慢,所以你们公司的运维发现项目慢的时候会加内存、换nb的硬盘,项目的效率提升的会很多,但是我们作为专业人士,我们应该提出来这样的技术点来提高效率。

    但是对于InnoDB数据表,内部的行存储格式没有区分固定长度和可变长度列(所有数据行都使用指向数据列值的头指针),因此在本质上,使用固定长度的CHAR列不一定比使用可变长度VARCHAR列性能要好。因而,主要的性能因素是数据行使用的存储总量。由于CHAR平均占用的空间多于VARCHAR,因此使用VARCHAR来最小化需要处理的数据行的存储总量和磁盘I/O是比较好的。

其他的字符串类型:BINARY、VARBINARY、BLOB、TEXT

  

BINARY 和 VARBINARY 类似于 CHAR 和 VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。
BLOB 是一个二进制大对象,可以容纳可变数量的数据。有 4 种 BLOB 类型:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。它们区别在于可容纳存储范围不同。
有 4 种 TEXT 类型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。对应的这 4 种 BLOB 类型,可存储的最大长度不同,可根据实际情况选择。

BLOB:
     1._BLOB和_text存储方式不同,_TEXT以文本方式存储,英文存储区分大小写,而_Blob是以二进制方式存储,不分大小写。
     2._BLOB存储的数据只能整体读出。
     3._TEXT可以指定字符集,_BLO不用指定字符集。
其他字符类型简单介绍

枚举类型与集合类型

字段的值只能在给定范围中选择,如单选框,多选框,如果你在应用程序或者前端不做选项限制,在MySQL的字段里面也能做限制
  enum 单选 只能在给定的范围内选一个值,如性别 sex 男male/女female
  set 多选 在给定的范围内可以选择一个或一个以上的值(爱好1,爱好2,爱好3...)

 枚举类型(enum)
            An ENUM column can have a maximum of 65,535 distinct elements. (The practical limit is less than 3000.)
            示例:
                CREATE TABLE shirts (
                    name VARCHAR(40),
                    size ENUM('x-small', 'small', 'medium', 'large', 'x-large')
                );
                INSERT INTO shirts (name, size) VALUES ('dress shirt','large'), ('t-shirt','medium'),('polo shirt','small');

  

          集合类型(set)
            A SET column can have a maximum of 64 distinct members.
            示例:
                CREATE TABLE myset (col SET('a', 'b', 'c', 'd'));
                INSERT INTO myset (col) VALUES ('a,d'), ('d,a'), ('a,d,a'), ('a,d,d'), ('d,a,d');
mysql> create table consumer( 
    -> name varchar(50),
    -> sex enum('male','female'),
    -> level enum('vip1','vip2','vip3','vip4','vip5'), #在指定范围内,多选一
    -> hobby set('play','music','read','study') #在指定范围内,多选多
    -> );

    mysql> insert into consumer values  
        -> ('xiaogui','male','vip5','read,study'),
        -> ('taibai','female','vip1','girl');

    mysql> select * from consumer;
    +------+--------+-------+------------+
    | name | sex    | level | hobby      |
    +------+--------+-------+------------+
    | xiaogui | male   | vip5  | read,study |
    | taibai | female | vip1  |            |
    +------+--------+-------+------------+
测试

6、表的完整性约束

PRIMARY KEY (PK)    标识该字段为该表的主键,可以唯一的标识记录
FOREIGN KEY (FK)    标识该字段为该表的外键
NOT NULL    标识该字段不能为空
UNIQUE KEY (UK)    标识该字段的值是唯一的
AUTO_INCREMENT    标识该字段的值自动增长(整数类型,而且为主键)
DEFAULT    为该字段设置默认值

UNSIGNED 无符号
ZEROFILL 使用0填充
约束条件分类

说明:

1. 是否允许为空,默认NULL,可设置NOT NULL,字段不允许为空,必须赋值
2. 字段是否有默认值,缺省的默认值是NULL,如果插入记录时不给字段赋值,此字段使用默认值
sex enum('male','female') not null default 'male'
age int unsigned NOT NULL default 20 必须为正值(无符号) 不允许为空 默认是20
3. 是否是key
主键 primary key
外键 foreign key
索引 (index,unique...)

not null与default

  是否可空,null表示空,非字符串
  not null - 不可空
  null - 可空

  

  默认值,创建列时可以指定默认值,当插入数据时如果未主动设置,则自动添加默认值
  create table tb1(
    nid int not null defalut 2,
    num int not null
  );

  先说一点:在我们插入数据的时候,可以这么写insert into tb1(nid,num) values(1,‘chao’);就是在插入输入的时候,指定字段插入数据,如果我在只给num插入值,可以这样写insert into tb1(num) values('chao');还可以插入数据的时候,指定插入数据字段的顺序:把nid和num换个位置,但是对应插入的值也要换位置。注意:即便是你只给一个字段传值了,那么也是生成一整条记录,这条记录的其他字段的值如果可以为空,那么他们就都是null空值,如果不能为空,就会报错。

==================not null====================
mysql> create table t1(id int); #id字段默认可以插入空
mysql> desc t1;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
mysql> insert into t1 values(); #可以插入空


mysql> create table t2(id int not null); #设置字段id不为空
mysql> desc t2;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO   |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
mysql> insert into t2 values(); #不能插入空
ERROR 1364 (HY000): Field 'id' doesn't have a default value



==================default====================
#设置id字段有默认值后,则无论id字段是null还是not null,都可以插入空,插入空默认填入default指定的默认值
mysql> create table t3(id int default 1);
mysql> alter table t3 modify id int not null default 1;



==================综合练习====================
mysql> create table student(
    -> name varchar(20) not null,
    -> age int(3) unsigned not null default 18,
    -> sex enum('male','female') default 'male',
    -> hobby set('play','study','read','music') default 'play,music'
    -> );
mysql> desc student;
+-------+------------------------------------+------+-----+------------+-------+
| Field | Type                               | Null | Key | Default    | Extra |
+-------+------------------------------------+------+-----+------------+-------+
| name  | varchar(20)                        | NO   |     | NULL       |       |
| age   | int(3) unsigned                    | NO   |     | 18         |       |
| sex   | enum('male','female')              | YES  |     | male       |       |
| hobby | set('play','study','read','music') | YES  |     | play,music |       |
+-------+------------------------------------+------+-----+------------+-------+
mysql> insert into student(name) values('chao');
mysql> select * from student;
+------+-----+------+------------+
| name | age | sex  | hobby      |
+------+-----+------+------------+
| chao|  18 | male | play,music |
+------+-----+------+------------+
not null和default练习

注意一点:如果是非严格模式,int类型不传值的话会默认为0,因为null不是int类型的,字段是int类型,所以他会自动将null变为0

unique

  独一无二,唯一属性:id,身份证号等

  是一种key,唯一键,是在数据类型之外的附加属性,还有加速查询的作用

============设置唯一约束 UNIQUE===============
方法一:
create table department1(
id int,
name varchar(20) unique,
comment varchar(100)
);


方法二:
create table department2(
id int,
name varchar(20),
comment varchar(100),
constraint uk_name unique(name)
);


mysql> insert into department1 values(1,'IT','技术');
Query OK, 1 row affected (0.00 sec)
mysql> insert into department1 values(1,'IT','技术');
ERROR 1062 (23000): Duplicate entry 'IT' for key 'name'
unique创建
create table service(
id int primary key auto_increment,
name varchar(20),
host varchar(15) not null,
port int not null,
unique(host,port) #联合唯一
);

mysql> insert into service values
    -> (1,'nginx','192.168.0.10',80),
    -> (2,'haproxy','192.168.0.20',80),
    -> (3,'mysql','192.168.0.30',3306)
    -> ;
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> insert into service(name,host,port) values('nginx','192.168.0.10',80);
ERROR 1062 (23000): Duplicate entry '192.168.0.10-80' for key 'host'
联合唯一

primary key

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

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

  

  一个表中可以:

    单列做主键
    多列做主键(复合主键或者叫做联合主键)

unique key和primary key都是MySQL的特殊类型,不仅仅是个字段约束条件,还称为索引,可以加快查询速度,这个索引功能我们后面再讲,现在只讲一下这些key作为约束条件的效果。

    关于主键的强调内容:
        1.一张表中必须有,并且只能由一个主键字段:innodb引擎下存储表数据的时候,会通过你的主键字段的数据来组织管理所有的数据,将数据做成一种树形结构的数据结构,帮你较少IO次数,提高获取定位数据、获取数据的速度,优化查询。
            解释:如果我们在一张表中没有设置primary key,那么mysql在创建表的时候,会按照顺序从上到下遍历你设置的字段,直到找到一个not null unique的字段,自动识别成主键pri,通过desc可以看到,这样是不是不好啊,所以我们在创建表的时候,要给他一个主键,让他优化的时候用,如果没有pri也没有not null unique字段,那么innodb引擎下的mysql被逼无奈,你没有设置主键字段,主键又有不为空且唯一的约束,又不能擅自给你的字段加上这些约束,那么没办法,它只能给你添加一个隐藏字段来帮你组织数据,如果是这样,你想想,主键是不是帮我们做优化查询用的啊,这个优化是我们可以通过主键来查询数据:例如:如果我们将id设置为主键,当我们查一个id为30的数据的时候,也就是select * from tb1 where id=30;这个查询语句的速度非常快,不需要遍历前面三十条数据,就好像我们使用的字典似的,找一个字,不需要一页一页的翻书,可以首先看目录,然后看在哪一节,然后看在哪一页,一步步的范围,然后很快就找到了,这就像我们说的mysql的索引(主键、唯一键)的工作方式,一步一步的缩小范围来查找,几步就搞定了,所以通过主键你能够快速的查询到你所需要的数据,所以,如果你的主键是mysql帮你加的隐藏的字段,你查询数据的时候,就不能将这个隐藏字段作为条件来查询数据了,就不能享受到优化后的查询速度了,对么
        
        2.一张表里面,通常都应该有一个id字段,而且通常把这个id字段作为主键,当然你非要让其他的字段作为主键也是可以的,看你自己的设计,创建表的时候,一般都会写create table t1(id int primary key);id int primary key这个东西在建表的时候直接就写上
关于主键的通俗解释和强调内容(重点*****)
mysql> create table t1(id int not null unique);
Query OK, 0 rows affected (0.02 sec)

mysql> desc t1;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO   | PRI | NULL    |       |
+-------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)
在没有设置主键的时候,not null+unique会被默认当成主键
============单列做主键===============
#方法一: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)
单列主键测试
联合主键
        和联合唯一是类似的,
        mysql> create table t10(
            ->id int,
            ->port int,
            ->primary key(id,port)
            -> );
        Query OK, 0 rows affected (0.45 sec)

        mysql> desc t10;
        +-------+---------+------+-----+---------+-------+
        | Field | Type    | Null | Key | Default | Extra |
        +-------+---------+------+-----+---------+-------+
        | id    | int(11) | NO   | PRI | 0       |       | 
        | port  | int(11) | NO   | PRI | 0       |       |
        +-------+---------+------+-----+---------+-------+
        2 rows in set (0.10 sec)
      
        看key,两个都写的是pri,两个联合起来作为主键,他们两个作为一个主键,不能再有其他的主键了,也就是在创建表的时候,只能出现一次primary key方法。
        有同学说,老师,我不写primary key行不,只写一个not null unique字段,当然行,但是我们应该这样做吗,是不是不应该啊,所以以后设置主键的时候,就使用primary key来指定
联合主键测试
==================多列做主键================
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    |       |
+--------------+-------------+------+-----+---------+-------+
3 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'
多列(联合)主键测试

auto_increment

  之前我们插入数据的时候,id也需要自己来写,是不是很麻烦啊,我们是不是想,只要有一条记录就直接插入进去啊,不需要考虑说,你现在存储到第多少条数据了,对不对,所以出现了一个叫做auto_increment的属性

  约束字段为自动增长,被约束的字段必须同时被key约束,也就是说只能给约束成key的字段加自增属性,默认起始位置为1,步长也为1.

#不指定id,则自动增长
create table student(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') default 'male'
);

mysql> desc student;
+-------+-----------------------+------+-----+---------+----------------+
| Field | Type                  | Null | Key | Default | Extra          |
+-------+-----------------------+------+-----+---------+----------------+
| id    | int(11)               | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)           | YES  |     | NULL    |                |
| sex   | enum('male','female') | YES  |     | male    |                |
+-------+-----------------------+------+-----+---------+----------------+
mysql> insert into student(name) values
    -> ('egon'),
    -> ('alex')
    -> ;

mysql> select * from student;
+----+------+------+
| id | name | sex  |
+----+------+------+
|  1 | egon | male |
|  2 | alex | male |
+----+------+------+


#也可以指定id
mysql> insert into student values(4,'asb','female');
Query OK, 1 row affected (0.00 sec)

mysql> insert into student values(7,'wsb','female');
Query OK, 1 row affected (0.00 sec)

mysql> select * from student;
+----+------+--------+
| id | name | sex    |
+----+------+--------+
|  1 | egon | male   |
|  2 | alex | male   |
|  4 | asb  | female |
|  7 | wsb  | female |
+----+------+--------+


#对于自增的字段,在用delete删除后,再插入值,该字段仍按照删除前的位置继续增长
mysql> delete from student;
Query OK, 4 rows affected (0.00 sec)

mysql> select * from student;
Empty set (0.00 sec)

mysql> insert into student(name) values('ysb');
mysql> select * from student;
+----+------+------+
| id | name | sex  |
+----+------+------+
|  8 | ysb  | male |
+----+------+------+

#应该用truncate清空表,比起delete一条一条地删除记录,truncate是直接清空表,在删除大表时用它
mysql> truncate student;
Query OK, 0 rows affected (0.01 sec)

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

mysql> select * from student;
+----+------+------+
| id | name | sex  |
+----+------+------+
|  1 | egon | male |
+----+------+------+
1 row in set (0.00 sec)
auto_increment测试
#在创建完表后,修改自增字段的起始值
mysql> create table student(
    -> id int primary key auto_increment,
    -> name varchar(20),
    -> sex enum('male','female') default 'male'
    -> );

mysql> alter table student auto_increment=3;

mysql> show create table student;
.......
ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

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

mysql> select * from student;
+----+------+------+
| id | name | sex  |
+----+------+------+
|  3 | egon | male |
+----+------+------+
row in set (0.00 sec)

mysql> show create table student;
.......
ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8


#也可以创建表时指定auto_increment的初始值,注意初始值的设置为表选项,应该放到括号外
create table student(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') default 'male'
)auto_increment=3;




#设置步长
sqlserver:自增步长
    基于表级别
    create table t1(
        id int。。。
    )engine=innodb,auto_increment=2 步长=2 default charset=utf8

mysql自增的步长:
    show session variables like 'auto_inc%';
    
    #基于会话级别
    set session auth_increment_increment=2 #修改会话级别的步长

    #基于全局级别的
    set global auth_increment_increment=2 #修改全局级别的步长(所有会话都生效)


#!!!注意了注意了注意了!!!
If the value of auto_increment_offset is greater than that of auto_increment_increment, the value of auto_increment_offset is ignored. 
翻译:如果auto_increment_offset的值大于auto_increment_increment的值,则auto_increment_offset的值会被忽略 ,这相当于第一步步子就迈大了,扯着了蛋
比如:设置auto_increment_offset=3,auto_increment_increment=2




mysql> set global auto_increment_increment=5;
Query OK, 0 rows affected (0.00 sec)

mysql> set global auto_increment_offset=3;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'auto_incre%'; #需要退出重新登录
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |
| auto_increment_offset    | 1     |
+--------------------------+-------+



create table student(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') default 'male'
);

mysql> insert into student(name) values('egon1'),('egon2'),('egon3');
mysql> select * from student;
+----+-------+------+
| id | name  | sex  |
+----+-------+------+
|  3 | egon1 | male |
|  8 | egon2 | male |
| 13 | egon3 | male |
+----+-------+------+
了解内容:步长:auto_increment_increment 起始偏移量:auto_increment_offset

foreign key

  一 快速理解foreign key(外键其实就是标明表和表之间的关系,表和表之间如果有关系的话就三种:一对一,多对一,多对多,我们挨个看看~)

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

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

    那这就体现出来了三个缺点:

      1.表的组织结构不清晰:员工的信息、部门的信息等等都掺在一张表里面。

      2.浪费空间,每一条信息都包含员工和部门,多个员工从属一个部门,也需要每个员工的信息里都包含着部门的信息,浪费硬盘空间。

      3.扩展性极差:如果想修改一个部门的信息,比如修改部门名称,那么这个包含员工和部门信息的表中的所有的包含这个部门信息的数据都需要进行修改,那么修改起来就非常麻烦,这是非常致命的缺点。

    解决方法:(画一个excel表格来表示一下效果~~)

      我们完全可以定义一个部门表,解耦和

      我们虽然将部门表提出来了,但是员工表本身是和部门有联系的,你光把部门信息提出来还是不够的,还需要建立关联

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

      

     在解释一下:数据要拆到不同表里面存着,你要站在两个表的角度来看两者之间的关系,你站在部门表的角度看,一个部门包含多个员工,站在员工表看,多个员工属于一个部门,以我们上课来举个例子看:现在的多个老师可以讲一个课程python,那么老师对于课程表来说就是多对一个关系,那这是不是就是最终关系呢,我们还需要站在课程表的角度来看,多个课程能不能被一个老师教啊,这个看业务场景,你看咱们学校就不行,讲python的只能讲python,但是我们上的小学,初中,高中是不是多个课程可以被一个老师教啊,所以从老男孩的业务来看,课程表对老师表是一对一的,即便是你多个老师可以讲这一门课程,但是这一门可能对应的那几个老师只能讲这一门,不能讲其他的课程,所以他们只是单纯的多对一的关系,多个老师对应一门课程,但是小学、初中、高中的业务,多个老师可以教一门课程,同样这多个老师每个老师又可以教多门课程,那么从课程表角度来看,多个课程也能从属一个老师,所以是多对多的关系:看下图

    

  二 一对多的关系  

    我们在看看员工和部门这个多对一的关系表:

    

    如果我们没有做强制的约束关系,那么在员工表里面那个部门id可以随便写,即便是部门表里面没有这个id号,它也是可以写的,但是这样写就错了,因为业务不允许,并且这个数据完全没用,根本就不存在这个部门,哪里来的这个部门的员工呢,对不对,所以要做一个硬性的关系,你员工里面的部门id一定要来自于部门表的id字段。怎么来做这个硬性关系呢,通过外键foreign key,怎么叫外键,就是跟外部的一个表进行关联,建立这种硬性的关系,就叫做外键,就像我们上面这两个表似的,左边的员工表有一个字段(部门id字段)来自于右边的部门表,那么我们就可以通过数据库在员工表的部门id字段加上一个foreign key,外键关联到右边部门表的id字段,这样就建立了这种硬性的关系了,之前我们是看着两张表之间有关系,但是没有做强制约束,还是两张普通的表,操作其中任何一个,另外一个也没问题,但是加上了这种强制关系之后,他们两个的操作也就都关联起来了,具体操作看下面的代码:

    

    部门表是被关联的表,员工表是关联表,也就是员工表要关联部门表,对吧,如果我们先创建员工表,在创建员工表的时候加外键关系,就会报错,看效果:

    

    所以我们应该先建立部门表,也就是被关联的表,因为关联表中的字段的数据是来根据被关联表的被关联字段的数据而来的。

     

    然后看一下表结构:

    

    表创建好了,如果我们直接给员工表插入几条数据,那么会报错,因为,你的部门还没有呢,你的员工表里面的那个dep_id外键字段的数据从何而来啊?看效果:

    

    然后我们先插入部门的数据,然后再插入员工的数据:

    

    然后查看一下数据:

    

    数据没问题了,但是你有没有发现一个问题,就是员工表的id从6开始的,因为我们前面插入了5条数据,失败了,虽然失败了,但是id自动增长了。

    所以有引出一个问题,如果想让id从头开始,我们可以把这些数据删掉,用delete的删除是没用的,需要用truncate来删除,这是清空表的意思。

    看一下delete:

     

    delete不是用来清空表的,是用来删除一些你想删除的符合某些条件的数据,一般用在delete from tb1 where id>20;这样的,如果要清空表,让id置零,使用truncate

    再看一下truncate:

    

    然后查看一下数据看看:

    

    ok,大家练习一下吧~~~~

   

    我们来看一下,如果对关联的表进行修改的话会有什么效果,首先我们先修改一下部门表的id字段中的某个数据,将id的值改一下

    

    报错了,那我们改一改员工表里面的外键字段dep_id,改它的值来试试:

    

    还是报错了!我靠,那我试试删除一下试试,解散一个部门,删除他的数据:

    

    报错了!不让你删除,因为你删除之后,员工表里面的之前属于这个部门的记录找不到对应的部门id了,就报错了

    那我删除一下员工表里面关于这个要被解散的部门的员工数据,按理说是不是应该没问题啊,来看看效果:

    

    删除成功了,完全没问题啊,那么关于这个部门的所有员工数据都被删除了,也就是说,你这个部门下面没有任何员工了,没有了限制了相当于,所以我们尝试一下看看现在能不能删除部门表里面的这个部门了

    

    ok~可以删除了

    虽然我们修改部门表或者员工表里面的部门id,但是我们可以删除,但是删除这个被关联表部门表的数据的时候由于有关联关系的存在,所以删除的时候也很麻烦,要先将关联数据删除,才能删除被关联的表的数据。

    刚才我们删除了教学部这个部门,当我们想解散这个部门的时候,首先想到的是什么,是不是我们的部门表,想直接操作部门表进行删除,对吧,想修改部门的id号,是不是首先想到的也是操作部门表进行修改,把部门的id修改了,但是我们由于关联关系的存在,不得不考虑关联表中的数据,对不对,所以操作就变得很麻烦了,有没有简单的方法呢?我们想做的是不是说,我想删除一个部门,直接删除部门表里面的数据就行了,是不是达到这个效果,删除一个部门的时候,与这个部门关联的所有的员工表的那些数据都跟着删除,或者我更新部门表中一个部门的id号,那么关联的员工表中的关联字段的部门id号跟着自动更新了,

     

  

    看一下解决办法:

    首先我们把之前的两个表删除了,能先删除部门表吗?如果删了部门表,你的员工表是不是找不到对应关系了,你说会不会报错啊,所以先删除员工表:

      1.先删除关联表,再删除被关联表,然后我们重新建立两个表,然后建表的时候说一下咱们的解决方案。

      

      2.重建表,我们现在要解决的问题是:我们要达到一个在做某个表(被关联表)更新或者删除操作的时候,关联表的数据同步的进行更新和删除的效果,所以我们在建表的时候,可以加上两个功能:同步更新和同步删除:看看如何实现:在建立关联关系的时候,加上这两句: on delete cascade和 on update cascade

        

      然后把我们之间的表和数据都插入进去:然后再进行更新删除操作:

        

      然后我们再直接删除部门表里面的数据的时候,你看看结果:

        

      成功了,并且员工表里面关联部门表id的数据也都删除了,是不是达到了我们刚才想要实现的效果呀

      下面我们来看一下更新操作,我们之前说更新一个部门的id号,注意一个问题昂,我更新部门的名称,你说有影响吗?肯定没有啊,因为我员工表并不是关联的部门的名称字段,而是关联的部门的id字段,你改部门名称没关系,我通过你的id照样找到你,但是你如果改了id号,那么我员工表里面的id号和你不匹配了,我就没法找到你,所有当你直接更新部门的id的时候,我就给你报错了,大哥,你想改的是关联字段啊,考虑一下关联表的数据们的感受行不行。我们来看一下加上 on update cascade之后的效果:

       

      将部门id为2的部门的id改成了200,完全ok,员工表里面之前关联id为2的部门的数据都改成了关联id为200的数据了。说明同步更新也是没问题的。

   我们总结一下foreign key的下面几个约束作用:

    1、先要建立被关联的表才能建立关联表

    2、在插入数据记录的时候,要先想被关联表中插入数据,才能往关联表里面插入数据

    3、更新或者删除数据的时候,都需要考虑关联表和被关联表的关系

      解决方案:

        a.删除表的时候,先删除关联表,再删除被关联表

        b.重建表的时候,在加外键关联的时候加上这两句:on delete cascade 和 on update cascade

表类型必须是innodb存储引擎,且被关联的字段,即references指定的另外一个表的字段,必须保证唯一
create table department(
id int primary key,
name varchar(20) not null
)engine=innodb;

#dpt_id外键,关联父表(department主键id),同步更新,同步删除
create table employee(
id int primary key,
name varchar(20) not null,
dpt_id int,
constraint fk_name foreign key(dpt_id) #这句话的意思是constraint 是声明我们要建立一个约束啦,fk_name是约束的名称,foreign key是约束的类型,整体的意思是,我要创建一个名为fk_name的外键关联啦,这个constraint就是一个声明的作用,在创建外键的时候不加constraint fk_name也是没问题的。先理解一下就行了,后面我们会细讲的。
references department(id)
on delete cascade
on update cascade 
)engine=innodb;


#先往父表department中插入记录
insert into department values
(1,'欧德博爱技术有限事业部'),
(2,'艾利克斯人力资源部'),
(3,'销售部');


#再往子表employee中插入记录
insert into employee values
(1,'chao',1),
(2,'alex1',2),
(3,'alex2',2),
(4,'alex3',2),
(5,'李坦克',3),
(6,'刘飞机',3),
(7,'张火箭',3),
(8,'林子弹',3),
(9,'加特林',3)
;


#删父表department,子表employee中对应的记录跟着删
mysql> delete from department where id=3;
mysql> select * from employee;
+----+-------+--------+
| id | name  | dpt_id |
+----+-------+--------+
|  1 | chao  |      1 |
|  2 | alex1 |      2 |
|  3 | alex2 |      2 |
|  4 | alex3 |      2 |
+----+-------+--------+


#更新父表department,子表employee中对应的记录跟着改
mysql> update department set id=22222 where id=2;
mysql> select * from employee;
+----+-------+--------+
| id | name  | dpt_id |
+----+-------+--------+
|  1 | chao  |      1 |
|  3 | alex2 |  22222 |
|  4 | alex3 |  22222 |
|  5 | alex1 |  22222 |
+----+-------+--------+
简单测试

一对多的内容大致就说完了,我们看一下多对多的关系

  三 多对多关系

     我们上面大致提了一下多对多的关系,下面我们通过一个例子来细讲一下,这个例子就用-->书和出版社的关系来看吧:

    

    上面是一对多没问题,我们再来看看书和作者的关系:

    

    一本书可以有多个作者,一个作者可不可以写多本书,两者之间是不是站在谁的角度去看都是一个一对多的关系啊,那这就是多对多的关系,那我们创建表的时候,需要将两个表都加一个foreign key的字段,但是你添加字段的时候,你想想,能直接给两个表都这一个foreign key字段吗,两个谁先创建,谁后创建,是不是都不行啊,两个表的创建是不是都依赖着另外一张表啊,所以我们之前的加外键字段的方式对于这种多对多的关系是不是就不好用啦,怎么办,我们需要通过第三张表来缓和一下两者的关系,通过第三张表来创建双方的关系

    我们先创建书表和作者表,然后创建第三张表,第三张表就需要有一个字段外键关联书表,还有一个字段外键关联作者表

    

    然后我们如果想查一下alex出了哪些书,你可以怎么查,想一下,首先在author作者表里面找一个alex的id是多少,alex的id为2,然后找一个第三张表里面author_id为2的数据中book的id,然后拿着这些book的id去book表里面找对应的book名称,你就能够知道alex这个作者出了哪几本书了,对不对,这就是一个多表查询的一个思路

    来我们创建一下试试看(学了foreign key,这个东西是不是很简单啊,两个foreign key嘛~~)

    

    

    建立前两张表,插入数据,建立第三张表

    然后给第三张表插入一些数据:

    

    查看一下数据:

    

    数据就创建好了,多对多就讲完了~~~~

  

  四 一对一关系

    我们来以咱们学校的学生来举例:

    最开始你只是一个客户,可能还处于咨询考虑的阶段,还没有转化为学生,也有的客户已经转换为学生了,说白了就是你交钱了,哈哈

    那我们来建两个表:客户表和学生表

    

    客户表里面存着客户的信息,学生表里面存着客户转换为学生之后的学生信息,那么这两个表是什么关系呢?你想一下,学生是不是从客户转换过来的,那么一个学生能对应多个用户的信息吗?当然是不能的,那么一个客户能对应多个学生的信息吗,当然也是不能的,那么他们两个就是一对一的关系,那这个关系该怎么建立呢?我们知道通过外键可以建立关系,如果在客户表里面加外键关联学生表的话,那说明你的学生表必须先被创建出来,这样肯定是不对的,因为你的客户表先有的,才能转换为学生,那如果在学生表加外键关联客户表的话,貌似是可以的,不过一个学生只对应一个客户,那么这个关系怎么加呢,外键我们知道是一对多的,那怎么搞?我们可以把这个关联字段设置成唯一的,不就可以了吗,我既和你有关联,我还不能重复,那就做到了我和你一对一的关联关系。

    

    

  表关系的总结  

分析步骤:
#1、先站在左表的角度去找
是否左表的多条记录可以对应右表的一条记录,如果是,则证明左表的一个字段foreign key 右表一个字段(通常是id)

#2、再站在右表的角度去找
是否右表的多条记录可以对应左表的一条记录,如果是,则证明右表的一个字段foreign key 左表一个字段(通常是id)

#3、总结:
#多对一:
如果只有步骤1成立,则是左表多对一右表
如果只有步骤2成立,则是右表多对一左表

#多对多
如果步骤1和2同时成立,则证明这两张表时一个双向的多对一,即多对多,需要定义一个这两张表的关系表来专门存放二者的关系

#一对一:
如果1和2都不成立,而是左表的一条记录唯一对应右表的一条记录,反之亦然。这种情况很简单,就是在左表foreign key右表的基础上,将左表的外键字段设置成unique即可
找表关系的步骤
#一对多或称为多对一
三张表:出版社,作者信息,书

一对多(或多对一):一个出版社可以出版多本书

关联方式:foreign key
一对多或多对一
=====================多对一=====================
create table press(
id int primary key auto_increment,
name varchar(20)
);

create table book(
id int primary key auto_increment,
name varchar(20),
press_id int not null,
foreign key(press_id) references press(id)
on delete cascade
on update cascade
);


insert into press(name) values
('北京工业地雷出版社'),
('人民音乐不好听出版社'),
('知识产权没有用出版社')
;

insert into book(name,press_id) values
('九阳神功',1),
('九阴真经',2),
('九阴白骨爪',2),
('独孤九剑',3),
('降龙十巴掌',2),
('葵花宝典',3)
一对多的简单示例
#多对多
三张表:出版社,作者信息,书

多对多:一个作者可以写多本书,一本书也可以有多个作者,双向的一对多,即多对多
  
关联方式:foreign key+一张新的表
多对多
=====================多对多=====================
create table author(
id int primary key auto_increment,
name varchar(20)
);


#这张表就存放作者表与书表的关系,即查询二者的关系查这表就可以了
create table author2book(
id int not null unique auto_increment,
author_id int not null,
book_id int not null,
constraint fk_author foreign key(author_id) references author(id)
on delete cascade
on update cascade,
constraint fk_book foreign key(book_id) references book(id)
on delete cascade
on update cascade,
primary key(author_id,book_id)
);


#插入四个作者,id依次排开
insert into author(name) values('egon'),('alex'),('yuanhao'),('wpq');

#每个作者与自己的代表作如下
1 egon: 
      1 九阳神功
      2 九阴真经
      3 九阴白骨爪
      4 独孤九剑
      5 降龙十巴掌
      6 葵花宝典


2 alex: 
      1 九阳神功
      6 葵花宝典

3 yuanhao:
      4 独孤九剑
      5 降龙十巴掌
      6 葵花宝典

4 wpq:
      1 九阳神功


insert into author2book(author_id,book_id) values
(1,1),
(1,2),
(1,3),
(1,4),
(1,5),
(1,6),
(2,1),
(2,6),
(3,4),
(3,5),
(3,6),
(4,1)
;
多对多简单示例

  中间那一张存放关系的表,对外关联的字段可以联合唯一

#一对一
两张表:学生表和客户表

一对一:一个学生是一个客户,一个客户有可能变成一个学校,即一对一的关系

关联方式:foreign key+unique
一对一
#一定是student来foreign key表customer,这样就保证了:
#1 学生一定是一个客户,
#2 客户不一定是学生,但有可能成为一个学生


create table customer(
id int primary key auto_increment,
name varchar(20) not null,
qq varchar(10) not null,
phone char(16) not null
);


create table student(
id int primary key auto_increment,
class_name varchar(20) not null,
customer_id int unique, #该字段一定要是唯一的
foreign key(customer_id) references customer(id) #外键的字段一定要保证unique
on delete cascade
on update cascade
);


#增加客户
insert into customer(name,qq,phone) values
('李飞机','31811231',13811341220),
('王大炮','123123123',15213146809),
('守榴弹','283818181',1867141331),
('吴坦克','283818181',1851143312),
('赢火箭','888818181',1861243314),
('战地雷','112312312',18811431230)
;


#增加学生
insert into student(class_name,customer_id) values
('脱产3班',3),
('周末19期',4),
('周末19期',5)
;
一对一简单示例
例一:一个用户只有一个博客

    用户表:
    id  name
    1    egon
    2    alex
    3    wupeiqi


    博客表   
           fk+unique
    id url name_id
    1  xxxx   1
    2  yyyy   3
    3  zzz    2



例二:一个管理员唯一对应一个用户
    用户表:
    id user  password
    1  egon    xxxx
    2  alex    yyyy

    管理员表:
       fk+unique
    id user_id password
    1   1      xxxxx
    2   2      yyyyy
一对一其他例子

了解:将来你们接触某一些大型项目的时候,尽量不要给表建立外键关系,因为外键直接在数据库级别就变成耦合的了,那么我们要拓展或者删除或者更改某些数据库或者数据表的时候,拓展起来就比较难,我们可以自己从自己的程序代码的逻辑层面上将这些关联关系建立好,有很多公司就是这么做的,利于拓展,如果我们加了很多的foreign key ,那么当你想删除一个表的时候,可能会牵一发而动全身,了解一下就可以了

   查看所有外键的名称的方法: select REFERENCED_TABLE_SCHEMA,REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME,table_name,CONSTRAINT_NAME from information_schema.key_column_usage;  #包含我们创建外键的时候,mysql帮我们自动生成的外键名称。

  外键这个key的名称我们可以通过constraint来指定:

  删除外键关联,添加外键字段并添加外键关联:

mysql> desc e3;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(11)  | NO   | PRI | NULL    | auto_increment |
| xx    | char(11) | YES  |     | NULL    |                |
| ee_id | int(11)  | YES  | MUL | NULL    |                |
+-------+----------+------+-----+---------+----------------+
3 rows in set (0.10 sec)
mysql> alter table e3 drop ee_id;  #直接删除外键字段是不可以的
ERROR 1553 (HY000): Cannot drop index 'ee_id': needed in a foreign key constraint
mysql> alter table e3 drop foreign key e3_ibfk_1; #通过上面的方法找到这个表的外键字段,然后先解除外键字段的关系,才能删除外键字段
Query OK, 0 rows affected (0.11 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> desc e3;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(11)  | NO   | PRI | NULL    | auto_increment |
| xx    | char(11) | YES  |     | NULL    |                |
| ee_id | int(11)  | YES  | MUL | NULL    |                |
+-------+----------+------+-----+---------+----------------+
3 rows in set (0.10 sec)
#解除了外键关系之后,是可以随意插入数据的,就没有了外键的约束
#但是表结构的key那一项里面还是显示MUL,不过没关系,已经没有外键约束的效果了,大家可以插入一条原来那个关联表的字段中不存在的数据来试一试,肯定是没问题的,我没有保存下来,就不给大家演示啦,然后然后我们就可以删除这个外键字段了
mysql> alter table e3 drop ee_id;
Query OK, 0 rows affected (0.65 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc e3;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(11)  | NO   | PRI | NULL    | auto_increment |
| xx    | char(11) | YES  |     | NULL    |                |
+-------+----------+------+-----+---------+----------------+
2 rows in set (0.10 sec)

#看添加外键字段和外键关联:
首先创建一个e2表,包含一个id字段,别忘了id字段最少也要是unique属性,primary key当然最好啦

  mysql> alter table e3 add ee_id int;
  Query OK, 0 rows affected (0.64 sec)
  Records: 0 Duplicates: 0 Warnings: 0

  mysql> alter table e3 add foreign key(ee_id) references e2(id);
  Query OK, 0 rows affected (0.83 sec)
  Records: 0 Duplicates: 0 Warnings: 0

  #添加关联删除和关联更新的操作:当删除主表数据的时候,从表中有关的数据都跟着删除,当主表的关系字段修改的时候,从表对应的关系字段的值也更着更新。

  alter table 从表 add foreign key(从表字段) references 主表(主表字段) on delete cascade on update cascade;

  #另外,能够作为主表(也就是多对一关系的那个一表的被关联的那个字段)的关系字段的约束最少要是唯一的unique属性。

外键约束有三种约束模式(都是针对父表的约束):

    模式一: district 严格约束(默认的 ),父表不能删除或者更新已经被子表数据引用的记录

    模式二:cascade 级联模式:父表的操作,对应的子表关联的数据也跟着操作 。

    模式三:set null:置空模式,父表操作之后,子表对应的数据(外键字段)也跟着被置空。

    通常的一个合理的约束模式是:删除的时候子表置空;更新的时候子表级联。

    指定模式的语法:foreign key(外键字段)references 父表(主键字段)on delete 模式 on update 模式;

    注意:删除置空的前提条件是 外键字段允许为空,不然外键会创建失败。

    外键虽然很强大,能够进行各种约束,但是外键的约束降低了数据的可控性和可拓展性。通常在实际开发时,很少使用外键来约束。

7、修改表 alter table

语法:
1. 修改表名
      ALTER TABLE 表名 
                          RENAME 新表名;

2. 增加字段
      ALTER TABLE 表名
                          ADD 字段名  数据类型 [完整性约束条件…], #注意这里可以通过逗号来分割,一下添加多个约束条件
                          ADD 字段名  数据类型 [完整性约束条件…];
      ALTER TABLE 表名
                          ADD 字段名  数据类型 [完整性约束条件…]  FIRST; #添加这个字段的时候,把它放到第一个字段位置去。
      ALTER TABLE 表名
                          ADD 字段名  数据类型 [完整性约束条件…]  AFTER 字段名;#after是放到后的这个字段的后面去了,我们通过一个first和一个after就可以将新添加的字段放到表的任意字段位置了。
                            
3. 删除字段
      ALTER TABLE 表名 
                          DROP 字段名;

4. 修改字段
      ALTER TABLE 表名 
                          MODIFY  字段名 数据类型 [完整性约束条件…];
      ALTER TABLE 表名 
                          CHANGE 旧字段名 新字段名 旧数据类型 [完整性约束条件…];  #change比modify还多了个改名字的功能,这一句是只改了一个字段名
      ALTER TABLE 表名 
                          CHANGE 旧字段名 新字段名 新数据类型 [完整性约束条件…];#这一句除了改了字段名,还改了数据类型、完整性约束等等的内容
语法

    给一个字段添加外键属性的语句:alter table 表2名 add foreign key(表2的一个字段) references 表1名(表1的一个字段);

    注意一点:在mysql里面表名是不区分大小写的,如果你将一个名为t1的(小写的t1)改名为一个T1(大写的T1),是完全没用的,因为在数据库里面表名都是小写的。

示例:
1. 修改存储引擎
mysql> alter table service 
    -> engine=innodb;

2. 添加字段
mysql> alter table student10
    -> add name varchar(20) not null,
    -> add age int(3) not null default 22;
    
mysql> alter table student10
    -> add stu_num varchar(10) not null after name;                //添加name字段之后

mysql> alter table student10                        
    -> add sex enum('male','female') default 'male' first;          //添加到最前面

3. 删除字段
mysql> alter table student10
    -> drop sex;

mysql> alter table service
    -> drop mac;

4. 修改字段类型modify
mysql> alter table student10
    -> modify age int(3);
mysql> alter table student10
    -> modify id int(11) not null primary key auto_increment;    //修改为主键

5. 增加约束(针对已有的主键增加auto_increment)
mysql> alter table student10 modify id int(11) not null primary key auto_increment;
ERROR 1068 (42000): Multiple primary key defined

mysql> alter table student10 modify id int(11) not null auto_increment;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

6. 对已经存在的表增加复合主键
mysql> alter table service2
    -> add primary key(host_ip,port);        

7. 增加主键
mysql> alter table student1
    -> modify name varchar(10) not null primary key;

8. 增加主键和自动增长
mysql> alter table student1
    -> modify id int not null primary key auto_increment;

9. 删除主键
a. 删除自增约束
mysql> alter table student10 modify id int(11) not null; 

b. 删除主键
mysql> alter table student10                                 
    -> drop primary key;
简单示例

     

8、复制表

     

    我们通过select查询出来的结果既有表结构又有表记录(数据),我们在重新创建一个和它一样的表的时候,之前用create还需要自己将表结构写好,然后把那些数据插入到新建的表中,很麻烦,那么我们就可以直接使用mysql提供的复制表的功能:(复制表用的很少昂,了解一下就行了)


    语法:复制表结构+记录 (key不会复制: 主键、外键和索引)
    mysql> create table new_service select * from service;#这句话的意思是你从service表里面查询出来的数据不要在屏幕上打印了,你直接给我的新表new_service

    我们自己写个例子:

      

       虽然我们不能复制key,但是我们可以给他加回去啊:alter table xxx

      

    只复制表结构,不要数据
    mysql> select * from service where 1=2; //条件为假,查不到任何记录,所以我们可以通过它来只复制表结构,看下面一句
    Empty set (0.00 sec)
    mysql> create table new1_service select * from service where 1=2;  #筛选数据的条件为假,那么只拿到了结构,并没有查询出任何的数据,所以做到了只复制表结构
    Query OK, 0 rows affected (0.00 sec)
    Records: 0 Duplicates: 0 Warnings: 0

    mysql> create table t4 like employees; #获取用like可以达到这个效果

猜你喜欢

转载自www.cnblogs.com/wangpanger/p/10301820.html