零基础学习MySql数据库—2

一、表的约束

真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。比如有一个字段是email,要求是唯一的。
表的约束很多,这里主要介绍如下几个,其余的以后讲解。null/not null,default, comment, zerofill,primary key,auto_increment,unique。

1.1 空属性
  • 两个值:null 和 not null
  • 数据库默认字段基本都是字段为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算。
mysql> select null;
+------+
| NULL |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

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

创建一个班级表,包含班级名和班级所在的教室,如果班级没有名字,你不知道你在哪个班级,如果教室名字可以为空,就不知道在哪上课。

mysql> create table myclass(
    -> class_name varchar(20) not null,
    -> class_room varchar(10) not null
    -> );
Query OK, 0 rows affected (0.06 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.01 sec)

插入数据,如果没有数据就会插入失败:

mysql> insert into myclass(class_name) values('class1'); 
ERROR 1364 (HY000): Field 'class_room' doesn't have a default value
1.2 默认值

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

mysql> create table tt12 (
    -> name varchar(20) not null,
    -> age tinyint unsigned default 0,
    -> gender char(2) default '男'
    -> );
Query OK, 0 rows affected (0.06 sec)

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

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

mysql> insert into tt12(name) value ('zhangsan');
Query OK, 1 row affected (0.01 sec)

mysql> select * from tt12;
+----------+------+--------+
| name     | age  | gender |
+----------+------+--------+
| zhangsan |    0 | 男     |
+----------+------+--------+
1 row in set (0.00 sec)

注意:set和enum不能设置默认值。

1.3 列描述

列描述:comment,没有实际含义,专门用来描述字段,会根据表创建语句保存,用来给程序员或DBA来进行了解。

mysql> create table tt13 (
    -> name varchar(20) not null comment '姓名',
    -> age tinyint unsigned default 0 comment '年龄',
    -> gender char(2) default '男' comment '性别'
    -> );
Query OK, 0 rows affected (0.08 sec)

通过的 desc 查看不到注释信息:
mysql> desc tt13;
+--------+---------------------+------+-----+---------+-------+
| Field  | Type                | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| name   | varchar(20)         | NO   |     | NULL    |       |
| age    | tinyint(3) unsigned | YES  |     | 0       |       |
| gender | char(2)             | YES  |     | 男      |       |
+--------+---------------------+------+-----+---------+-------+
3 rows in set (0.01 sec)

通过 show 查看:
mysql> show create table tt13\G
*************************** 1. row ***************************
       Table: tt13
Create Table: CREATE TABLE `tt13` (
  `name` varchar(20) NOT NULL COMMENT '姓名',
  `age` tinyint(3) unsigned DEFAULT '0' COMMENT '年龄',
  `gender` char(2) DEFAULT '男' COMMENT '性别'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
1.4 zerofill

刚开始学习数据库时,很多人对数字类型后面的长度很迷茫。通过 show 看看 tt3 表的建表语句:

mysql> show create table tt3\G
*************************** 1. row ***************************
       Table: tt3
Create Table: CREATE TABLE `tt3` (
  `a` int(10) unsigned DEFAULT NULL,
  `b` int(10) unsigned DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.01 sec)

可以看到int(10),这个代表什么意思呢?整型不是4字节码?这个10又代表什么呢?其实没有zerofill这个属性,括号内的数字是毫无意义的。a和b列就是前面插入的数据,如下:

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

但是对列添加了zerofill属性后,显示的结果就有所不同了。修改tt3表的属性:

mysql> alter table tt3 change a a int(5) unsigned zerofill;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

对a列添加了zerofill属性,再进行查找,返回如下结果:

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

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

mysql> select a, hex(a) from tt3;
+-------+--------+
| a     | hex(a) |
+-------+--------+
| 00001 | 1      |
+-------+--------+
1 row in set (0.01 sec)

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

1.5 主键

主键:primary key用来唯一的约束该字段里面的数据,不能重复,不能为空,主键所在的列是整数类型。
一张表中最多只能有一个主键。
创建表的时候直接在字段上指定主键:

mysql> create table tt14 (
    -> id int unsigned primary key comment '学号不能为空',
    -> name varchar(20) not null
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> desc tt14;
+-------+------------------+------+-----+---------+-------+
| 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)

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

mysql>  create table tt15 (
    ->     id int unsigned,
    ->     course char(10) comment '课程代码',
    ->     score tinyint unsigned default 60 comment '成绩',
    ->     primary key(id, course)  -- id和course为复合主键
    ->     );
Query OK, 0 rows affected (0.03 sec)

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

当表创建好以后,可以再次追加主键

alter table 表名add primary key(字段列表)

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

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

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

删除主键:
alter table 表名drop primary key;

mysql> alter table tt14 drop primary key;
Query OK, 1 row affected (0.06 sec)
Records: 1  Duplicates: 0  Warnings: 0

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

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

自增长的特点:

  • 任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)
  • 自增长字段必须是整数
  • 一张表最多只能有一个自增长

