目录

  • 什么是数据库
  • 1.2 主流数据库
  • 基本使用
  • 服务器,数据库,表关系
  • 基础使用
  • 数据逻辑存储
  • MySQL架构
  • SQL分类
  • 存储引擎
  • 库的操作
  • 字符集和校验规则
    • 校验规则对数据库的影响(大小写)
  • 操纵数据库
  • 修改数据库
  • 表的操作
    • 创建表
    • 查看表结构
    • 修改表
    • 删除表
  • 数据类型
    • tinyint类型
    • bit类型
    • 小数类型
    • decimal
    • 字符串类型
      • char
      • varchar
      • char和varchar比较
      • 日期和时间类型
      • enum和set
      • find_in_set
  • 表的约束
    • 空属性
    • 默认值
    • 列描述
    • zerofill
    • 主键
      • 删除主键
      • 添加主键
      • 复合主键
    • 自增长
    • 唯一键
    • 外键
    • 综合案例
  • 表的增删改查
    • Create
    • 单行数据 + 全列插入
    • 多行数据 + 指定列插入
    • 插入否则更新
    • 替换
    • SELECT
      • 指定列查询,并为列信息取别名
      • 查询字段为表达式
      • DISTINCT结果去重
    • WHERE 条件
    • NULL 的查询
    • 结果排序
    • 筛选分页结果
    • Update
    • Delete
    • 截断表
    • 插入查询结果
    • 聚合函数
      • COUNT函数使用
      • sum求和计算
      • avg显示平均总分
      • max求较大值
      • min求较小值
    • group by
  • 函数
    • 日期函数
    • 字符串函数
    • 数学函数
    • 其它函数
  • 复合查询(重点)
    • 基本查询
    • 多表查询
    • 自连接
    • 子查询
      • 单行子查询
      • 多行子查询
      • 多列子查询
      • 在from子句中使用子查询
    • 合并查询
    • union all

什么是数据库

存储数据用文件就可以了,为什么还要弄个数据库?
文件保存数据有以下几个缺点:

  • 文件的安全性问题
  • 文件不利于数据查询和管理
  • 文件不利于存储海量数据
  • 文件在程序中控制不方便

数据库存储介质:

  1. 磁盘
  2. 内存

1.2 主流数据库

SQL Sever: 微软的产品,.Net程序员的最爱,中大型项目。
Oracle: 甲骨文产品,适合大型项目,复杂的业务逻辑,并发一般来说不如MySQL。

MySQL:世界上最受欢迎的数据库,属于甲骨文,并发性好,不适合做复杂的业务。主要用在电商,SNS,论坛。对简单的SQL处理效果好。

PostgreSQL :加州大学伯克利分校计算机系开发的关系型数据库,不管是私用,商用,还是学术研究使用,可以免费使用,修改和分发。

SQLite: 是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。

H2: 是一个用Java开发的嵌入式数据库,它本身只是一个类库,可以直接嵌入到应用项目中

基本使用

使用之前查看mysql服务端是否启动

查看mysql的客户端存放位置

[mzt@VM-16-4-centos /]$ which mysql
/usr/bin/mysql
[mzt@VM-16-4-centos /]$

连接服务器

mysql -h 127.0.0.1 -P 3306 -u root -p
//指明服务器ip地址 mysql端口号和用户进行登录


基本概念:
1、我们经常通过mysql客户端下达指令再让mysql服务端再到后端执行数据控制

2、mysql服务端默认使用的端口号是3306,所使用的协议是tcp协议

数据库的存放位置
vim /etc/my.cnf 可进入该配置文件

在这个默认存放位置下可以看到我们已有的数据库和表

服务器,数据库,表关系

所谓安装数据库服务器,只是在机器上安装了一个数据库管理系统程序,这个管理程序可以管理多个数据库,一般开发人员会针对每一个应用创建一个数据库。

为保存应用中实体的数据,一般会在数据库中创建多个表,以保存程序中实体的数据。数据库服务器、数据库和表的关系如下

基础使用

显示建立的数据库

show databases;

查看创建的表的信息


查看表结构


查看数据库信息

创建数据库

create database 数据库名

效果:

使用数据库

use  databasename   数据库名

清空屏幕

system clear

创建数据表

create table student(id int,name varchar(10),age int    //最后一个数据不用逗号隔开);  //分号结尾

插入数据

insert into student(id, name, age) values(1,'张三',18);

显示插入的信息

select * from student;

效果:

删除数据表

drop table 表名

数据逻辑存储

MySQL架构

MySQL 是一个可移植的数据库,几乎能在当前所有的操作系统上运行,如 Unix/Linux、Windows、Mac 和Solaris。各种系统在底层实现方面各有不同,但是 MySQL 基本上能保证在各个平台上的物理体系结构的一致性

SQL分类

DDL【data definition language】 数据定义语言,用来维护存储数据的结构代表指令: create, drop, alter

DML【data manipulation language】 数据操纵语言,用来对数据进行操作代表指令: insert,delete,update

DML中又单独分了一个DQL,数据查询语言,代表指令: select DCL【Data Control Language】 数据控制语言,主要负责权限管理和事务代表指令: grant,revoke,commit

存储引擎

存储引擎是:数据库管理系统如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。MySQL的核心就是插件式存储引擎,支持多种存储引擎。

查看存储引擎

show engines;
show engines \G;  // \G选项会以格式化输出

效果:

库的操作

语法:

CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [, create_specification] ...]
create_specification:
[DEFAULT] CHARACTER SET charset_name //字符编码
[DEFAULT] COLLATE collation_name   //检验格式

大写的表示关键字
[ ] 是可选项
CHARACTER SET: 指定数据库采用的字符集
COLLATE: 指定数据库字符集的校验规则
IF NOT EXISTS.

创建一个使用utf8字符集的 db2 数据库

create database code charset=utf8;
//设置数据库字符编码为utf8

效果:

创建一个使用utf字符集,并带校对规则的 db3 数据库

create database db3
charset=utf8  //编码格式
collate utf8_general_ci; //校验规则采用utf8

当然很明显在这个地方看不到他的校验规则,这里我们回到linux界面下查看mysql的文件

回到linux下可以看到code数据库的校验规则,这里博主是将mysql的默认存放位置放在/var/lib/mysql 下,读者也可以参考,

字符集和校验规则

查看系统默认字符集以及校验规则

show variables like 'character_set_database'; //模糊匹配
show variables like 'collation_database'; //模糊匹配

查看数据库支持的字符集

show charset;
// 字符集主要是控制用什么语言。比如utf8就可以使用中文。

查看数据库支持的字符集校验规则

show collation;

校验规则对数据库的影响(大小写)

不区分大小写

//创建不区分大小写的数据库
create database test1 collate utf8_general_ci;
//使用数据库
use test1;
//创建表
create table person(name varchar(20));
//向表中插入数据
insert into person values('a');
insert into person values('A');
insert into person values('b');
insert into person values('B');

查询结果

select * from person where name='a';

大小写a都显示了出来

区分大小写

//创建数据库,检验大小写
create database test2 collate utf8_bin;
//使用数据库
use test2;
//创建表
create table person(name varchar(20));
//插入数据
insert into person values('a');
insert into person values('A');
insert into person values('b');
insert into person values('B');

查询结果

select * from person where name='a';

区分大小写只会显示出小a

操纵数据库

查看数据库

show databases;

显示创建语句

show create database 数据库名;

效果:

说明:
MySQL 建议我们关键字使用大写,但是不是必须的。
数据库名字的反引号``,是为了防止使用的数据库名刚好是关键字
/*!40100 default… */ 这个不是注释,表示当前mysql版本大于4.01版本,就执行这句话

修改数据库

ALTER DATABASE db_name
[alter_spacification [,alter_spacification]...]
alter_spacification:
[DEFAULT] CHARACTER SET charset_name
[DEFAULT] COLLATE collation_name

说明:
对数据库的修改主要指的是修改数据库的字符集,校验规则
实例: 将 mytest 数据库字符集改成 gbk

表的操作

创建表

CREATE TABLE table_name ( field1 datatype,field2 datatype, field3 datatype
) character set 字符集 collate 校验规则 engine 存储引擎;

说明:
1、field 表示列名
2、datatype 表示列的类型
3、character set 字符集,如果没有指定字符集,则以所在数据库的字符集为准
4、collate 校验规则,如果没有指定校验规则,则以所在数据库的校验规则为准
5、默认的存储引擎是InnoDB

create table user(id int,name varchar(30) comment '用户名',password char(32) comment '32位密码的md5值',birthday date comment '生日')character set utf8 engine MyISAM;
// 设置存储引擎由原来的InnoDB变为MyISAM
// 设置字符编码为:utf8
// comment 做列信息描述

效果:

使用MyISAM做存储引擎会多创建3个文件.MYI后缀指支持索引,使用InnoDB做存储引擎只会产生2个文件

查看表结构

desc 表名

效果:

修改表

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

插入数据

insert into user values(10,'张三',md5('4572'),'2020-10-03');
insert into user values(10,'李四',md5('3372'),'2020-07-03');
insert into user values(10,'王五',md5('1372'),'2010-07-03');
insert into user values(10,'蝙蝠侠',md5('1302'),'2000-07-03');

password列使用了md5加密后的效果

修改表的结构

新建一列

alter table user add assert varchar(30) after id;
//新建一列assert 在id的后面

效果:

修改列信息

alter table user modify assert varchar(50);
//修改列名assert 的变长字符串为50大小,只修改空间,并不会添加内容

效果:

删除列

alter table user drop assert;
//删除刚刚创建的列assert
//注意:删除字段一定要小心,删除字段及其对应的列数据都没了

效果:

修改表名

alter table user rename to emp;
//将user表名修改为emp

效果:

修改列名并重新定义

alter table emp change name xm varchar(40);
//修改列名name,修改后为xm 重新定义类型为varchar(40)

效果:

总结修改表结构:

alter table 表名字 【add / modify / drop / rename / change】

删除表

drop table 表名

数据类型

数据类型分类

数值类型

tinyint类型

数值越界测试:

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+------+
| num  |
+------+
| 1    |
+------+1 row in set (0.00 sec)

说明:
在MySQL中,整型可以指定是有符号的和无符号的,默认是有符号的。可以通过UNSIGNED来说明某个字段是无符号的

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 1mysql> insert into tt2 values(255);
Query OK, 1 row affected (0.02 sec)
mysql> select * from tt2;
+------+
| num  |
+------+
| 255  |
+------+
1 row in set (0.00 sec)

注意:尽量不使用unsigned,对于int类型可能存放不下的数据,int unsigned同样可能存放不下,与其如此,还不如设计时,将int类型提升为bigint类型。

bit类型

基本语法:

bit[(M)] : 位字段类型。M表示每个值的位数,范围从1到64。
如果M被忽略,默认为1。
mysql> create table tt4 ( id int, a bit(8));
Query OK, 0 rows affected (0.01 sec)
mysql> insert into tt4 values(10, 10);
Query OK, 1 row affected (0.01 sec)mysql> select * from tt4;
//#发现很怪异的现象,a的数据10没有出现+------+------+
| id   | a    |
+------+------+
| 10   |      |
+------+------+1 row in set (0.00 sec)

bit使用的注意事项:
bit字段在显示时,是按照ASCII码对应的值显示

mysql> insert into tt4 values(65, 65);
mysql> select * from tt4;
+------+------+
| id   | a    |
+------+------+
| 10   |      |
| 65   | A    |
+------+------+

如果我们有这样的值,只存放0或1,这时可以定义bit(1)。这样可以节省空间

mysql> create table tt5(gender bit(1));
mysql> insert into tt5 values(0);
Query OK, 1 row affected (0.00 sec) //成功mysql> insert into tt5 values(1);
Query OK, 1 row affected (0.00 sec) //成功mysql> insert into tt5 values(2); //错误
//-- 当插入2时,已经越界了 ERROR 1406 (22001):
Data too long for column 'gender' at row 1

小数类型

float

float[(m, d)] [unsigned] //[ ]指选项
// M指定显示长度,d指定小数位数,占用空间4个字节

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

mysql> create table tt6(id int, salary float(4,2));
Query OK, 0 rows affected (0.01 sec)
mysql> insert into tt6 values(100, -99.99);
Query OK, 1 row affected (0.00 sec) mysql> insert into tt6 values(101, -99.991);
//#多的这一点被拿掉了 Query OK, 1 row affected (0.00 sec)
mysql> select * from tt6;
+------+--------+
| id   | salary |
+------+--------+
| 100  | -99.99 |
| 101  | -99.99 |
+------+--------+
2 rows in set (0.00 sec)

从结果来看 -99.991 末尾的小数已经被丢弃了,只保留了前四位

decimal

decimal(m, d) [unsigned]
//定点数m指定长度,d表示小数点的位数

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

decimal(5,2) unsigned 表示的范围 0 ~ 999.99
decimal和float很像,但是有区别:
float和decimal表示的精度不一样

mysql> create table tt8 ( id int, salary float(10,8), salary2 decimal(10,8)
); //插入同一个浮点数,查看最后在表中的存储
mysql> insert into tt8 values(100,23.12345612, 23.12345612);
Query OK, 1 row affected (0.00 sec)
mysql> select * from tt8;
+------+-------------+-------------+
| id   | salary      | salary2     |
+------+-------------+-------------+
| 100  | 23.12345695 | 23.12345612 |
//# 发现decimal的精度更准确,因此如果我们希望某个数据表示高精度,
//选择decimal

说明:float表示的精度大约是7位。
decimal整数最大位数m为65。支持小数最大位数d是30。如果d被省略,默认为0.如果m被省略,默认是10

建议:如果希望小数的精度高,推荐使用decimal

字符串类型

char

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

mysql> create table tt9(id int, name char(2));
Query OK, 0 rows affected (0.00 sec) mysql> insert into tt9 values(100, 'ab');
Query OK, 1 row affected (0.00 sec) mysql> insert into tt9 values(101, '中国');
Query OK, 1 row affected (0.00 sec)mysql> select * from tt9;
+------+--------+
| id   | name   |
+------+--------+
| 100  | ab     |
| 101  | 中国    |
+------+--------+

//我们的表是使用utf8的字符编码的,而一个中文所占用的字节是3
//即使这里插入的是一个中文,但是实际上的char(2)只是根据应用层面来考虑的,char(2) 表示可以存放两个字符,可以是字母或汉字,但是不能超过2个,char类型最多只能是255

错误示范:超出类型的最大值

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

度值可以为255

varchar

varchar(L): 可变长度字符串,L表示字符长度,最大长度65535个字节

mysql> create table tt10(id int ,name varchar(6));
//--表示这里可以存放6个字符
mysql> insert into tt10 values(100, 'hello');
mysql> insert into tt10 values(100, '我爱你,中国');
mysql> select * from tt10;+------+--------------------+
| id   | name               |
+------+--------------------+
| 100  | hello              |
| 100  | 我爱你,中国         |
+------+--------------------+

说明:
关于varchar(len),len到底是多大,这个len值,和表的编码密切相关:varchar长度可以指定为0到65535之间的值,但是有1 - 3 个字节用于记录数据大小,所以说有效字节数是65532。

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

mysql> create table tt11(name varchar(21845))charset=utf8;
//--验证了utf8确实是不能超过21844 ERROR 1118 (42000): Row size too large. The maximum row size for the used
table type, not counting BLOBs, is 65535. You have to
change some columns to TEXT or BLOBs //ok
mysql> create table tt11(name varchar(21844)) charset=utf8;
Query OK, 0 rows affected (0.01 sec)

char和varchar比较

  • 如何选择定长或变长字符串?
  • 如果数据确定长度都一样,就使用定长(char),比如:身份证,手机号,md5
  • 如果数据长度有变化,就使用变长(varchar), 比如:名字,地址,但是 - 你要保证最长的能存的进去。
  • 定长的磁盘空间比较浪费,但是效率高。
  • 变长的磁盘空间比较节省,但是效率低。
  • 定长的意义是,直接开辟好对应的空间
  • 变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少。

日期和时间类型

常用的日期有如下三个:

  • date :日期 ‘yyyy-mm-dd’ ,占用三字节
  • datetime 时间日期格式 ‘yyyy-mm-dd HH:ii:ss’ 表示范围从 1000 到 9999 ,占用八字节
  • timestamp :时间戳,从1970年开始的 yyyy-mm-d d HH:ii:ss 格式和 datetime 完全一致,占用四字节
create table birthday (t1 date, t2 datetime, t3 timestamp);

使用三种时间类型创建表,而如果是时间戳的话我们不需要指定插入一个数据,系统会根据当前时间自动填充这一信息

更新数据

update birthday set t1='2020-9-10';
//  update 表名 set 列名 = 具体时间

效果:

enum和set

语法:

  • enum:枚举,“单选”类型;

  • enum(‘选项1’,‘选项2’,‘选项3’,…);

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

  • set:集合,“多选”类型;

  • set(‘选项值1’,‘选项值2’,‘选项值3’, …);

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

  • 说明:不建议在添加枚举值,集合值的时候采用数字的方式,因为不利于阅读

案例:

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

mysql> create table Romance(-> name varchar(30),-> gender enum('男','女'),-> hobby set('游泳','武术','登山','谋略')-> );
Query OK, 0 rows affected (0.02 sec)mysql> desc Romance;
+--------+------------------------------------------+------+-----+---------+-------+
| Field  | Type                                     | Null | Key | Default | Extra |
+--------+------------------------------------------+------+-----+---------+-------+
| name   | varchar(30)                              | YES  |     | NULL    |       |
| gender | enum('男','女')                          | YES  |     | NULL    |       |
| hobby  | set('游泳','武术','登山','谋略')         | YES  |     | NULL    |       |
+--------+------------------------------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

插入数据

mysql> insert into Romance values('刘备','男','武术,登山');
Query OK, 1 row affected (0.00 sec)mysql> select * from Romance;
+--------+--------+---------------+
| name   | gender | hobby         |
+--------+--------+---------------+
| 刘备   | 男     | 武术,登山       |
+--------+--------+---------------+
1 row in set (0.00 sec)

查询

mysql> select name from Romance where gender='男';
+--------+
| name   |
+--------+
| 刘备   |
+--------+
1 row in set (0.00 sec)mysql> select name from Romance where hobby='武术,登山';
+--------+
| name   |
+--------+
| 刘备   |
+--------+
1 row in set (0.00 sec)

find_in_set

集合查询使用find_in_set函数:

find_in_set(sub,str_list) :如果 sub 在 str_list 中,则返回下标;如果不在,返回0; str_list 用逗号分隔的字符串。

mysql> select * from Romance;
+-----------+--------+-----------------------------+
| name      | gender | hobby                       |
+-----------+--------+-----------------------------+
| 刘备      | 男     | 武术,登山                     |
| 诸葛亮    | 男     | 谋略                          |
| 曹操      | 男     | 游泳,武术,登山,谋略             |
| 周瑜      | 男     | 武术,登山,谋略                 |
+-----------+--------+-----------------------------+
4 rows in set (0.00 sec)//将包含登山兴趣的用户显示出来
mysql> select * from Romance where find_in_set('登山',hobby);
+--------+--------+-----------------------------+
| name   | gender | hobby                       |
+--------+--------+-----------------------------+
| 刘备   | 男     | 武术,登山                     |
| 曹操   | 男     | 游泳,武术,登山,谋略            |
| 周瑜   | 男     | 武术,登山,谋略                |
+--------+--------+-----------------------------+
3 rows in set (0.00 sec)//而如果是用select 去查询的话,只会显示出只包含登山的信息
mysql> select * from Romance where hobby='登山';
+--------+--------+--------+
| name   | gender | hobby  |
+--------+--------+--------+
| 小乔   | 女     | 登山    |
+--------+--------+--------+
1 row in set (0.00 sec)

总结:
1、find_in_set函数会将所有包含相关信息的用户全部显示出来,而只使用where hobby=‘登山’ 语句只会将只有登山兴趣的用户显示出来

2、enum可以有多个选项,但是使用枚举类型只能做单项选择

3、set集合可以有多个选项,但是set集合可以做多选

表的约束

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

空属性

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

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

mysql> select null;
+------+
| NULL |
+------+
| NULL |
+------+
1 row in set (0.00 sec) //null数据并不参与运算
mysql> select 1+null;
+--------+
| 1+null |
+--------+
| NULL   |
+--------+
1 row in set (0.00 sec)

创建一个班级表,包含班级名和班级所在的教室。

站在正常的业务逻辑中:
1、如果班级没有名字,你不知道你在哪个班级
2、如果教室名字可以为空,就不知道在哪上课
所以我们在设计数据库表的时候,一定要在表中进行限制,满足上面条件的数据就不能插入到表中。这就是“约束”。

Database changed
mysql> create table class(-> class_name varchar(30) not null,-> class_room varchar(10) not null);
Query OK, 0 rows affected (0.02 sec)mysql> desc class;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| class_name | varchar(30) | NO   |     | NULL    |       |
| class_room | varchar(10) | NO   |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)//如果插入数据的时候漏掉一个就会报错,因为已经是非空的约束条件
mysql> insert into class values('04s1000');
ERROR 1136 (21S01): Column count doesn't match value
count at row 1

默认值

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

mysql> create table tmp(-> name varchar(10) not null,-> age tinyint unsigned default 20,-> sex char(2) default '男'-> );
Query OK, 0 rows affected (0.02 sec)mysql> desc tmp;
+-------+---------------------+------+-----+---------+-------+
| Field | Type                | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| name  | varchar(10)         | NO   |     | NULL    |       |
| age   | tinyint(3) unsigned | YES  |     | 20      |       |
| sex   | char(2)             | YES  |     | 男      |       |
+-------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

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

mysql> insert into tmp(name) values('霹雳火');
Query OK, 1 row affected (0.00 sec)//只指定了姓名信息其他信息均以缺省值填充
mysql> select * from tmp;
+-----------+------+------+
| name      | age  | sex  |
+-----------+------+------+
| 霹雳火    |   20 | 男   |
+-----------+------+------+
1 row in set (0.00 sec)

注意:只有设置了default的列,才可以在插入值的时候,对列进行省略

列描述

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

//创建表
mysql> create table user(-> name varchar(20) not null comment '姓名',-> age tinyint unsigned default 18 comment '年龄',-> sex char(2) default '男' comment '性别'-> );
Query OK, 0 rows affected (0.02 sec)//查看表结构
mysql> desc user;
+-------+---------------------+------+-----+---------+-------+
| Field | Type                | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| name  | varchar(20)         | NO   |     | NULL    |       |
| age   | tinyint(3) unsigned | YES  |     | 18      |       |
| sex   | char(2)             | YES  |     | 男      |       |
+-------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)//查看表的详细信息
mysql> show create table user;
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                         |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| user  | CREATE TABLE `user` (`name` varchar(20) NOT NULL COMMENT '姓名',`age` tinyint(3) unsigned DEFAULT '18' COMMENT '年龄',`sex` char(2) DEFAULT '男' COMMENT '性别'
) ENGINE=InnoDB DEFAULT CHARSET=utf8        |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

这里通过comment关键字可以让人清楚的知道这列信息的具体含义

zerofill

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

//建立表
mysql> create table tt(-> data1 int(10) unsigned default NULL,-> data2 int(10) unsigned default NULL-> );mysql> create table tt( data1 int(10) unsigned default NULL, data2 int(10) unsigned default NULL );
Query OK, 0 rows affected (0.02 sec)//查看表的信息
mysql> show create table tt;
+-------+-------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                              |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------+
| tt    | CREATE TABLE `tt` (`data1` int(10) unsigned DEFAULT NULL,`data2` int(10) unsigned DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

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

mysql> insert into tt values(1,2);
Query OK, 1 row affected (0.00 sec)mysql> select * from tt;
+-------+-------+
| data1 | data2 |
+-------+-------+
|     1 |     2 |
+-------+-------+
1 row in set (0.00 sec)

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

//修改tt表data1字段的属性
mysql> alter table tt change data1 data1 int(5) unsigned zerofill;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0//查看tt表
mysql> desc tt;
+-------+--------------------------+------+-----+---------+-------+
| Field | Type                     | Null | Key | Default | Extra |
+-------+--------------------------+------+-----+---------+-------+
| data1 | int(5) unsigned zerofill | YES  |     | NULL    |       |
| data2 | int(10) unsigned         | YES  |     | NULL    |       |
+-------+--------------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)//再插入数据
mysql> insert into tt values(2,3);
Query OK, 1 row affected (0.00 sec)
//此时查看的时候可以发现字段是占5个字符的,而data1被修改为
//zerofill属性后,如果插入值不够5个字符长度,那么缺少的字符个数
//就用0来补充
mysql> select * from tt;
+-------+-------+
| data1 | data2 |
+-------+-------+
| 00001 |     2 |
| 00002 |     3 |
+-------+-------+
2 rows in set (0.00 sec)

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

mysql> select data1,hex(data1) from tt;
+-------+------------+
| data1 | hex(data1) |
+-------+------------+
| 00001 | 1          |
| 00002 | 2          |
| 20000 | 4E20       |
+-------+------------+
3 rows in set (0.00 sec)

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

主键

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

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

//创建表并添加主键
mysql> create table tt4(-> id int(10) unsigned primary key comment '用户id',-> name varchar(10) not null comment '用户名'-> );
Query OK, 0 rows affected (0.02 sec)//查看表结构
mysql> desc tt4;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   | PRI | NULL    |       |
| name  | varchar(10)      | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

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

mysql> insert into tt4 values(1,'张三');
Query OK, 1 row affected (0.00 sec)
//插入重复值就会操作失败
mysql> insert into tt4 values(1,'李四');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
//查看数据
mysql> select * from tt4;
+----+--------+
| id | name   |
+----+--------+
|  1 | 张三   |
+----+--------+
1 row in set (0.00 sec)

删除主键

mysql> alter table tt4 drop primary key;
Query OK, 1 row affected (0.06 sec)
Records: 1  Duplicates: 0  Warnings: 0mysql> desc tt4;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   |     | NULL    |       |
| name  | varchar(10)      | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

添加主键

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

mysql> alter table tt4 add primary key(id);
Query OK, 0 rows affected (0.07 sec)
Records: 0  Duplicates: 0  Warnings: 0mysql> desc tt4;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | NO   | PRI | NULL    |       |
| name  | varchar(10)      | NO   |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

复合主键

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

mysql> create table tt5(-> id int unsigned comment '用户id',-> teacher varchar(30) comment '教师名' not null,-> score tinyint unsigned default 60 comment '成绩',-> primary key(id,teacher)-> );
Query OK, 0 rows affected (0.03 sec)//查看表结构,tt5表的复合主键是id和teacher的组合
mysql> desc tt5;
+---------+---------------------+------+-----+---------+-------+
| Field   | Type                | Null | Key | Default | Extra |
+---------+---------------------+------+-----+---------+-------+
| id      | int(10) unsigned    | NO   | PRI | NULL    |       |
| teacher | varchar(30)         | NO   | PRI | NULL    |       |
| score   | tinyint(3) unsigned | YES  |     | 60      |       |
+---------+---------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

插入信息的时候

mysql> insert into tt5 values(100,'mzt',80);
Query OK, 1 row affected (0.00 sec)mysql> insert into tt5 values(100,'mzt',90);
ERROR 1062 (23000): Duplicate entry '100-mzt' for key 'PRIMARY'

这里会有一个错误信息提示,意思是’100-mzt’是复合主键,不能跟主键信息重复

自增长

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

自增长的特点:

  • 1、任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)
  • 2、自增长字段必须是整数
  • 3、一张表最多只能有一个自增长
mysql> create table tt6( id int unsigned primary key auto_increment , name varchar(10) not null
);
Query OK, 0 rows affected (0.02 sec)mysql> desc tt6;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(10)      | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

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

mysql> insert into tt6(name)values('mzt');
Query OK, 1 row affected (0.00 sec)mysql> insert into tt6(name)values('mzt');
Query OK, 1 row affected (0.00 sec)mysql> insert into tt6(name)values('mzt');
Query OK, 1 row affected (0.00 sec)//插入数据后id会开始自增,并且是从1开始自增的
mysql> select * from tt6;
+----+------+
| id | name |
+----+------+
|  1 | mzt  |
|  2 | mzt  |
|  3 | mzt  |
+----+------+
3 rows in set (0.00 sec)//查看最近插入 AUTO_INCREMENT的值
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
|                3 |
+------------------+
1 row in set (0.00 sec)//这里可以通过查看表的详细信息可知AUTO_INCREMENT的值已经是4了
mysql> show create table tt6;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                    |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tt6   | CREATE TABLE `tt6` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`name` varchar(10) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

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

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

唯一键

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

2、唯一键的本质和主键差不多,唯一键允许为空,而且可以多个为空,空字段不做唯一性比较。

3、关于唯一键和主键的区别:
我们可以简单理解成,主键更多的是标识唯一性的。而唯一键更多的是保证在业务上,不要和别的信息出现重复。