示例:

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

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

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

mysql> select * from tt16;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
+----+------+
2 rows in set (0.00 sec)
1.7 唯一键

一张表中有往往有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键:唯一键就可以解决表中有多个字段需要唯一性约束的问题。

  • 唯一键的本质和主键差不多,唯一键允许为空,而且可以多个为空,空字段不做唯一性比较。
mysql>  create table student (
    -> id char(10) unique comment '学号,不能重复,但可以为空',
    -> name varchar(10)
    -> );
Query OK, 0 rows affected (0.02 sec)

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

mysql> insert into student(id, name) values('01', 'bbb'); -- 唯一约束不能重复
ERROR 1062 (23000): Duplicate entry '01' for key 'id'
mysql> insert into student(id, name) 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)

二、表的增删改查(CRUD)详解

2.1 增加

语法:

insert into table_name[(column[,column...])] values (value [,value...]);

示例:
1.创建一张商品表:

mysql> create table goods(
    -> id int unsigned primary key,
    -> goods_name varchar(50) not null default'',
    -> price float not null default 0.0
    -> );
Query OK, 0 rows affected (0.03 sec)

2.插入两条记录:

mysql> insert into goods values(100, '牛排', 88.8);
Query OK, 1 row affected (0.01 sec)

mysql> insert into goods values(101, '披萨', 25.8);
Query OK, 1 row affected (0.00 sec)

mysql> select * from goods;
+-----+------------+-------+
| id  | goods_name | price |
+-----+------------+-------+
| 100 | 牛排       |  88.8 |
| 101 | 披萨       |  25.8 |
+-----+------------+-------+
2 rows in set (0.00 sec)

使用添加语句注意的细节:

  • 插入的数据应与字段的数据类型相同。比如,将‘abc’插入到id列就不行:
mysql> insert into goods values('abc', 'pizza', 72);
ERROR 1366 (HY000): Incorrect integer value: 'abc' for column 'id' at row 1
  • 数据的大小应在规定的范围内,例如:不能将一个长度为80的字符串插入到长度为40的列中。
mysql> create table tt17(name varchar(5));
Query OK, 0 rows affected (0.03 sec)

mysql> insert into tt17 values('abcdef');
ERROR 1406 (22001): Data too long for column 'name' at row 1
  • 在values中列出的数据位置必须与被加入的列位置相对应。
mysql> insert into goods values(200, 3.4, 'steak'); --价格和名字写反了
ERROR 1265 (01000): Data truncated for column 'price' at row 1
  • 字符和日期类型应该包含在单引号中。
mysql> insert into goods values(123, fish, 50); --字符串没有用单引号
ERROR 1054 (42S22): Unknown column 'fish' in 'field list'
  • 插入空值,不指定或 insert into table values(null)
  • insert into table values(),(),() 一次性添加多条记录
mysql> insert into goods values(1, 'aa', 3.3), (2, 'bb', 4.4),(3, 'cc', 5.5); -- 一次性添加三条记录
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from goods;
+-----+------------+-------+
| id  | goods_name | price |
+-----+------------+-------+
|   1 | aa         |   3.3 |
|   2 | bb         |   4.4 |
|   3 | cc         |   5.5 |
+-----+------------+-------+
3 rows in set (0.00 sec)
  • 如果给表中的所有字段添加数据,可以不写前面的字段名称
mysql> insert into goods values(4, 'apple', 3.5); -- 如果没有给出字段名称,values中必须给出所有的字段值
Query OK, 1 row affected (0.00 sec)
  • 如果你只给表的某几个字段赋值,则需要制定字段名
mysql> insert into goods(id, goods_name) values (5, 'mouse');
Query OK, 1 row affected (0.01 sec)
2.1.1 增加进阶

在数据插入的时候,假设主键对应的值已经存在:插入失败!

mysql> insert into goods values(101, 'ccc', 20.5);
ERROR 1062 (23000): Duplicate entry '101' for key 'PRIMARY'

当主键存在冲突的时候(duplicate key),可以选择性的进行处理:
1.更新操作:

insert into 表名(字段列表) values(值列表) on duplicate key update 字段=新值; 

mysql> insert into goods values(101, 'ccc', 20.5) on duplicate key update goods_name='ccc',
price=20.5;
Query OK, 2 rows affected (0.01 sec)

2.替换:主键如果没有冲突,就直接插入

replace into 表名(包含字段) values(值列表);

mysql> replace into goods values(100, 'huawei', 1999);
Query OK, 2 rows affected (0.01 sec)