假设一个场景比如在公司,我们需要一个员工管理系统,系统中有一个员工表,员工表中有两列信息,一个身份证号码,一个是员工工号, 我们可以选择身份号码作为主键。 而我们设计员工工号的时候,需要一种约束:而所有的员工工号都不能重复。 具体指的是在公司的业务上不能重复,我们设计表的时候,需要这个约束,那么就可以将员工工号设计成为唯一键。 一般而言,我们建议将主键设计成为和当前业务无关的字段,这样,当业务调整的时候,我们可以尽量不会对主键做过大的调 整。

create table tt7(id int unsigned primary key auto_increment comment '用户id',job varchar(10) unique comment '工号',name varchar(10) comment ‘名字’);mysql> desc tt7;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| job   | varchar(10)      | YES  |     | NULL    |                |
| name  | varchar(10)      | YES  |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

插入数据

//插入数据
mysql> insert into tt7 values(100,'0201','张三');
Query OK, 1 row affected (0.02 sec)//唯一约束不能重复
mysql> insert into tt7 values(100,'0201','李四');
ERROR 1062 (23000): Duplicate entry '100' for key 'PRIMARY'//查看数据,只有张三的信息被插入进去
mysql> select * from tt7;
+-----+------+--------+
| id  | job  | name   |
+-----+------+--------+
| 100 | 0201 | 张三   |
+-----+------+--------+
1 row in set (0.00 sec)

设置唯一约束条件的数据不能重复,但是这条数据可以为null

mysql> insert into tt7 values(101,NULL,'李四');
Query OK, 1 row affected (0.01 sec)//数据为NULL依然可以插入,成功显示
mysql> select * from tt7;
+-----+------+--------+
| id  | job  | name   |
+-----+------+--------+
| 100 | 0201 | 张三   |
| 101 | NULL | 李四   |
+-----+------+--------+
2 rows in set (0.00 sec)

外键

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

语法:

foreign key (字段名) references 主表(列)

创建主表

mysql> create table class(-> id int primary key comment '班级id',-> name varchar(30) not null comment'班级名字'-> );
Query OK, 0 rows affected (0.02 sec)mysql> desc class;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   | PRI | NULL    |       |
| name  | varchar(30) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

创建从表

mysql> create table student(-> id int primary key comment'学生id',-> name varchar(30) not null comment'学生名字',-> class_id int,-> foreign key(class_id) references class(id)-> );
Query OK, 0 rows affected (0.03 sec)mysql> desc student;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id       | int(11)     | NO   | PRI | NULL    |       |
| name     | varchar(30) | NO   |     | NULL    |       |
| class_id | int(11)     | YES  | MUL | NULL    |       |
+----------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

他们的关联关系是从表stu的class_id 与 主表id构成关联关系

mysql> insert into class values(10,'C++大佬班');
Query OK, 1 row affected (0.00 sec)mysql> insert into class values(20,'linux.大佬班');
Query OK, 1 row affected (0.01 sec)mysql> insert into student values(100,'本贾尼',10);
Query OK, 1 row affected (0.00 sec)mysql> insert into student values(200,'林纳斯',20);
Query OK, 1 row affected (0.00 sec)mysql> select * from student;
+-----+-----------+----------+
| id  | name      | class_id |
+-----+-----------+----------+
| 100 | 本贾尼    |       10 |
| 200 | 林纳斯    |       20 |
+-----+-----------+----------+
2 rows in set (0.00 sec)

而如果主键中不存在这样的信息,强行插入就会有报错警告

mysql> insert into student values(300,'张三',30);
ERROR 1062 (23000): Duplicate entry '300' for key 'PRIMARY'

但是插入null值又是可以的

mysql> insert into student values(300,'张三',NULL);
Query OK, 1 row affected (0.00 sec)mysql> select * from student;
+-----+-----------+----------+
| id  | name      | class_id |
+-----+-----------+----------+
| 100 | 本贾尼    |       10 |
| 200 | 林纳斯    |       20 |
| 300 | 张三      |     NULL |
+-----+-----------+----------+
3 rows in set (0.00 sec)

删除有主外键关系的表

//如果主表和从表已经建立了关联关系,此时直接去删除主表列是不行的
mysql> delete from class where id=20;
ERROR 1451 (23000): Cannot delete or update a
parent row: a foreign key constraint fails (`code`.
`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY
(`class_id`) REFERENCES `class` (`id`))//删除从表列信息class_id后,再去删除主表列信息,因为class_id
//是关联主表id的,为了保证数据的完整性必须删除从表的信息
//再去删除主表的信息,这样子才那保证表跟表是的结构是完全对照的
mysql> delete from student where class_id=20;
Query OK, 1 row affected (0.01 sec)
//删除成功
mysql> delete from class where id=20;
Query OK, 1 row affected (0.00 sec)mysql> select * from class;
+----+--------------+
| id | name         |
+----+--------------+
| 10 | C++大佬班    |
+----+--------------+
1 row in set (0.00 sec)

综合案例

1、有一个商店的数据,记录客户及购物情况,有以下三个表组成:
商品goods(商品编号goods_id,商品名goods_name, 单价unitprice, 商品类别category, 供应商provider)

2、客户customer(客户号customer_id,姓名name,住址address,邮箱email,性别sex,身份证card_id)

3、购买purchase(购买订单号order_id,客户号customer_id,商品号goods_id,购买数量nums)
要求:

  • 每个表的主外键
  • 客户的姓名不能为空值
  • 邮箱不能重复
  • 客户的性别(男,女)
mysql> create table goods(-> goods_id int primary key auto_increment comment '商品编号',-> goods_name varchar(32) not null comment '商品名称',-> unitprice int not null default 0 comment '单价,单位分',-> category varchar(12) comment '商品分类',-> provider varchar(64) not null comment '供商品名称'-> );
Query OK, 0 rows affected (0.02 sec)mysql> create table customer(-> customer_id int primary key auto_increment comment '客户编号',-> name varchar(30) not null comment '客户姓名',-> address varchar(256) comment '客户地址',-> email varchar(64) unique key comment '电子邮箱',-> sex enum('男','女') not null comment '性别',-> card_id char(18) unique key comment '身份证'-> );
Query OK, 0 rows affected (0.04 sec)mysql> create table purchase(-> order_id int primary key auto_increment comment '订单号',-> customer_id int comment '客户编号',-> goods_id int comment '商品编号',-> nums int default 0 comment '购买数量',-> foreign key (customer_id) references customer(customer_id),-> foreign key (goods_id) references goods(goods_id)-> );
Query OK, 0 rows affected (0.03 sec)mysql> desc goods;
+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| goods_id   | int(11)     | NO   | PRI | NULL    | auto_increment |
| goods_name | varchar(32) | NO   |     | NULL    |                |
| unitprice  | int(11)     | NO   |     | 0       |                |
| category   | varchar(12) | YES  |     | NULL    |                |
| provider   | varchar(64) | NO   |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)mysql> desc customer;
+-------------+-------------------+------+-----+---------+----------------+
| Field       | Type              | Null | Key | Default | Extra          |
+-------------+-------------------+------+-----+---------+----------------+
| customer_id | int(11)           | NO   | PRI | NULL    | auto_increment |
| name        | varchar(30)       | NO   |     | NULL    |                |
| address     | varchar(256)      | YES  |     | NULL    |                |
| email       | varchar(64)       | YES  | UNI | NULL    |                |
| sex         | enum('男','女')   | NO   |     | NULL    |                |
| card_id     | char(18)          | YES  | UNI | NULL    |                |
+-------------+-------------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)mysql> desc purchase;
+-------------+---------+------+-----+---------+----------------+
| Field       | Type    | Null | Key | Default | Extra          |
+-------------+---------+------+-----+---------+----------------+
| order_id    | int(11) | NO   | PRI | NULL    | auto_increment |
| customer_id | int(11) | YES  | MUL | NULL    |                |
| goods_id    | int(11) | YES  | MUL | NULL    |                |
| nums        | int(11) | YES  |     | 0       |                |
+-------------+---------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

表的增删改查

Create(创建), Retrieve(读取),Update(更新),Delete(删除)

Create

Database changed
mysql> create table student(-> id int unsigned primary key auto_increment ,-> sn int not null unique key comment '学号',-> name varchar(20) not null ,-> qq varchar(20) unique key -> );

单行数据 + 全列插入

mysql> desc students;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| sn    | int(11)          | NO   | UNI | NULL    |                |
| name  | varchar(20)      | NO   |     | NULL    |                |
| qq    | varchar(20)      | YES  | UNI | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)mysql> insert into students values(100,10000,'张三','447');
Query OK, 1 row affected (0.01 sec)mysql> select * from students;
+-----+-------+--------+------+
| id  | sn    | name   | qq   |
+-----+-------+--------+------+
| 100 | 10000 | 张三   | 447  |
+-----+-------+--------+------+
1 row in set (0.00 sec)

多行数据 + 指定列插入

mysql> insert into students (id,sn,name ,qq)values(102,10010,'李四','5454548@qq.com'),(103,0544,'王五','545646@qq.com');mysql> select * from students;
+-----+-------+--------+----------------+
| id  | sn    | name   | qq             |
+-----+-------+--------+----------------+
| 100 | 10000 | 张三   | 447            |
| 101 |  1000 | 李四   | 5454@qq.com    |
| 102 | 10010 | 李四   | 5454548@qq.com |
| 103 |   544 | 王五   | 545646@qq.com  |
+-----+-------+--------+----------------+
4 rows in set (0.00 sec)

插入否则更新

由于 主键 或者 唯一键 对应的值已经存在而导致插入失败

//主键的信息已经存在,再次插入就会报错误信息
mysql> insert into students values(100,1007,'王二','5454@qq.com');
ERROR 1062 (23000): Duplicate entry '100' for key 'PRIMARY'//唯一键的信息已经存在,再次插入就会报错误信息
mysql> select * from students;
+-----+-------+--------+----------------+
| id  | sn    | name   | qq             |
+-----+-------+--------+----------------+
| 100 | 10000 | 张三   | 447            |
| 101 |  1000 | 李四   | 5454@qq.com    |
| 102 | 10010 | 李四   | 5454548@qq.com |
| 103 |   544 | 王五   | 545646@qq.com  |
+-----+-------+--------+----------------+
4 rows in set (0.00 sec)mysql> insert into student values(104,4000,'赵六','545646@qq.com');
ERROR 1136 (21S01): Column count doesn't match value count at row 1

邮箱并不会存在是一样的情况,所以会出现冲突

可以选择性的进行同步更新操作语法,即使信息冲突也能成功插入
语法

INSERT ... ON DUPLICATE KEY UPDATE
column = value [, column = value] ...

举例:

mysql> select * from students;
+-----+-------+--------+----------------+
| id  | sn    | name   | qq             |
+-----+-------+--------+----------------+
| 100 | 10000 | 张三   | 447            |
| 101 |  1000 | 李四   | 5454@qq.com    |
| 102 | 10010 | 李四   | 5454548@qq.com |
| 103 |   544 | 王五   | 545646@qq.com  |
+-----+-------+--------+----------------+
4 rows in set (0.00 sec)//如果想要插入的信息已经存在,那么就会被
//替换成后面的参数信息那一部分
mysql> INSERT INTO students (id, sn, name) VALUES (100,
10010, '唐大师') ON DUPLICATE KEY UPDATE sn = 10011,
name = '.大师';Query OK, 2 rows affected (0.01 sec)mysql> select * from students;
+-----+-------+-----------+----------------+
| id  | sn    | name      | qq             |
+-----+-------+-----------+----------------+
| 100 | 10011 | 唐大师    | 447            |
| 101 |  1000 | 李四      | 5454@qq.com    |
| 102 | 10010 | 李四      | 5454548@qq.com |
| 103 |   544 | 王五      | 545646@qq.com  |
+-----+-------+-----------+----------------+
4 rows in set (0.00 sec)

替换

1、主键或者唯一键没有冲突,就插入数据
2、如果主键和唯一键的信息相同,那么就删除该行数据,重新插入一条新的数据

语法:

REPLACE INTO students (sn, name) VALUES (val1,val2....);

原表:

mysql> select * from students;
+-----+-------+-----------+----------------+
| id  | sn    | name      | qq             |
+-----+-------+-----------+----------------+
| 100 | 10011 | 唐大师    | 447            |
| 101 |  1000 | 李四      | 5454@qq.com    |
| 102 | 10010 | 李四      | 5454548@qq.com |
| 103 |   544 | 王五      | 545646@qq.com  |
+-----+-------+-----------+----------------+
4 rows in set (0.00 sec)

使用replace后,我们在插入数据的时候,这条消息会和第一行数据发生冲突,这时候就会将第一行数据给删除,然后再表中尾插一条新的数据

replace into students(id,sn,name,qq)values(100,10011,'三藏','447');
Query OK, 2 rows affected (0.01 sec)

插入后显示

//原表的第一天数据已经被删除,此后在后面又插入了一条数据
mysql> select * from students;
+-----+-------+--------+----------------+
| id  | sn    | name   | qq             |
+-----+-------+--------+----------------+
| 101 |  1000 | 李四   | 5454@qq.com    |
| 102 | 10010 | 李四   | 5454548@qq.com |
| 103 |   544 | 王五   | 545646@qq.com  |
| 200 | 10011 | 三藏   | 447            |
+-----+-------+--------+----------------+
4 rows in set (0.00 sec)

SELECT

创建表并插入数据

mysql> create table student1(-> id int primary key auto_increment ,-> name varchar(20) not null comment '学生.姓名',-> chinese float default 0.0 comment '语文成绩',-> math float default 0.0 comment '数学成绩',-> english float default 0.0 comment '英文成绩'-> );mysql> select * from student1;
+----+-----------+---------+------+---------+
| id | name      | chinese | math | english |
+----+-----------+---------+------+---------+
|  1 | 小明      |      68 |   88 |      50 |
|  2 | 小红      |      66 |   98 |      70 |
|  3 | 小王      |      66 |   98 |      60 |
|  4 | 莫扎特    |     100 |  100 |     100 |
|  5 | 王五      |      10 |   10 |      10 |
|  6 | 张三      |      66 |   66 |      66 |
+----+-----------+---------+------+---------+
6 rows in set (0.00 sec)

指定列查询,并为列信息取别名

mysql> select name '姓名',chinese '语文',math '数学',english '英语' from student1;
+-----------+--------+--------+--------+
| 姓名      | 语文   | 数学   | 英语   |
+-----------+--------+--------+--------+
| 小明      |     68 |     88 |     50 |
| 小红      |     66 |     98 |     70 |
| 小王      |     66 |     98 |     60 |
| 莫扎特    |    100 |    100 |    100 |
| 王五      |     10 |     10 |     10 |
| 张三      |     66 |     66 |     66 |
+-----------+--------+--------+--------+
6 rows in set (0.00 sec)

查询字段为表达式

mysql> select name '姓名',id '用户id', 100 '测试' from student1;
+-----------+----------+--------+
| 姓名      | 用户id   | 测试   |
+-----------+----------+--------+
| 小明      |        1 |    100 |
| 小红      |        2 |    100 |
| 小王      |        3 |    100 |
| 莫扎特    |        4 |    100 |
| 王五      |        5 |    100 |
| 张三      |        6 |    100 |
+-----------+----------+--------+
6 rows in set (0.00 sec)

可以在select语句后面加一个表达式,这里在显示的时候会新增一列信息出来,这里取别名为测试

如果想要在查询他们分数的同时随便把总分也给计算完,可以在查询字段的时候选择表达式

mysql> select name '姓名',chinese '语文',math '数学'
,english '英语',chinese+math+english '总分' from student1;
+-----------+--------+--------+--------+--------+
| 姓名      | 语文   | 数学   | 英语   | 总分   |
+-----------+--------+--------+--------+--------+
| 小明      |     68 |     88 |     50 |    206 |
| 小红      |     66 |     98 |     70 |    234 |
| 小王      |     66 |     98 |     60 |    224 |
| 莫扎特    |    100 |    100 |    100 |    300 |
| 王五      |     10 |     10 |     10 |     30 |
| 张三      |     66 |     66 |     66 |    198 |
+-----------+--------+--------+--------+--------+
6 rows in set (0.00 sec)

查询的时候指定字段表达式会将计算结果显示出来,通过这里计算的总分就可以看出

DISTINCT结果去重

mysql> select math from student1;
+------+
| math |
+------+
|   88 |
|   98 |
|   98 |
|  100 |
|   10 |
|   66 |
|   66 |
+------+
7 rows in set (0.00 sec)mysql> select distinct math from student1;
+------+
| math |
+------+
|   88 |
|   98 |
|  100 |
|   10 |
|   66 |
+------+
5 rows in set (0.00 sec)

通过查询的结果可以看出重复的值已经被去除了,原本有两个66,现在只剩一个了

WHERE 条件

比较运算符:

运算符 说明
>, >=, <, <= 大于,大于等于,小于,小于等于
= 等于,NULL 不安全,例如 NULL = NULL 的结果是 NULL
<=> 等于,NULL 安全,例如 NULL <=> NULL 的结果是 TRUE(1)
!=, <> 不等于
BETWEEN a0 AND a1 范围匹配,[a0, a1],如果 a0 <= value <= a1,返回 TRUE(1)
IN (option, …) 如果是 option 中的任意一个,返回 TRUE(1)
IS NULL 是 NULL
IS NOT NULL 不是 NULL
LIKE 模糊匹配。% 表示任意多个(包括 0 个)任意字符;_ 表示任意一个字符

逻辑运算符:

运算符 说明
AND 多个条件必须都为 TRUE(1),结果才是 TRUE(1)
OR 任意一个条件为 TRUE(1), 结果为 TRUE(1)
NOT 条件为 TRUE(1),结果为 FALSE(0)

案例:
找出英语不及格的同学及英语成绩

mysql> select name,english from student1 where english < 60;
+--------+---------+
| name   | english |
+--------+---------+
| 小明   |      50 |
| 王五   |      10 |
+--------+---------+
2 rows in set (0.00 sec)

语文成绩在 [80, 90] 分的同学及语文成绩

mysql> select * from student1;
+----+-----------+---------+------+---------+
| id | name      | chinese | math | english |
+----+-----------+---------+------+---------+
|  1 | 小明      |      68 |   88 |      50 |
|  2 | 小红      |      66 |   98 |      70 |
|  3 | 小王      |      66 |   98 |      60 |
|  4 | 莫扎特    |     100 |  100 |     100 |
|  5 | 王五      |      10 |   10 |      10 |
|  6 | 张三      |      66 |   66 |      66 |
|  7 | 李四      |      66 |   66 |      66 |
|  8 | 小张      |      88 |   32 |      33 |
+----+-----------+---------+------+---------+
8 rows in set (0.00 sec)//使用and进行条件链接
mysql> select name,chinese from student1 where chinese >= 80 and chinese <= 90 ;
+--------+---------+
| name   | chinese |
+--------+---------+
| 小张   |      88 |
+--------+---------+
1 row in set (0.00 sec)

使用between 用作条件判断

mysql> select name,chinese from student1 where chinese between 80 and 90;//-- 使用 BETWEEN ... AND ... 条件
+--------+---------+
| name   | chinese |
+--------+---------+
| 小张   |      88 |
+--------+---------+
1 row in set (0.00 sec)

数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩

mysql> select name,math from student1 where (math=58 or math=59 or math=98 or math=99);//-- 使用 OR 进行条件连接
+--------+------+
| name   | math |
+--------+------+
| 小红   |   98 |
| 小王   |   98 |
+--------+------+
2 rows in set (0.00 sec)

使用 IN 条件

mysql> select name,math from student1 where math in(58,59,98,99);
+--------+------+
| name   | math |
+--------+------+
| 小红   |   98 |
| 小王   |   98 |
+--------+------+
2 rows in set (0.00 sec)

姓张的同学及莫同学

mysql> select name from student1 where name like '_张';
+--------+
| name   |
+--------+
| 小张   |
+--------+
1 row in set (0.00 sec)mysql> select name from student1 where name like '莫%';
+-----------+
| name      |
+-----------+
| 莫扎特    |
+-----------+
1 row in set (0.00 sec)

语文成绩好于或等于英语成绩的同学

mysql> select name,chinese,math from student1 where chinese >= math;
+-----------+---------+------+
| name      | chinese | math |
+-----------+---------+------+
| 莫扎特    |     100 |  100 |
| 王五      |      10 |   10 |
| 张三      |      66 |   66 |
| 李四      |      66 |   66 |
| 小张      |      88 |   32 |
+-----------+---------+------+
5 rows in set (0.00 sec)

总分在 200 分以下的同学

mysql> select name,chinese,math,english,
math+chinese+english '总分'
from student1 where chinese+math+english < 200;+--------+---------+------+---------+--------+
| name   | chinese | math | english | 总分   |
+--------+---------+------+---------+--------+
| 王五   |      10 |   10 |      10 |     30 |
| 张三   |      66 |   66 |      66 |    198 |
| 李四   |      66 |   66 |      66 |    198 |
| 小张   |      88 |   32 |      33 |    153 |
+--------+---------+------+---------+--------+
4 rows in set (0.00 sec)

注意:
别名不能在where条件中使用,否则会弹出错误信息

mysql> select name,math,english,chinese,math+english+chinese total from student1 where toal < 200;
ERROR 1054 (42S22): Unknown column 'toal' in 'where clause'

语文成绩 > 80 并且不姓张的同学

mysql> select name,chinese from student1 where (chinese > 80 and name not like '%张');
+-----------+---------+
| name      | chinese |
+-----------+---------+
| 莫扎特    |     100 |
+-----------+---------+
1 row in set (0.00 sec)

查找小张同学,否则要求总成绩 > 200 并且 语文成绩 < 数学成绩 并且 英语成绩 > 80

mysql> select name,math,chinese,english,math+english+chinese
'总分' from student1 where name like '%张' or
(math+englissh+chinese>200
+--------+------+---------+---------+--------+
| name   | math | chinese | english | 总分   |
+--------+------+---------+---------+--------+
| 小张   |   32 |      88 |      33 |    153 |
+--------+------+---------+---------+--------+
1 row in set (0.00 sec)

NULL 的查询

//查询为NULL
mysql> select name,qq from student1 where qq is null;
+-----------+------+
| name      | qq   |
+-----------+------+
| 小明      | NULL |
| 小红      | NULL |
| 小王      | NULL |
| 莫扎特    | NULL |
| 王五      | NULL |
| 张三      | NULL |
| 李四      | NULL |
| 小张      | NULL |
| 小黄      | NULL |
| 小黄      | NULL |
+-----------+------+
10 rows in set (0.00 sec)//查询不为NULL
mysql> select * from student1;
+----+-----------+---------+------+---------+--------------+
| id | name      | chinese | math | english | qq           |
+----+-----------+---------+------+---------+--------------+
|  1 | 小明      |      68 |   88 |      50 | NULL         |
|  2 | 小红      |      66 |   98 |      70 | NULL         |
|  3 | 小王      |      66 |   98 |      60 | NULL         |
|  4 | 莫扎特    |     100 |  100 |     100 | NULL         |
|  5 | 王五      |      10 |   10 |      10 | NULL         |
|  6 | 张三      |      66 |   66 |      66 | NULL         |
|  7 | 李四      |      66 |   66 |      66 | NULL         |
|  8 | 小张      |      88 |   32 |      33 | NULL         |
|  9 | 小黄      |      99 |    0 |      88 | NULL         |
| 10 | 小黄      |       0 |    0 |       0 | NULL         |
| 11 | 小王      |       0 |    0 |       0 | 45878@qq.com |
+----+-----------+---------+------+---------+--------------+
11 rows in set (0.00 sec)mysql> select name,qq from student1 where qq is not null;
+--------+--------------+
| name   | qq           |
+--------+--------------+
| 小王   | 45878@qq.com |
+--------+--------------+
1 row in set (0.00 sec)

NULL 和 NULL 的比较,= 和 <=> 的区别

//使用=号比较NULL值这个时候是不起作用的
mysql> select NULL=NULL ,NULL=1,NULL=0;
+-----------+--------+--------+
| NULL=NULL | NULL=1 | NULL=0 |
+-----------+--------+--------+
|      NULL |   NULL |   NULL |
+-----------+--------+--------+
1 row in set (0.00 sec)
//而使用<=>去比较NULL会显示他的结果值
mysql> select NULL <=> NULL , NULL <=> 1, NULL <=> 0;
+---------------+------------+------------+
| NULL <=> NULL | NULL <=> 1 | NULL <=> 0 |
+---------------+------------+------------+
|             1 |          0 |          0 |
+---------------+------------+------------+
1 row in set (0.00 sec)

结果排序

– ASC 为升序(从小到大)
– DESC 为降序(从大到小)
– 默认为 ASC

语法:

SELECT ... FROM table_name [WHERE ...] ORDER BY column
[ASC|DESC], [...];

同学及数学成绩,按数学成绩升序显示

//默认升序
mysql> select name,math from student1 order by math;
+-----------+------+
| name      | math |
+-----------+------+
| 小黄      |    0 |
| 小黄      |    0 |
| 小王      |    0 |
| 王五      |   10 |
| 小张      |   32 |
| 张三      |   66 |
| 李四      |   66 |
| 小明      |   88 |
| 小红      |   98 |
| 小王      |   98 |
| 莫扎特    |  100 |
+-----------+------+
11 rows in set (0.00 sec)

以qq排序,这里注意的是NULL值比任何值都小

mysql> select name,qq from student1 order by qq;
+-----------+--------------+
| name      | qq           |
+-----------+--------------+
| 小明      | NULL         |
| 小红      | NULL         |
| 小王      | NULL         |
| 莫扎特    | NULL         |
| 王五      | NULL         |
| 张三      | NULL         |
| 李四      | NULL         |
| 小张      | NULL         |
| 小黄      | NULL         |
| 小黄      | NULL         |
| 小王      | 45878@qq.com |
+-----------+--------------+
11 rows in set (0.00 sec)

修改排序结果使用desc,默认排降序

mysql> select name,qq from student1 order by qq desc;
+-----------+--------------+
| name      | qq           |
+-----------+--------------+
| 小王      | 45878@qq.com |
| 小明      | NULL         |
| 小红      | NULL         |
| 小王      | NULL         |
| 莫扎特    | NULL         |
| 王五      | NULL         |
| 张三      | NULL         |
| 李四      | NULL         |
| 小张      | NULL         |
| 小黄      | NULL         |
| 小黄      | NULL         |
+-----------+--------------+
11 rows in set (0.00 sec)

查询同学及总分,由高到低

mysql> select name,math+chinese+english '总分' from student1 order by math+english+chinese desc;
+-----------+--------+
| name      | 总分   |
+-----------+--------+
| 莫扎特    |    300 |
| 小红      |    234 |
| 小王      |    224 |
| 小明      |    206 |
| 张三      |    198 |
| 李四      |    198 |
| 小黄      |    187 |
| 小张      |    153 |
| 王五      |     30 |
| 小黄      |      0 |
| 小王      |      0 |
+-----------+--------+
11 rows in set (0.00 sec)

将小王同学和小张同学的数学成绩按照降序的方式排序

mysql> select name,math from student1 where name like '%张' or name like '%王' order by math desc;
+--------+------+
| name   | math |
+--------+------+
| 小王   |   98 |
| 小张   |   32 |
| 小王   |    0 |
+--------+------+
3 rows in set (0.00 sec)

筛选分页结果

  • 起始下标为 0

  • 从 0 开始,筛选 n 条结果 SELECT … FROM table_name [WHERE …] [ORDER BY …] LIMIT n;

  • 从 s 开始,筛选 n 条结果 SELECT … FROM table_name [WHERE …] [ORDER BY …] LIMIT s, n;

  • 从 s 开始,筛选 n 条结果,比第二种用法更明确,建议使用 SELECT … FROM table_name [WHERE …] [ORDER BY …] LIMIT n OFFSET s;

从0位置开始筛选n条结果


mysql> select * from student1 order by math;
+----+-----------+---------+------+---------+--------------+
| id | name      | chinese | math | english | qq           |
+----+-----------+---------+------+---------+--------------+
|  9 | 小黄      |      99 |    0 |      88 | NULL         |
| 10 | 小黄      |       0 |    0 |       0 | NULL         |
| 11 | 小王      |       0 |    0 |       0 | 45878@qq.com |
|  5 | 王五      |      10 |   10 |      10 | NULL         |
|  8 | 小张      |      88 |   32 |      33 | NULL         |
|  6 | 张三      |      66 |   66 |      66 | NULL         |
|  7 | 李四      |      66 |   66 |      66 | NULL         |
|  1 | 小明      |      68 |   88 |      50 | NULL         |
|  2 | 小红      |      66 |   98 |      70 | NULL         |
|  3 | 小王      |      66 |   98 |      60 | NULL         |
|  4 | 莫扎特    |     100 |  100 |     100 | NULL         |
+----+-----------+---------+------+---------+--------------+
11 rows in set (0.00 sec)mysql> select name,chinese,math,english,qq from student1 order by math limit 3;
+--------+---------+------+---------+--------------+
| name   | chinese | math | english | qq           |
+--------+---------+------+---------+--------------+
| 小王   |       0 |    0 |       0 | 45878@qq.com |
| 小黄   |      99 |    0 |      88 | NULL         |
| 小黄   |       0 |    0 |       0 | NULL         |
+--------+---------+------+---------+--------------+
3 rows in set (0.00 sec)

从s位置开始筛选n条结果

mysql> select * from student1 order by math;
+----+-----------+---------+------+---------+--------------+
| id | name      | chinese | math | english | qq           |
+----+-----------+---------+------+---------+--------------+
|  9 | 小黄      |      99 |    0 |      88 | NULL         |
| 10 | 小黄      |       0 |    0 |       0 | NULL         |
| 11 | 小王      |       0 |    0 |       0 | 45878@qq.com |
|  5 | 王五      |      10 |   10 |      10 | NULL         |
|  8 | 小张      |      88 |   32 |      33 | NULL         |
|  6 | 张三      |      66 |   66 |      66 | NULL         |
|  7 | 李四      |      66 |   66 |      66 | NULL         |
|  1 | 小明      |      68 |   88 |      50 | NULL         |
|  2 | 小红      |      66 |   98 |      70 | NULL         |
|  3 | 小王      |      66 |   98 |      60 | NULL         |
|  4 | 莫扎特    |     100 |  100 |     100 | NULL         |
+----+-----------+---------+------+---------+--------------+
11 rows in set (0.00 sec)mysql> select name,chinese,math,english,qq from student1 order by math limit 3,4;
+--------+---------+------+---------+------+
| name   | chinese | math | english | qq   |
+--------+---------+------+---------+------+
| 王五   |      10 |   10 |      10 | NULL |
| 小张   |      88 |   32 |      33 | NULL |
| 张三   |      66 |   66 |      66 | NULL |
| 李四   |      66 |   66 |      66 | NULL |
+--------+---------+------+---------+------+
4 rows in set (0.00 sec)

offset和limit组合 从 s位置开始,筛选 n 条结果

mysql> select * from student1 order by math;
+----+-----------+---------+------+---------+--------------+
| id | name      | chinese | math | english | qq           |
+----+-----------+---------+------+---------+--------------+
|  9 | 小黄      |      99 |    0 |      88 | NULL         |
| 10 | 小黄      |       0 |    0 |       0 | NULL         |
| 11 | 小王      |       0 |    0 |       0 | 45878@qq.com |
|  5 | 王五      |      10 |   10 |      10 | NULL         |
|  8 | 小张      |      88 |   32 |      33 | NULL         |
|  6 | 张三      |      66 |   66 |      66 | NULL         |
|  7 | 李四      |      66 |   66 |      66 | NULL         |
|  1 | 小明      |      68 |   88 |      50 | NULL         |
|  2 | 小红      |      66 |   98 |      70 | NULL         |
|  3 | 小王      |      66 |   98 |      60 | NULL         |
|  4 | 莫扎特    |     100 |  100 |     100 | NULL         |
+----+-----------+---------+------+---------+--------------+
11 rows in set (0.00 sec)mysql> select name,chinese,math,english,qq from student1 order by math limit 3 offset 6;
+--------+---------+------+---------+------+
| name   | chinese | math | english | qq   |
+--------+---------+------+---------+------+
| 李四   |      66 |   66 |      66 | NULL |
| 小明   |      68 |   88 |      50 | NULL |
| 小红   |      66 |   98 |      70 | NULL |
+--------+---------+------+---------+------+
3 rows in set (0.00 sec)

Update

语法:

UPDATE table_name SET column = expr [, column = expr ...]
[WHERE ...] [ORDER BY ...] [LIMIT ...]

对查询到的结果进行列值更新

将张三同学的数学成绩变更为 80 分

mysql> select * from student1;
+----+-----------+---------+------+---------+--------------+
| id | name      | chinese | math | english | qq           |
+----+-----------+---------+------+---------+--------------+
|  1 | 小明      |      68 |   88 |      50 | NULL         |
|  2 | 小红      |      66 |   98 |      70 | NULL         |
|  3 | 小王      |      66 |   98 |      60 | NULL         |
|  4 | 莫扎特    |     100 |  100 |     100 | NULL         |
|  5 | 王五      |      10 |   10 |      10 | NULL         |
|  6 | 张三      |      66 |   66 |      66 | NULL         |
|  7 | 李四      |      66 |   66 |      66 | NULL         |
|  8 | 小张      |      88 |   32 |      33 | NULL         |
|  9 | 小黄      |      99 |    0 |      88 | NULL         |
| 10 | 小黄      |       0 |    0 |       0 | NULL         |
| 11 | 小王      |       0 |    0 |       0 | 45878@qq.com |
+----+-----------+---------+------+---------+--------------+
11 rows in set (0.00 sec)mysql> update student1 set math=80 where name='张三';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0mysql> select name,math from student1 where name='张三';
+--------+------+
| name   | math |
+--------+------+
| 张三   |   80 |
+--------+------+
1 row in set (0.00 sec)

将李四同学的数学成绩变更为 60 分,语文成绩变更为 70 分

//查看数据
mysql> select * from student1;
+----+-----------+---------+------+---------+--------------+
| id | name      | chinese | math | english | qq           |
+----+-----------+---------+------+---------+--------------+
|  1 | 小明      |      68 |   88 |      50 | NULL         |
|  2 | 小红      |      66 |   98 |      70 | NULL         |
|  3 | 小王      |      66 |   98 |      60 | NULL         |
|  4 | 莫扎特    |     100 |  100 |     100 | NULL         |
|  5 | 王五      |      10 |   10 |      10 | NULL         |
|  6 | 张三      |      66 |   80 |      66 | NULL         |
|  7 | 李四      |      66 |   66 |      66 | NULL         |
|  8 | 小张      |      88 |   32 |      33 | NULL         |
|  9 | 小黄      |      99 |    0 |      88 | NULL         |
| 10 | 小黄      |       0 |    0 |       0 | NULL         |
| 11 | 小王      |       0 |    0 |       0 | 45878@qq.com |
+----+-----------+---------+------+---------+--------------+
11 rows in set (0.00 sec)
//更新数据
mysql> update student1 set math=60,chinese=70 where name='李四';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0
//查看更新后的数据
mysql> select name,math,chinese from student1 where name='李四';
+--------+------+---------+
| name   | math | chinese |
+--------+------+---------+
| 李四   |   60 |      70 |
+--------+------+---------+
1 row in set (0.00 sec)

将总成绩倒数前三的 3 位同学的数学成绩加上 30 分

mysql> update student1 set math = math+30 order by math+english+chinese limit 3;
Query OK, 3 rows affected (0.07 sec)
Rows matched: 3  Changed: 3  Warnings: 0mysql> select name,math,math+english+chinese 总分 from student1 order by 总分 limit 3;
+--------+------+--------+
| name   | math | 总分   |
+--------+------+--------+
| 小王   |   30 |     30 |
| 小黄   |   30 |     30 |
| 王五   |   40 |     60 |
+--------+------+--------+
3 rows in set (0.00 sec)

将所有同学的语文成绩更新为原来的 2 倍

mysql> select * from student1;
+----+-----------+---------+------+---------+--------------+
| id | name      | chinese | math | english | qq           |
+----+-----------+---------+------+---------+--------------+
|  1 | 小明      |      68 |   88 |      50 | NULL         |
|  2 | 小红      |      66 |   98 |      70 | NULL         |
|  3 | 小王      |      66 |   98 |      60 | NULL         |
|  4 | 莫扎特    |     100 |  100 |     100 | NULL         |
|  5 | 王五      |      10 |   40 |      10 | NULL         |
|  6 | 张三      |      66 |   80 |      66 | NULL         |
|  7 | 李四      |      70 |   60 |      66 | NULL         |
|  8 | 小张      |      88 |   32 |      33 | NULL         |
|  9 | 小黄      |      99 |    0 |      88 | NULL         |
| 10 | 小黄      |       0 |   30 |       0 | NULL         |
| 11 | 小王      |       0 |   30 |       0 | 45878@qq.com |
+----+-----------+---------+------+---------+--------------+
11 rows in set (0.00 sec)
//更新数据
mysql> update student1 set chinese= chinese*2 ;
Query OK, 9 rows affected (0.01 sec)
Rows matched: 11  Changed: 9  Warnings: 0
//查看更新后的数据
mysql> select * from student1;
+----+-----------+---------+------+---------+--------------+
| id | name      | chinese | math | english | qq           |
+----+-----------+---------+------+---------+--------------+
|  1 | 小明      |     136 |   88 |      50 | NULL         |
|  2 | 小红      |     132 |   98 |      70 | NULL         |
|  3 | 小王      |     132 |   98 |      60 | NULL         |
|  4 | 莫扎特    |     200 |  100 |     100 | NULL         |
|  5 | 王五      |      20 |   40 |      10 | NULL         |
|  6 | 张三      |     132 |   80 |      66 | NULL         |
|  7 | 李四      |     140 |   60 |      66 | NULL         |
|  8 | 小张      |     176 |   32 |      33 | NULL         |
|  9 | 小黄      |     198 |    0 |      88 | NULL         |
| 10 | 小黄      |       0 |   30 |       0 | NULL         |
| 11 | 小王      |       0 |   30 |       0 | 45878@qq.com |
+----+-----------+---------+------+---------+--------------+
11 rows in set (0.00 sec)

Delete

删除数据语法:

DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]

删除张三的所有成绩

//查看张三的信息
mysql> delete from student1 where name='张三';
Query OK, 1 row affected (0.01 sec)
//删除后查看,信息为空
mysql> select name,math,chinese,english from student1 where name='张三';
Empty set (0.00 sec)

删除整张表数据

//删除表数据
delete from studnet1;
//删除后,数据为空
mysql> select * from student1;
Empty set (0.00 sec)

截断表

语法:

TRUNCATE [TABLE] table_name

注意:这个操作慎用

  1. 只能对整表操作,不能像 DELETE 一样针对部分数据操作;
  2. 实际上 MySQL 不对数据操作,所以比 DELETE 更快,但是TRUNCATE在删除数据的时候,并不经过真正的事物,所以无法回滚
  3. 会重置 AUTO_INCREMENT 项
//创建测试表
mysql> create table test(-> id int primary key auto_increment,-> name varchar(20)-> );
Query OK, 0 rows affected (0.02 sec)
//插入数据
mysql> insert into test(name) values('a');
Query OK, 1 row affected (0.01 sec)
mysql> insert into test(name) values('b');
Query OK, 1 row affected (0.01 sec)
mysql> insert into test(name) values('c');
Query OK, 1 row affected (0.01 sec)
mysql> insert into test(name) values('d');
Query OK, 1 row affected (0.02 sec)
//查看表信息
mysql> show create table test;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| test  | CREATE TABLE `test` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(20) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
//AUTO_INCREMENT 已经被更新为5

使用TRUNCATE 会将表中的AUTO_INCREMENT 重置

//表中原本的AUTO_INCREMENT 值为5
mysql> show create table test;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| test  | CREATE TABLE `test` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(20) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)//使用truncate重置AUTO_INCREMENT 的效果:
mysql> show create table test;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                               |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| test  | CREATE TABLE `test` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(20) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

插入查询结果

INSERT INTO table_name [(column [, column ...])] SELECT ...
//创建表
mysql> create table test(-> id int,-> name varchar(20)-> );
Query OK, 0 rows affected (0.02 sec)
//插入数据
mysql> insert into test values(1,'aa');
Query OK, 1 row affected (0.00 sec)mysql> insert into test values(1,'bb');
Query OK, 1 row affected (0.01 sec)mysql> insert into test values(2,'aa');
Query OK, 1 row affected (0.01 sec)mysql> insert into test values(3,'cc');
Query OK, 1 row affected (0.00 sec)mysql> insert into test values(3,'cc');
Query OK, 1 row affected (0.01 sec)
//查看表数据
mysql> select * from test;
+------+------+
| id   | name |
+------+------+
|    1 | aa   |
|    1 | bb   |
|    2 | aa   |
|    3 | cc   |
|    3 | cc   |
+------+------+
5 rows in set (0.00 sec)
//创建副表
mysql> create table new_test like test;
Query OK, 0 rows affected (0.03 sec)
//将主表的信息插入到副表中
mysql> insert into new_test select * from test;
Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0
//查看主表
mysql> select * from test;
+------+------+
| id   | name |
+------+------+
|    1 | aa   |
|    1 | bb   |
|    2 | aa   |
|    3 | cc   |
|    3 | cc   |
+------+------+
5 rows in set (0.00 sec)
//查看副表
mysql> select * from new_test;
+------+------+
| id   | name |
+------+------+
|    1 | aa   |
|    1 | bb   |
|    2 | aa   |
|    3 | cc   |
|    3 | cc   |
+------+------+
5 rows in set (0.00 sec)

聚合函数

函数 说明
COUNT([DISTINCT] expr) 返回查询到的数据的 数量
SUM([DISTINCT] expr) 返回查询到的数据的 总和,不是数字没有意义
AVG([DISTINCT] expr) 返回查询到的数据的 平均值,不是数字没有意义
MAX([DISTINCT] expr) 返回查询到的数据的 最大值,不是数字没有意义
MIN([DISTINCT] expr) 返回查询到的数据的 最小值,不是数字没有意义

COUNT函数使用

mysql> select * from student1;
+----+--------+---------+------+---------+----------------+
| id | name   | chinese | math | english | qq             |
+----+--------+---------+------+---------+----------------+
|  1 | 张三   |      56 |   77 |      88 | 5456464@qq.com |
|  2 | 李四   |      66 |   87 |      98 | 5445464@qq.com |
|  3 | 王五   |      99 |   86 |      99 | 5446564@qq.com |
+----+--------+---------+------+---------+----------------+
3 rows in set (0.00 sec)
//查看表中成员的个数
mysql> select count(*) from student1;
+----------+
| count(*) |
+----------+
|        3 |
+----------+
1 row in set (0.01 sec)
//也可以使用count(1)表达式效果跟使用count(*)表达式是一样的
mysql> select count(1) from student1;
+----------+
| count(*) |
+----------+
|        3 |
+----------+
//插入一个新值
mysql> insert into student1 values(4,'小六',99,86,99,NULL);
Query OK, 1 row affected (0.01 sec)//count函数也可以使用字段做参数
mysql> select count(qq) from student1;
+-----------+
| count(qq) |
+-----------+
|         3 |
+-----------+
1 row in set (0.00 sec)mysql> select * from student1;
+----+--------+---------+------+---------+----------------+
| id | name   | chinese | math | english | qq             |
+----+--------+---------+------+---------+----------------+
|  1 | 张三   |      56 |   77 |      88 | 5456464@qq.com |
|  2 | 李四   |      66 |   87 |      98 | 5445464@qq.com |
|  3 | 王五   |      99 |   86 |      99 | 5446564@qq.com |
|  4 | 小六   |      99 |   86 |      99 | NULL           |
+----+--------+---------+------+---------+----------------+
4 rows in set (0.00 sec)//查看数学考试成绩的个数
mysql> select count(math) from student1;
+-------------+
| count(math) |
+-------------+
|           4 |
+-------------+
1 row in set (0.00 sec)
//distinct math 可以去重相同数学成绩的个数
mysql> select count(distinct math) from student1;
+----------------------+
| count(distinct math) |
+----------------------+
|                    3 |
+----------------------+
1 row in set (0.00 sec)

sum求和计算

//计算数学总分数
mysql> select sum(math) from student1;
+-----------+
| sum(math) |
+-----------+
|       336 |
+-----------+
1 row in set (0.00 sec)//查看成绩小于60分的分数之和,如果没有那就是NULL
mysql> select sum(math) from student1 where math<60;
+-----------+
| sum(math) |
+-----------+
|      NULL |
+-----------+
1 row in set (0.00 sec)
//如果有,就会将所有不及格的人的分数加起来显示
mysql> select sum(math) from student1 where math<90;
+-----------+
| sum(math) |
+-----------+
|       336 |
+-----------+
1 row in set (0.00 sec)

avg显示平均总分

mysql> select avg(math + chinese + english) from student1;
+-------------------------------+
| avg(math + chinese + english) |
+-------------------------------+
|                           260 |
+-------------------------------+
1 row in set (0.00 sec)

max求较大值

mysql> select max(math) from student1;
+-----------+
| max(math) |
+-----------+
|        87 |
+-----------+
1 row in set (0.00 sec)

min求较小值

//返回小于70分的较小值
mysql> select min(math) from student1 where math<80;
+-----------+
| min(math) |
+-----------+
|        77 |
+-----------+
1 row in set (0.00 sec)

group by

在select中使用group by 子句可以对指定列进行分组查询

select column1, column2, .. from table group by column;

案例:
准备工作,创建一个雇员信息表(来自oracle 9i的经典测试表)
EMP员工表
DEPT部门表
SALGRADE工资等级表

mysql> desc emp;
+----------+--------------------------+------+-----+---------+-------+
| Field    | Type                     | Null | Key | Default | Extra |
+----------+--------------------------+------+-----+---------+-------+
| empno    | int(6) unsigned zerofill | NO   |     | NULL    |       |
| ename    | varchar(10)              | YES  |     | NULL    |       |
| job      | varchar(9)               | YES  |     | NULL    |       |
| mgr      | int(4) unsigned zerofill | YES  |     | NULL    |       |
| hiredate | datetime                 | YES  |     | NULL    |       |
| sal      | decimal(7,2)             | YES  |     | NULL    |       |
| comm     | decimal(7,2)             | YES  |     | NULL    |       |
| deptno   | int(2) unsigned zerofill | YES  |     | NULL    |       |
+----------+--------------------------+------+-----+---------+-------+
8 rows in set (0.00 sec)mysql> desc dept-> ;
+--------+--------------------------+------+-----+---------+-------+
| Field  | Type                     | Null | Key | Default | Extra |
+--------+--------------------------+------+-----+---------+-------+
| deptno | int(2) unsigned zerofill | NO   |     | NULL    |       |
| dname  | varchar(14)              | YES  |     | NULL    |       |
| loc    | varchar(13)              | YES  |     | NULL    |       |
+--------+--------------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)mysql> desc salgrade;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| grade | int(11) | YES  |     | NULL    |       |
| losal | int(11) | YES  |     | NULL    |       |
| hisal | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
3 rows in set (0.00 sec)

显示各个部门的平均工资和最高工资

mysql> select deptno ,avg(sal),max(sal) from emp group by deptno;
+--------+-------------+----------+
| deptno | avg(sal)    | max(sal) |
+--------+-------------+----------+
|     10 | 2916.666667 |  5000.00 |
|     20 | 2175.000000 |  3000.00 |
|     30 | 1566.666667 |  2850.00 |
+--------+-------------+----------+
3 rows in set (0.00 sec)

显示每个部门的每种岗位的平均工资和最低工资

mysql> select deptno, job,avg(sal),min(sal) from emp group by deptno,job;
+--------+-----------+-------------+----------+
| deptno | job       | avg(sal)    | min(sal) |
+--------+-----------+-------------+----------+
|     10 | CLERK     | 1300.000000 |  1300.00 |
|     10 | MANAGER   | 2450.000000 |  2450.00 |
|     10 | PRESIDENT | 5000.000000 |  5000.00 |
|     20 | ANALYST   | 3000.000000 |  3000.00 |
|     20 | CLERK     |  950.000000 |   800.00 |
|     20 | MANAGER   | 2975.000000 |  2975.00 |
|     30 | CLERK     |  950.000000 |   950.00 |
|     30 | MANAGER   | 2850.000000 |  2850.00 |
|     30 | SALESMAN  | 1400.000000 |  1250.00 |
+--------+-----------+-------------+----------+
9 rows in set (0.00 sec)

显示平均工资低于2000的部门和它的平均工资

//对各部门分组完了后,显示他们的平均工资和部门编号
mysql> select deptno, avg(sal) from emp group by deptno ;
+--------+-------------+
| deptno | avg(sal)    |
+--------+-------------+
|     10 | 2916.666667 |
|     20 | 2175.000000 |
|     30 | 1566.666667 |
+--------+-------------+
3 rows in set (0.00 sec)//筛选出部门平均工资低于2000的部门编号,使用having对group by结果进行过滤
//--having经常和group by搭配使用,作用是对分组进行筛选,作用有些像where。
mysql> select deptno 部门,avg(sal) 平均工资 from emp group by deptno having 平均工资 < 2000;
+--------+--------------+
| 部门   | 平均工资     |
+--------+--------------+
|     30 |  1566.666667 |
+--------+--------------+
1 row in set (0.00 sec)

函数

日期函数

函数名称 描述
current_date() 当前日期
current_time() 当前时间
current_timestamp 当前时间戳
date(datetime) 返回datetime参数的日期部分
date_add(date, intertval, d_value_type) 在date中添加日期或者时间,interval后的数值单位可以是:year、minute、second day
date_sub(date, intertval, d_value_type) 在date中减去日期或者时间,interval后的数值单位可以是:year、minute、second day
datediff(date1, date2) 两个日期的差值,单位是天
now() 当前时间

测试:
current_date获取当前年月日

mysql> select current_date();
+----------------+
| current_date() |
+----------------+
| 2021-12-04     |
+----------------+
1 row in set (0.00 sec)

current_time函数获取时分秒

mysql> select current_time();
+----------------+
| current_time() |
+----------------+
| 20:19:07       |
+----------------+
1 row in set (0.00 sec)

current_timestamp函数获取当前时间戳

mysql> select  current_timestamp();
+---------------------+
| current_timestamp() |
+---------------------+
| 2021-12-04 20:20:47 |
+---------------------+
1 row in set (0.00 sec)

日期的基础上加上日期

mysql> select date_add('2021-12-4',interval 10 day);
+---------------------------------------+
| date_add('2021-12-4',interval 10 day) |
+---------------------------------------+
| 2021-12-14                            |
+---------------------------------------+
1 row in set (0.00 sec)

在日期的基础上减去时间:

mysql> select date_sub('2021-12-14', interval 10 day);
+-----------------------------------------+
| date_sub('2021-12-14', interval 10 day) |
+-----------------------------------------+
| 2021-12-04                              |
+-----------------------------------------+
1 row in set (0.00 sec)

计算两个日期之间相差多少天:

mysql> select datediff('2021-10-10','2021-8-10');
+------------------------------------+
| datediff('2021-10-10','2021-8-10') |
+------------------------------------+
|                                 61 |
+------------------------------------+
1 row in set (0.00 sec)

案例:
创建一个生日表,插入当前时间

mysql> create table birthday1(-> id int primary key auto_increment,-> birthday date not null-> );mysql> select * from birthday1;
+----+------------+
| id | birthday   |
+----+------------+
|  1 | 2021-12-04 |
|  2 | 2021-12-04 |
+----+------------+

创建一个留言表

//创建表
mysql> create table mymessage(-> username varchar(20) not null unique key,-> content  varchar(20) not null,-> sendtime datetime-> );
Query OK, 0 rows affected (0.03 sec)
//插入数据
mysql> insert into mymessage(username, content,sendtime)values('中华小子','我爱我国',current_date());
Query OK, 1 row affected (0.01 sec)mysql> insert into mymessage(username, content,sendtime)values('电击小子','我爱我华夏',current_date());
Query OK, 1 row affected (0.00 sec)//显示数据
mysql> select * from mymessage;
+--------------+-----------------+---------------------+
| username     | content         | sendtime            |
+--------------+-----------------+---------------------+
| 中华小子     | 我爱我国        | 2021-12-04 00:00:00 |
| 电击小子     | 我爱我华夏      | 2021-12-04 00:00:00 |
+--------------+-----------------+---------------------+
2 rows in set (0.00 sec)

显示所有留言信息,发布日期只显示日期,不用显示时间

mysql> select username 用户名,content 留言, date(sendtime) 留言时间 from mymessage;
+--------------+-----------------+--------------+
| 用户名       | 留言            | 留言时间     |
+--------------+-----------------+--------------+
| 中华小子     | 我爱我国        | 2021-12-04   |
| 电击小子     | 我爱我华夏      | 2021-12-04   |
+--------------+-----------------+--------------+
2 rows in set (0.00 sec)

请查询在2分钟内发布的帖子

查看两分钟之内的信息是看当前时间是否存在【sendtime,sendtime + 2】这个区间内,如果存在就判断该时间是2分钟发布的留言

//更新李青用户当前的留言时间
mysql> update mymessage set sendtime=now() where username='李青';
Query OK, 1 row affected (0.00 sec)
//显示信息
mysql> select * from mymessage;
+--------------+-----------------+---------------------+
| username     | content         | sendtime            |
+--------------+-----------------+---------------------+
| 中华小子     | 我爱我国        | 2021-12-04 00:00:00 |
| 李青         | 国足加油!!      | 2021-12-04 21:06:41 |
| 电击小子     | 我爱我华夏      | 2021-12-04 00:00:00 |
+--------------+-----------------+---------------------+
3 rows in set (0.00 sec)
//查询两分钟之内留言的信息
mysql> select username 用户名 ,content 留言内容 ,sendtime 留言时间 from mymessage where date_add(sendtime,interval 2 minute) > now();
+-----------+----------------+---------------------+
| 用户名    | 留言内容       | 留言时间            |
+-----------+----------------+---------------------+
| 李青      | 国足加油!!     | 2021-12-04 21:06:41 |
+-----------+----------------+---------------------+
1 row in set (0.00 sec)

字符串函数

函数名 说明
charset(str) 返回字符串字符集
concat(string,【,…】) 链接字符串
instr(string,substring) 返回substring()在string中出现的位置,没有则返回0
ucase 小写转大写
lcase 大写转小写
left(string, length) 从string的左边起取length长度个字符
length(string) 获取string字符串的长度
replace(str,search_str, replace_str) 在string中用replace_str替换search_str
strcmp(string,string) 比较两个字符串的长度
substring(str, pointer, 【,length】) 从str的pointer位置开始截取length个长度的字符
ltrim(string)、rtrim(string)、trim(string) 去除前空格或者后空格

案例:
获取mymessage表的username列的字符集

mysql> select charset(username) from mymessage;
+-------------------+
| charset(username) |
+-------------------+
| utf8              |
| utf8              |
| utf8              |
+-------------------+
3 rows in set (0.00 sec)

字符拼接,拼接显示一个人的留言板全部信息

mysql> select concat(username,'留言时间是:',sendtime,'留言内容是:',content) 描述 from mymessage where username='李青'
';
+-----------------------------------------------------------------------------+
| 描述                                                                        |
+-----------------------------------------------------------------------------+
| 李青留言时间是:2021-12-04 21:06:41留言内容是:国足加油!!                   |
+-----------------------------------------------------------------------------+
1 row in set (0.00 sec)

求所占字节大小

mysql> select length('你好');
+------------------+
| length('你好')   |
+------------------+
|                6 |
+------------------+
1 row in set (0.00 sec)mysql> select length('abc');
+---------------+
| length('abc') |
+---------------+
|             3 |
+---------------+
1 row in set (0.00 sec)mysql> select length('1');
+-------------+
| length('1') |
+-------------+
|           1 |
+-------------+
1 row in set (0.00 sec)//也可以使用length查询表内数据时间占用的字节数
mysql> select * from mymessage;
+--------------+-----------------+---------------------+
| username     | content         | sendtime            |
+--------------+-----------------+---------------------+
| 中华小子     | 我爱我国        | 2021-12-04 00:00:00 |
| 李青         | 国足加油!!      | 2021-12-04 21:06:41 |
| 电击小子     | 我爱我华夏      | 2021-12-04 00:00:00 |
+--------------+-----------------+---------------------+
3 rows in set (0.00 sec)mysql> select length(username) from mymessage;
+------------------+
| length(username) |
+------------------+
|               12 |
|                6 |
|               12 |
+------------------+
3 rows in set (0.00 sec)

注意:length函数返回字符串长度,以字节为单位。如果是多字节字符则计算多个字节数;如果是单字节字符则算作一个字节。比如:字母,数组算作一个字节,中文表示多个字节数(与字符集编码有关)

替换

如果不指定则将全部的str修改为对应的字符串

mysql> select replace(username,'李青','盲僧') from mymessage where username='李青';
+-------------------------------------+
| replace(username,'李青','盲僧')     |
+-------------------------------------+
| 盲僧                                |
+-------------------------------------+
1 row in set (0.00 sec)

效果:

截取字符串

substring默认是以1开始为第一个字符的下标,如果不指定则截取原表中所有的字符串

//不指定
mysql> select substring(username,1,2) from mymessage where username='李青';
+-------------------------+
| substring(username,1,2) |
+-------------------------+
| 李青                    |
+-------------------------+
1 row in set (0.00 sec)
//指定
mysql> select substring(username,1,2) from mymessage ;
+-------------------------+
| substring(username,1,2) |
+-------------------------+
| 中华                    |
| 李青                    |
| 电击                    |
+-------------------------+
3 rows in set (0.00 sec)

以首字母大写的方式显示所有用户的名字

mysql> select * from test;
+------------+
| name       |
+------------+
| liqing     |
| damo       |
| daolang    |
| linghuchon |
+------------+
4 rows in set (0.00 sec)//截取一段字符并拼接,并将首字符转换为大写
mysql> select concat(ucase(substring(name,1,1)),substring(name,2)) from test;
+------------------------------------------------------+
| concat(ucase(substring(name,1,1)),substring(name,2)) |
+------------------------------------------------------+
| Liqing                                               |
| Damo                                                 |
| Daolang                                              |
| Linghuchon                                           |
+------------------------------------------------------+
4 rows in set (0.00 sec)

数学函数

函数名 说明
abs(number) 绝对值函数
bin(descimal_number) 十进制转换为二进制
hex(descimal_number) 转换为十六进制
conv(number, from_base, to_base) 进制转换
ceilling(number) 向上去整
floor(number) 向下取整
format(number, decimal_places) 格式化保留小数位数
hex(descimal_number) 转换为16进制
rand() 返回随机浮点数,范围【0.0, 1.0】
mod(number, denominator) 取模,求余

测试:
绝对值

mysql> select abs(-127);
+-----------+
| abs(-127) |
+-----------+
|       127 |
+-----------+
1 row in set (0.00 sec)

向上取整

mysql> select  ceiling(23.07);
+----------------+
| ceiling(23.07) |
+----------------+
|             24 |
+----------------+
1 row in set (0.00 sec)

向下取整

mysql> select floor(23.07);
+--------------+
| floor(23.07) |
+--------------+
|           23 |
+--------------+
1 row in set (0.00 sec)

保留后两位小数

mysql> select format(123.4567 ,2);
//后面参数可以指定保留两位小数
+--------------------+
| format(123.4567,2) |
+--------------------+
| 123.46             |
+--------------------+
1 row in set (0.00 sec)

产生随机小数,可以做运算

mysql> select rand();
+--------------------+
| rand()             |
+--------------------+
| 0.4044063942547947 |
+--------------------+
1 row in set (0.00 sec)mysql> select rand() * 10;
+--------------------+
| rand() * 10        |
+--------------------+
| 2.8106791924784695 |
+--------------------+
1 row in set (0.00 sec)

其它函数

user() 查询当前用户

mysql> select  user();
+----------------+
| user()         |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)

md5(str)

md5(str)对一个字符串进行md5摘要,摘要后得到一个32位字符串,使用md5加密后的字符串是定长的,并不会因为str的长度改变而改变,并且md5产生的值是不会冲突的

mysql> select md5('45464');
+----------------------------------+
| md5('45464')                     |
+----------------------------------+
| f486fd86b3fdbf6f4f365d49c2bbe29a |
+----------------------------------+
1 row in set (0.00 sec)

显示当前使用数据库

mysql> select database();
+------------+
| database() |
+------------+
| code       |
+------------+
1 row in set (0.00 sec)

ifnull()

ifnull(val1, val2) 如果val1为null,返回val2,否则返回val1的值

mysql> select  ifnull('123','234');
+---------------------+
| ifnull('123','234') |
+---------------------+
| 123                 |
+---------------------+
1 row in set (0.00 sec)mysql> select  ifnull(NULL,'234');
+--------------------+
| ifnull(NULL,'234') |
+--------------------+
| 234                |
+--------------------+
1 row in set (0.00 sec)

复合查询(重点)

基本查询

查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J

mysql> select * from emp where (sal>500 or job='MANAGER') and ename like 'J%';
+--------+-------+---------+------+---------------------+---------+------+--------+
| empno  | ename | job     | mgr  | hiredate            | sal     | comm | deptno |
+--------+-------+---------+------+---------------------+---------+------+--------+
| 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
| 007900 | JAMES | CLERK   | 7698 | 1981-12-03 00:00:00 |  950.00 | NULL |     30 |
+--------+-------+---------+------+---------------------+---------+------+--------+
2 rows in set (0.00 sec)

按照部门号升序而雇员的工资降序排序

mysql> select * from emp order by deptno, sal desc;
+--------+--------+-----------+------+---------------------+---------+---------+--------+
| empno  | ename  | job       | mgr  | hiredate            | sal     | comm    | deptno |
+--------+--------+-----------+------+---------------------+---------+---------+--------+
| 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10 |
| 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10 |
| 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10 |
| 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20 |
| 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20 |
| 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20 |
| 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20 |
| 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20 |
| 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30 |
| 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30 |
| 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30 |
| 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30 |
| 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30 |
| 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30 |
+--------+--------+-----------+------+---------------------+---------+---------+--------+
14 rows in set (0.00 sec)

使用年薪进行降序排序

ifnull(comm,0),如果comm值为NULL就返回0,否则返回comm的值

mysql> select ename,ifnull(comm,0) + 12 * sal 年薪 from emp order by 年薪 desc;
+--------+----------+
| ename  | 年薪     |
+--------+----------+
| KING   | 60000.00 |
| SCOTT  | 36000.00 |
| FORD   | 36000.00 |
| JONES  | 35700.00 |
| BLAKE  | 34200.00 |
| CLARK  | 29400.00 |
| ALLEN  | 19500.00 |
| TURNER | 18000.00 |
| MARTIN | 16400.00 |
| MILLER | 15600.00 |
| WARD   | 15500.00 |
| ADAMS  | 13200.00 |
| JAMES  | 11400.00 |
| SMITH  |  9600.00 |
+--------+----------+
14 rows in set (0.00 sec)

显示工资最高的员工的名字和工作岗位

mysql> select ename,job,sal from emp order by sal desc limit 1;
+-------+-----------+---------+
| ename | job       | sal     |
+-------+-----------+---------+
| KING  | PRESIDENT | 5000.00 |
+-------+-----------+---------+
1 row in set (0.00 sec)

显示工资高于平均工资的员工信息

mysql> select * from emp where sal >(select avg(sal) from emp);
+--------+-------+-----------+------+---------------------+---------+------+--------+
| empno  | ename | job       | mgr  | hiredate            | sal     | comm | deptno |
+--------+-------+-----------+------+---------------------+---------+------+--------+
| 007566 | JONES | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
| 007698 | BLAKE | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 | NULL |     30 |
| 007782 | CLARK | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 | NULL |     10 |
| 007788 | SCOTT | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL |     20 |
| 007839 | KING  | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 | NULL |     10 |
| 007902 | FORD  | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL |     20 |
+--------+-------+-----------+------+---------------------+---------+------+--------+
6 rows in set (0.00 sec)

显示每个部门的平均工资和最高工资

format函数可以控制浮点数的精度,这里精确到小数点后两位

mysql> select deptno, format(avg(sal),2), max(sal) from emp group by deptno;
+--------+--------------------+----------+
| deptno | format(avg(sal),2) | max(sal) |
+--------+--------------------+----------+
|     10 | 2,916.67           |  5000.00 |
|     20 | 2,175.00           |  3000.00 |
|     30 | 1,566.67           |  2850.00 |
+--------+--------------------+----------+
3 rows in set (0.00 sec)

显示平均工资低于2000的部门号和它的平均工资

mysql> select deptno ,avg(sal)  平均工资 from emp group by deptno having 平均工资<2000;
+--------+--------------+
| deptno | 平均工资     |
+--------+--------------+
|     30 |  1566.666667 |
+--------+--------------+
1 row in set (0.00 sec)

显示每种岗位的雇员总数,平均工资

mysql> select job,count(*),format(avg(sal),2) from emp group by job;
+-----------+----------+--------------------+
| job       | count(*) | format(avg(sal),2) |
+-----------+----------+--------------------+
| ANALYST   |        2 | 3,000.00           |
| CLERK     |        4 | 1,037.50           |
| MANAGER   |        3 | 2,758.33           |
| PRESIDENT |        1 | 5,000.00           |
| SALESMAN  |        4 | 1,400.00           |
+-----------+----------+--------------------+
5 rows in set (0.00 sec)

多表查询

实际开发中往往数据来自不同的表,所以需要多表查询。我们用一个简单的公司管理系统,有三张表EMP,DEPT,SALGRADE来演示如何进行多表查询。


显示雇员名、雇员工资以及所在部门的名字因为上面的数据来自EMP和DEPT表,因此要联合查询

笛卡尔积概念:

笛卡尔乘积是指在数学中,两个集合X和Y的笛卡尓积(Cartesian
product),又称直积,表示为X×Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员 。假设集合A={a, b},集合B={0, 1, 2},则两个集合的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0),
(b, 1), (b, 2)}。

显示雇员名、雇员工资以及所在部门的名字因为上面的数据来自EMP和DEPT表,因此要联合查询

/使用笛卡尔积
mysql> select dept.deptno,emp.deptno,ename,sal from emp ,dept;
+--------+--------+--------+---------+
| deptno | deptno | ename  | sal     |
+--------+--------+--------+---------+
|     10 |     20 | SMITH  |  800.00 |
|     20 |     20 | SMITH  |  800.00 |
|     30 |     20 | SMITH  |  800.00 |
|     40 |     20 | SMITH  |  800.00 |
|     10 |     30 | ALLEN  | 1600.00 |
|     20 |     30 | ALLEN  | 1600.00 |
|     30 |     30 | ALLEN  | 1600.00 |
|     40 |     30 | ALLEN  | 1600.00 |
|     10 |     30 | WARD   | 1250.00 |
|     20 |     30 | WARD   | 1250.00 |
|     30 |     30 | WARD   | 1250.00 |
|     40 |     30 | WARD   | 1250.00 |
|     10 |     20 | JONES  | 2975.00 |
|     20 |     20 | JONES  | 2975.00 |
|     30 |     20 | JONES  | 2975.00 |
|     40 |     20 | JONES  | 2975.00 |
|     10 |     30 | MARTIN | 1250.00 |
|     20 |     30 | MARTIN | 1250.00 |
|     30 |     30 | MARTIN | 1250.00 |
|     40 |     30 | MARTIN | 1250.00 |
|     10 |     30 | BLAKE  | 2850.00 |
|     20 |     30 | BLAKE  | 2850.00 |
|     30 |     30 | BLAKE  | 2850.00 |
|     40 |     30 | BLAKE  | 2850.00 |
|     10 |     10 | CLARK  | 2450.00 |
|     20 |     10 | CLARK  | 2450.00 |
|     30 |     10 | CLARK  | 2450.00 |
|     40 |     10 | CLARK  | 2450.00 |
|     10 |     20 | SCOTT  | 3000.00 |
|     20 |     20 | SCOTT  | 3000.00 |
|     30 |     20 | SCOTT  | 3000.00 |
|     40 |     20 | SCOTT  | 3000.00 |
|     10 |     10 | KING   | 5000.00 |
|     20 |     10 | KING   | 5000.00 |
|     30 |     10 | KING   | 5000.00 |
|     40 |     10 | KING   | 5000.00 |
|     10 |     30 | TURNER | 1500.00 |
|     20 |     30 | TURNER | 1500.00 |
|     30 |     30 | TURNER | 1500.00 |
|     40 |     30 | TURNER | 1500.00 |
|     10 |     20 | ADAMS  | 1100.00 |
|     20 |     20 | ADAMS  | 1100.00 |
|     30 |     20 | ADAMS  | 1100.00 |
|     40 |     20 | ADAMS  | 1100.00 |
|     10 |     30 | JAMES  |  950.00 |
|     20 |     30 | JAMES  |  950.00 |
|     30 |     30 | JAMES  |  950.00 |
|     40 |     30 | JAMES  |  950.00 |
|     10 |     20 | FORD   | 3000.00 |
|     20 |     20 | FORD   | 3000.00 |
|     30 |     20 | FORD   | 3000.00 |
|     40 |     20 | FORD   | 3000.00 |
|     10 |     10 | MILLER | 1300.00 |
|     20 |     10 | MILLER | 1300.00 |
|     30 |     10 | MILLER | 1300.00 |
|     40 |     10 | MILLER | 1300.00 |
+--------+--------+--------+---------+
56 rows in set (0.00 sec)//对笛卡尔积进行筛选,筛选出员工部门编号对应的部门表信息
mysql> select dept.deptno,emp.deptno,ename,sal from emp ,dept where emp.deptno=dept.deptno;
+--------+--------+--------+---------+
| deptno | deptno | ename  | sal     |
+--------+--------+--------+---------+
|     20 |     20 | SMITH  |  800.00 |
|     30 |     30 | ALLEN  | 1600.00 |
|     30 |     30 | WARD   | 1250.00 |
|     20 |     20 | JONES  | 2975.00 |
|     30 |     30 | MARTIN | 1250.00 |
|     30 |     30 | BLAKE  | 2850.00 |
|     10 |     10 | CLARK  | 2450.00 |
|     20 |     20 | SCOTT  | 3000.00 |
|     10 |     10 | KING   | 5000.00 |
|     30 |     30 | TURNER | 1500.00 |
|     20 |     20 | ADAMS  | 1100.00 |
|     30 |     30 | JAMES  |  950.00 |
|     20 |     20 | FORD   | 3000.00 |
|     10 |     10 | MILLER | 1300.00 |
+--------+--------+--------+---------+
14 rows in set (0.01 sec)

显示部门号为10的部门名,员工名和工资

mysql> select emp.deptno,dept.deptno dname,ename,sal from emp,dept where dept.deptno=emp.deptno and emp.deptno=10;
+--------+-------+--------+---------+
| deptno | dname | ename  | sal     |
+--------+-------+--------+---------+
|     10 |    10 | CLARK  | 2450.00 |
|     10 |    10 | KING   | 5000.00 |
|     10 |    10 | MILLER | 1300.00 |
+--------+-------+--------+---------+
3 rows in set (0.00 sec)

显示各个员工的姓名,工资,及工资级别

只要在工资等级范围内就将他显示出来,因为sal和salgrade是在不同表中,所以在查询的时候需要将这两张表做笛卡尔积,而如果工资在【losal, hisal】这个区间里面就将他显示

mysql> select ename,sal,grade from emp,salgrade where emp.sal between losal and hisal;
+--------+---------+-------+
| ename  | sal     | grade |
+--------+---------+-------+
| SMITH  |  800.00 |     1 |
| ALLEN  | 1600.00 |     3 |
| WARD   | 1250.00 |     2 |
| JONES  | 2975.00 |     4 |
| MARTIN | 1250.00 |     2 |
| BLAKE  | 2850.00 |     4 |
| CLARK  | 2450.00 |     4 |
| SCOTT  | 3000.00 |     4 |
| KING   | 5000.00 |     5 |
| TURNER | 1500.00 |     3 |
| ADAMS  | 1100.00 |     1 |
| JAMES  |  950.00 |     1 |
| FORD   | 3000.00 |     4 |
| MILLER | 1300.00 |     2 |
+--------+---------+-------+
14 rows in set (0.00 sec)

自连接

自连接是指在同一张表连接查询

显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号–empno)

拆解:要想找到mgr这个人就得通过FORD和mgr的关系查询这个领导编号,最后将领导对应的信息显示

mysql> select ename,empno from emp where emp.empno=(select mgr from emp where ename='FORD');
+-------+--------+
| ename | empno  |
+-------+--------+
| JONES | 007566 |
+-------+--------+
1 row in set (0.00 sec)

使用多表查询(自查询)

表和表本身做笛卡尔积,员工的名字是FORD,在笛卡尔积结果中找出对应的关系mgr和empno,这里会给表取别名不可避免,这样才能使两张相同的表做笛卡尔积结果

mysql> select a.ename,a.empno from emp a,emp b where a.mgr=b.empno and a.ename='FORD';
+-------+--------+
| ename | empno  |
+-------+--------+
| FORD  | 007902 |
+-------+--------+
1 row in set (0.00 sec)

子查询

单行子查询

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询

显示SMITH同一部门的员工

mysql> select *from emp where deptno=(select deptno from emp where ename='SMITH');
+--------+-------+---------+------+---------------------+---------+------+--------+
| empno  | ename | job     | mgr  | hiredate            | sal     | comm | deptno |
+--------+-------+---------+------+---------------------+---------+------+--------+
| 007369 | SMITH | CLERK   | 7902 | 1980-12-17 00:00:00 |  800.00 | NULL |     20 |
| 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
| 007788 | SCOTT | ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL |     20 |
| 007876 | ADAMS | CLERK   | 7788 | 1987-05-23 00:00:00 | 1100.00 | NULL |     20 |
| 007902 | FORD  | ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL |     20 |
+--------+-------+---------+------+---------------------+---------+------+--------+
5 rows in set (0.00 sec)

多行子查询

返回多行记录的子查询

in关键字;查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的

先将部门号为10的所有岗位显示出来当作一个集合,然后再将表中出现在集合中的工作岗位列举出来,<>操作符是不相等的意思

mysql> select ename,job,sal,empno,deptno from emp where job in (select distinct job from emp where deptno=10)and deptnno<>10 ;
+-------+---------+---------+--------+--------+
| ename | job     | sal     | empno  | deptno |
+-------+---------+---------+--------+--------+
| JONES | MANAGER | 2975.00 | 007566 |     20 |
| BLAKE | MANAGER | 2850.00 | 007698 |     30 |
| SMITH | CLERK   |  800.00 | 007369 |     20 |
| ADAMS | CLERK   | 1100.00 | 007876 |     20 |
| JAMES | CLERK   |  950.00 | 007900 |     30 |
+-------+---------+---------+--------+--------+
5 rows in set (0.00 sec)

使用子查询显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号

//部门为30 的最大工资是2850
mysql> select max(sal) from emp where deptno=30;
+----------+
| max(sal) |
+----------+
|  2850.00 |
+----------+
1 row in set (0.00 sec)mysql> select ename,sal,deptno from emp where sal > (select max(sal) from emp where deptno=30);
+-------+---------+--------+
| ename | sal     | deptno |
+-------+---------+--------+
| JONES | 2975.00 |     20 |
| SCOTT | 3000.00 |     20 |
| KING  | 5000.00 |     10 |
| FORD  | 3000.00 |     20 |
+-------+---------+--------+
4 rows in set (0.00 sec)

all关键字显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号

mysql> select ename,sal,deptno from emp where sal >all(select sal from emp where deptno=30);
+-------+---------+--------+
| ename | sal     | deptno |
+-------+---------+--------+
| JONES | 2975.00 |     20 |
| SCOTT | 3000.00 |     20 |
| KING  | 5000.00 |     10 |
| FORD  | 3000.00 |     20 |
+-------+---------+--------+
4 rows in set (0.00 sec)

any关键字;显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门的员工)

//部门为30的员工最低工资
mysql> select min(sal) from emp where deptno=30;
+----------+
| min(sal) |
+----------+
|   950.00 |
+----------+
1 row in set (0.00 sec)//显示所有大于部门30工资的员工信息,包括自己的部门的员工
mysql> select ename,sal,deptno from emp where sal > any(select sal from emp where deptno=30);
+--------+---------+--------+
| ename  | sal     | deptno |
+--------+---------+--------+
| ALLEN  | 1600.00 |     30 |
| WARD   | 1250.00 |     30 |
| JONES  | 2975.00 |     20 |
| MARTIN | 1250.00 |     30 |
| BLAKE  | 2850.00 |     30 |
| CLARK  | 2450.00 |     10 |
| SCOTT  | 3000.00 |     20 |
| KING   | 5000.00 |     10 |
| TURNER | 1500.00 |     30 |
| ADAMS  | 1100.00 |     20 |
| FORD   | 3000.00 |     20 |
| MILLER | 1300.00 |     10 |
+--------+---------+--------+
12 rows in set (0.00 sec)

多列子查询

单行子查询是指子查询只返回单列,单行数据;多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子 查询则是指查询返回多个列数据的子查询语句

查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人

mysql> select * from emp where (deptno,job)=(select deptno,job from emp where ename='SMITH') and ename<> 'SMITH';
+--------+-------+-------+------+---------------------+---------+------+--------+
| empno  | ename | job   | mgr  | hiredate            | sal     | comm | deptno |
+--------+-------+-------+------+---------------------+---------+------+--------+
| 007876 | ADAMS | CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 | NULL |     20 |
+--------+-------+-------+------+---------------------+---------+------+--------+
1 row in set (0.00 sec)

在from子句中使用子查询

子查询语句出现在from子句中。这里要用到数据查询的技巧,把一个子查询当做一个临时表使用。

显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资

mysql> select * from emp ,(select deptno,avg(sal) asal from emp group by deptno) as tmp where emp.deptno=tmp.deptno and emp.sal>asal;
+--------+-------+-----------+------+---------------------+---------+--------+--------+--------+-------------+
| empno  | ename | job       | mgr  | hiredate            | sal     | comm   | deptno | deptno | asal        |
+--------+-------+-----------+------+---------------------+---------+--------+--------+--------+-------------+
| 007499 | ALLEN | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 | 300.00 |     30 |     30 | 1566.666667 |
| 007566 | JONES | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |   NULL |     20 |     20 | 2175.000000 |
| 007698 | BLAKE | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |   NULL |     30 |     30 | 1566.666667 |
| 007788 | SCOTT | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |   NULL |     20 |     20 | 2175.000000 |
| 007839 | KING  | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |   NULL |     10 |     10 | 2916.666667 |
| 007902 | FORD  | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |   NULL |     20 |     20 | 2175.000000 |
+--------+-------+-----------+------+---------------------+---------+--------+--------+--------+-------------+
6 rows in set (0.00 sec)

查找每个部门工资最高的人的姓名、工资、部门、最高工资

mysql> select emp.ename,emp.deptno,emp.sal  from emp, (select deptno,max(sal) mysal from emp group by deptno) as tmpwhere emp.deptno=tmp.deptno and emp.sal = mysal;
+-------+--------+---------+
| ename | deptno | sal     |
+-------+--------+---------+
| BLAKE |     30 | 2850.00 |
| SCOTT |     20 | 3000.00 |
| KING  |     10 | 5000.00 |
| FORD  |     20 | 3000.00 |
+-------+--------+---------+
4 rows in set (0.00 sec)

显示每个部门的信息(部门名,编号,地址)和人员数量

方法1:使用多表

讲emp表和dept表做笛卡尔积,再对deptno、dname、loc进行分组筛选出每个部门的信息

mysql> select dept.deptno,dept.loc,dept.dname,count(*) from dept,emp where dept.deptno=emp.deptno group by dept.deptno
o,dept.dname,dept.loc;
+--------+----------+------------+----------+
| deptno | loc      | dname      | count(*) |
+--------+----------+------------+----------+
|     10 | NEW YORK | ACCOUNTING |        3 |
|     20 | DALLAS   | RESEARCH   |        5 |
|     30 | CHICAGO  | SALES      |        6 |
+--------+----------+------------+----------+
3 rows in set (0.00 sec)

方法2:使用子查询

mysql> select dept.deptno,loc,dname mc from dept,(select deptno,count(*)mc from emp group by deptno) tmp where tmp.deptno=dept.deptno;
+--------+----------+------------+
| deptno | loc      | mc         |
+--------+----------+------------+
|     10 | NEW YORK | ACCOUNTING |
|     20 | DALLAS   | RESEARCH   |
|     30 | CHICAGO  | SALES      |
+--------+----------+------------+
3 rows in set (0.01 sec)

合并查询

在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all

union

该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行

案例:将工资大于2500或职位是MANAGER的人找出来

mysql> select ename,job,sal from emp where sal>2500 union select ename,job,sal from emp where job='MANAGER';
+-------+-----------+---------+
| ename | job       | sal     |
+-------+-----------+---------+
| JONES | MANAGER   | 2975.00 |
| BLAKE | MANAGER   | 2850.00 |
| SCOTT | ANALYST   | 3000.00 |
| KING  | PRESIDENT | 5000.00 |
| FORD  | ANALYST   | 3000.00 |
| CLARK | MANAGER   | 2450.00 |
+-------+-----------+---------+

union all

该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。

案例:将工资大于25000或职位是MANAGER的人找出来

mysql> select ename,job,sal from emp where sal>2500 union all select ename,job,sal from emp where job='MANAGER';
+-------+-----------+---------+
| ename | job       | sal     |
+-------+-----------+---------+
| JONES | MANAGER   | 2975.00 |
| BLAKE | MANAGER   | 2850.00 |
| SCOTT | ANALYST   | 3000.00 |
| KING  | PRESIDENT | 5000.00 |
| FORD  | ANALYST   | 3000.00 |
| JONES | MANAGER   | 2975.00 |
| BLAKE | MANAGER   | 2850.00 |
| CLARK | MANAGER   | 2450.00 |
+-------+-----------+---------+
8 rows in set (0.00 sec)

Mysql入门宝典【硬核前方高能,佬有所学】相关推荐

  1. 硬核!用Mac Mini翻新了一台12年前的电脑

    本文转载自 差评君 有这么一位差友,不知道从哪儿加到了托尼的微信,都还没打招呼呢,上来就向我展现了他最近的硬核杰作. 他将 M1 款的 Mac Mini 塞进了 09 年款 27 寸 iMac,并把详 ...

  2. 程序员硬核宝典(面试题集、在线免费工具箱)

    今天给大家分享一些程序员面试题集以及一个在线免费工具箱,废话休说,直奔主题: 一.程序员硬核知识 1.大厂面试指北 http://notfound9.github.io/interviewGuide/ ...

  3. mysql long类型_怒肝两个月MySQL源码,我总结出这篇2W字的MySQL协议详解(超硬核干货)!!...

    点击上方蓝色"冰河技术",关注并选择"设为星标" 持之以恒,贵在坚持,每天进步一点点! 作者个人研发的在高并发场景下,提供的简单.稳定.可扩展的延迟消息队列框架 ...

  4. 程序员需要了解的硬核知识之操作系统入门

    对于程序员来说,最莫大的荣耀莫过于自己的软件被大多数人使用了吧. 历史文章请戳 程序员需要了解的硬核知识之内存 程序员需要了解的硬核知识之CPU 程序员需要了解的硬核知识之二进制 程序员需要了解的硬核 ...

  5. 计算机软硬知识有哪些,电脑入门硬核必备知识大全

    计算机视觉是人工智能技术的一个重要领域,打个比方(不一定恰当),我认为计算机视觉是人工智能时代的眼睛,可见其重要程度.计算机视觉其实是一个很宏大的概念,下图是有人总结的计算机视觉所需要的技能树.下面就 ...

  6. 别瞎学了,我的MySQL学习之路(超详细超硬核)

    大家好,我是帅地. 在之前校招面试中,mysql 被问到频率是真的高,当初为了能够在 mysql 这块加分,看了不少书籍,在网上也找了不少资料,走了不少弯路,庆幸的是,每次面试官问到 mysql 相关 ...

  7. 全网最硬核PWN入门_图解分析

    PWN 序 Linux环境下的基础知识 从C源码到可执行文件的生成过程 程序的编译与链接 什么是可执行文件 可执行文件分类PE/ELF ELF文件格式 区分节和段的存储区域 加载ELF / 查看节和段 ...

  8. 入门到精通,阿里架构师撰写的两份MySQL技术宝典,已经超神

    前言 MySQL是世界上最受欢迎的数据库管理系统之一. 为什么这样说呢?答案就是-- 用在小型开发项目上,还是用来构建那些声名显赫的网站,MySQL都证明了自己是个稳定.可靠.快速.可信的系统,足以胜 ...

  9. 史上最硬核的Linux依赖问题解决方案

    最近正好在研究dpkg和rpm,对Linux依赖有了更深的认识. 在网上看了很多,所有docker.虚拟机.编译安装.以及各种另辟蹊径的答案 都是面向日常繁重的业务没时间折腾而不得已做出的妥协和让步. ...

最新文章

  1. java 装配_java – 无法自动装配方法
  2. 【Socket网络编程】15. 发送端和接收端数据大小不一致时 的分析
  3. python动态图片转字符画_GIF动态图,视频?都能用Python转换成字符画图像
  4. 显示SAP Spartacus每个page slot使用的Angular Component uid
  5. 后怎么恢复_爬山后小腿肌肉酸痛怎么办 ?这样来恢复!|新生活公社
  6. 给定一个由n个数字组成的数组,请检查是否存在重复项
  7. JavaScript中的innerHTML,innerHTML,value属性
  8. 关于日志打印的几点建议以及非最佳实践
  9. 3D中obj文件操作
  10. windows Server 2008+iis 7.5 部署应用程序
  11. DRILLNET 2.0------第二十章 高温高压钻井水力计算模型
  12. 再探结构体字节对齐问题
  13. cxgrid 行合并单元格_Excel合并单元格无法筛选和排序,你必须掌握这3个小技巧...
  14. 北斗一号卫星授时技术及在电力系统中的应用
  15. LimeSDR实验教程(5) WiFi解调
  16. 以数为本、谋求智变,联通大数据“跑步”进入发展新阶段!
  17. 无法解析的外部符号 _transfer_8to16copy_3dne
  18. 有了这 15 款编程游戏,谁都可以学编程!
  19. npoi获取合并单元格_梦琪小生 C# 如何使用NPOI操作Excel以及读取合并单元格等
  20. Matlab中的diag函数用法

热门文章

  1. pycharm专业版 激活+汉化
  2. 数据挖掘实验(二):主成分分析PCA R语言
  3. toad mysql导入excel_toad导入表数据库
  4. Level2行情接口
  5. 数据库原理第六章课后题答案(第四版)
  6. 弹性云服务器是什么,大家怎样租用云服务器才可靠?
  7. 高精度加法C++(acwing复习题)
  8. Linux转换图形界面与命令行界面
  9. 电脑颜色变成黑白色了怎么调回来
  10. “from win32 import win32api“标红问题