mysql> select * from goods;
+-----+------------+-------+
| id  | goods_name | price |
+-----+------------+-------+
|   1 | aa         |   3.3 |
|   2 | bb         |   4.4 |
|   3 | cc         |   5.5 |
|   4 | apple      |   3.5 |
|   5 | mouse      |     0 |
| 100 | huawei     |  1999 |
| 101 | ccc        |  20.5 |
+-----+------------+-------+
7 rows in set (0.00 sec)
2.2 修改

更新表中的数据
语法:

update tbl_name set col_name1=expr1, [, col_name2=expr2 ...] [where conditon]

示例:将所有产品的价格修改为300

mysql> update goods set price=300;
Query OK, 7 rows affected (0.01 sec)
Rows matched: 7  Changed: 7  Warnings: 0

mysql> select * from goods;
+-----+------------+-------+
| id  | goods_name | price |
+-----+------------+-------+
|   1 | aa         |   300 |
|   2 | bb         |   300 |
|   3 | cc         |   300 |
|   4 | apple      |   300 |
|   5 | mouse      |   300 |
| 100 | huawei     |   300 |
| 101 | ccc        |   300 |
+-----+------------+-------+
7 rows in set (0.00 sec)

示例:将 id 为 100 的产品价格修改为2000:

mysql> update goods set price=2000 where id=100;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from goods where id=100;
+-----+------------+-------+
| id  | goods_name | price |
+-----+------------+-------+
| 100 | huawei     |  2000 |
+-----+------------+-------+
1 row in set (0.00 sec)

示例:将 id 为 101 的产品价格增加200:

mysql> update goods set price=price+200 where id=101;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from goods where id=101;
+-----+------------+-------+
| id  | goods_name | price |
+-----+------------+-------+
| 101 | ccc        |   500 |
+-----+------------+-------+
1 row in set (0.00 sec)

update 使用细节:

  • update 语法可以用心值更新原有表中的各列
  • set子句指示要修改哪些列和要给予哪些值
  • where子句指定应更新哪些行。如果没有where子句,则更新所有行
  • 如果需要更新多个字段,可以通过set 字段1=值1,字段2=值2…

更新还可以限制更新数量:

update 表名set 字段=值[where 条件] [limit 更新数量];

比如,goods表中有5条ccc产品。我们希望将前3条改成ddd:

mysql> select * from goods where goods_name='ccc';
+-----+------------+-------+
| id  | goods_name | price |
+-----+------------+-------+
| 101 | ccc        |   500 |
| 102 | ccc        |   999 |
| 103 | ccc        |   999 |
| 104 | ccc        |   999 |
| 105 | ccc        |   999 |
+-----+------------+-------+
5 rows in set (0.00 sec)

执行更新操作并查询结果:

mysql> update goods set goods_name='ddd' where goods_name='ccc' limit 3;
Query OK, 3 rows affected (0.01 sec)
Rows matched: 3  Changed: 3  Warnings: 0

mysql> select * from goods;
+-----+------------+-------+
| id  | goods_name | price |
+-----+------------+-------+
|   1 | aa         |   300 |
|   2 | bb         |   300 |
|   3 | cc         |   300 |
|   4 | apple      |   300 |
|   5 | mouse      |   300 |
| 100 | huawei     |  2000 |
| 101 | ddd        |   500 |
| 102 | ddd        |   999 |
| 103 | ddd        |   999 |
| 104 | ccc        |   999 |
| 105 | ccc        |   999 |
+-----+------------+-------+
11 rows in set (0.00 sec)
2.3 删除

删除表中的数据
语法:

delete from tbl_name [where condition]

示例:删除表中 id 为 101 的数据

mysql> delete from goods where id=101;
Query OK, 1 row affected (0.01 sec)

在练习删除时,可以复制一份表,避免数据删没了
1.复制表结构:

mysql> create table goods2 like goods;
Query OK, 0 rows affected (0.06 sec)

2.把 goods 表的数据复制到 goods2:

mysql> insert into goods2 select * from goods;
Query OK, 10 rows affected (0.01 sec)
Records: 10  Duplicates: 0  Warnings: 0

删除表中的所有记录:

mysql> delete from goods; --删除整个表的数据,但是表的结构还存在

使用truncate删除表中的记录:

mysql> truncate table goods; --这个指令也把整个表记录删除

上述两种删除整表的区别:

  • 效果一样,truncate速度快
  • delete可以带where条件,删除更加灵活
  • delete可以返回被删除的记录数,而truncate返回0
  • 推荐使用delete

delete使用细节:

  • 如果不适用where子句,将删除整个表中所有数据
  • delete语句不能删除某一列的值(可以用update置null)
  • 使用delete语句仅删除记录,不删除表本身(drop table)

猜你喜欢

转载自blog.csdn.net/yubujian_l/article/details/81429775