MySQL基础【学习至基本语句】

这篇具有很好参考价值的文章主要介绍了MySQL基础【学习至基本语句】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


操作系统:CentOS 8
数据库版本:8.0.26 Source distribution

一、安装与配置

1、安装

yum install -y mysql-server.x86_64

2、MySQL安装完成后,启动报错,查看MySQL的状态,发现是3306端口被占用

[root@iZ56kkvaq4nlfhZ etc]# systemctl status mysqld.service
● mysqld.service - MySQL 8.0 database server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; disabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Tue 2023-09-12 18:58:37 CST; 10s ago
  Process: 655712 ExecStopPost=/usr/libexec/mysql-wait-stop (code=exited, status=0/SUCCESS)
  Process: 655672 ExecStart=/usr/libexec/mysqld --basedir=/usr (code=exited, status=1/FAILURE)
  Process: 655635 ExecStartPre=/usr/libexec/mysql-prepare-db-dir mysqld.service (code=exited, status=0/SUCCESS)
  Process: 655610 ExecStartPre=/usr/libexec/mysql-check-socket (code=exited, status=0/SUCCESS)
 Main PID: 655672 (code=exited, status=1/FAILURE)
   Status: "Server startup in progress"
    Error: 98 (Address already in use)

Sep 12 18:58:34 iZ56kkvaq4nlfhZ systemd[1]: Starting MySQL 8.0 database server...
Sep 12 18:58:37 iZ56kkvaq4nlfhZ systemd[1]: mysqld.service: Main process exited, code=exited, status=1/FAILURE
Sep 12 18:58:37 iZ56kkvaq4nlfhZ systemd[1]: mysqld.service: Failed with result 'exit-code'.
Sep 12 18:58:37 iZ56kkvaq4nlfhZ systemd[1]: Failed to start MySQL 8.0 database server.
[root@iZ56kkvaq4nlfhZ etc]# 

此时,可以查询是谁占用了3306,然后把占用进程kill掉,此处就可以使用命令kill 57039,但是我不想这么做,这个进程和我的一个服务有关,不能杀

[root@iZ56kkvaq4nlfhZ etc]# lsof -i :3306
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
mysqld  57039  www   35u  IPv6 149967      0t0  TCP *:mysql (LISTEN)
[root@iZ56kkvaq4nlfhZ etc]# netstat -anp | grep :3306
tcp6       0      0 :::3306                 :::*                    LISTEN      57039/mysqld 

于是,我选择修改MySQL的启动端口,将启动端口修改为3307,编辑下面的配置文件

 vim /etc/my.cnf.d/mysql-server.cnf

添加一行内容,如下:

port=3307

此时配置文件就变成了:

[root@iZ56kkvaq4nlfhZ ~]# cat /etc/my.cnf.d/mysql-server.cnf 
#
# This group are read by MySQL server.
# Use it for options that only the server (but not clients) should see
#
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/en/server-configuration-defaults.html

# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mysqld according to the
# instructions in http://fedoraproject.org/wiki/Systemd

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysql/mysqld.log
pid-file=/run/mysqld/mysqld.pid
port=3307    # 添加这一行,端口修改为3307

[root@iZ56kkvaq4nlfhZ ~]# 

然后重启MySQL,就可以正常启动了

[root@iZ56kkvaq4nlfhZ etc]# systemctl restart mysqld.service 
[root@iZ56kkvaq4nlfhZ etc]# systemctl status mysqld.service 
● mysqld.service - MySQL 8.0 database server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; disabled; vendor prese>   Active: active (running) since Tue 2023-09-12 19:09:51 CST; 16min ago
  Process: 655712 ExecStopPost=/usr/libexec/mysql-wait-stop (code=exited, status=>  Process: 656204 ExecStartPost=/usr/libexec/mysql-check-upgrade (code=exited, st>  Process: 656122 ExecStartPre=/usr/libexec/mysql-prepare-db-dir mysqld.service (>  Process: 656097 ExecStartPre=/usr/libexec/mysql-check-socket (code=exited, stat> Main PID: 656159 (mysqld)
   Status: "Server is operational"
    Tasks: 37 (limit: 10836)
   Memory: 354.7M
   CGroup: /system.slice/mysqld.service
           └─656159 /usr/libexec/mysqld --basedir=/usr

Sep 12 19:09:50 iZ56kkvaq4nlfhZ systemd[1]: Starting MySQL 8.0 database server...
Sep 12 19:09:51 iZ56kkvaq4nlfhZ systemd[1]: Started MySQL 8.0 database server.

修改MySQL的密码,修改密码之后,再登录MySQL需要使用密码。

mysql  # 进入MySQL命令行
# MySQL的用户名密码存储在这个数据库中,修改密码,必须使用这个数据库
mysql> use mysql;   
# 查看数据库中的用户
mysql> select user,host from mysql.user;
+------------------+-----------+
| user             | host      |
+------------------+-----------+
| mysql.infoschema | localhost |
| mysql.session    | localhost |
| mysql.sys        | localhost |
| root             | localhost |
+------------------+-----------+
4 rows in set (0.00 sec)
# 修改'root'@'localhost'的密码
mysql> alter user 'root'@'localhost' identified with mysql_native_password by '12345';
Query OK, 0 rows affected (0.01 sec)
# 刷新权限
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> 
# 此时端口开放3307
mysql> show variables like '%port%' ;
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| admin_port               | 33062 |
| large_files_support      | ON    |
| mysqlx_port              | 33060 |
| mysqlx_port_open_timeout | 0     |
| port                     | 3307  |
| report_host              |       |
| report_password          |       |
| report_port              | 3307  |
| report_user              |       |
| require_secure_transport | OFF   |
+--------------------------+-------+
10 rows in set (0.01 sec)

mysql> exit
Bye

设置MySQL监听所有IP,更改配置文件后重启MySQL

[root@iZ56kkvaq4nlfhZ etc]# vim /etc/my.cnf.d/mysql-server.cnf 
[root@iZ56kkvaq4nlfhZ etc]# cat /etc/my.cnf.d/mysql-server.cnf
#
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysql/mysqld.log
pid-file=/run/mysqld/mysqld.pid
port=3307
bind-address=0.0.0.0   # 添加这一行
[root@iZ56kkvaq4nlfhZ etc]#
[root@iZ56kkvaq4nlfhZ etc]# systemctl restart mysqld.service 
[root@iZ56kkvaq4nlfhZ etc]# systemctl status mysqld.service 
● mysqld.service - MySQL 8.0 database server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; disabled; vendor preset: disabled)
   Active: active (running) since Tue 2023-09-12 20:56:18 CST; 11s ago
  Process: 657283 ExecStopPost=/usr/libexec/mysql-wait-stop (code=exited, status=0/SUCCESS)
  Process: 657493 ExecStartPost=/usr/libexec/mysql-check-upgrade (code=exited, status=0/SUCCESS)
  Process: 657411 ExecStartPre=/usr/libexec/mysql-prepare-db-dir mysqld.service (code=exited, status=0/SUCCESS)
  Process: 657385 ExecStartPre=/usr/libexec/mysql-check-socket (code=exited, status=0/SUCCESS)
 Main PID: 657448 (mysqld)
   Status: "Server is operational"
    Tasks: 38 (limit: 10836)
   Memory: 356.1M
   CGroup: /system.slice/mysqld.service
           └─657448 /usr/libexec/mysqld --basedir=/usr

Sep 12 20:56:17 iZ56kkvaq4nlfhZ systemd[1]: Starting MySQL 8.0 database server...
Sep 12 20:56:18 iZ56kkvaq4nlfhZ systemd[1]: Started MySQL 8.0 database server.
[root@iZ56kkvaq4nlfhZ etc]#

创建一个可以远程连接的root用户

CREATE USER 'root'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;

二、常用命令

1、创建数据库

先登录数据库

[root@iZ56kkvaq4nlfhZ ~]# mysql -u root -p
Enter password:     # 这里输入数据库密码
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.26 Source distribution
.........
.........

然后,我们查看一下MySQL中有哪些数据库,命令如下:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.01 sec)

mysql> 

现在创建一个名为 game的数据库

mysql> create database game;
Query OK, 1 row affected (0.00 sec)

mysql>

此时再查看一下数据库,会发现多了一个game

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| game               |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql> 

2、删除数据库

现在删除刚才新建的数据库game

mysql> DROP DATABASE game;
Query OK, 0 rows affected (0.01 sec)

此时再查看,game已被删除

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

mysql> 

3、创建表

  在MySQL中,数据类型定义了每个列可以存储的数据类型。以下是一些主要的数据类型
  1、字符串数据类型:包括CHAR,VARCHAR,TINYTEXT,TEXT,MEDIUMTEXT,LONGTEXT和BLOB。CHAR和VARCHAR都用于存储非二进制字符串,但CHAR存储固定长度的字符串(最大255个字符),而VARCHAR存储可变长度的字符串(最大65535个字符)。TINYTEXT,TEXT,MEDIUMTEXT和LONGTEXT用于存储大量文本数据,它们之间的主要区别在于它们可以存储的文本的最大长度32。BLOB用于存储二进制对象,通常用于存储文件、图像等多媒体文件
   2、数值数据类型:包括整数类型(如INTEGER,SMALLINT),定点类型(如DECIMAL,NUMERIC),浮点类型(如FLOAT,DOUBLE)和位值类型(如BIT)。整数类型用于存储整数值,定点类型用于存储精确的小数值,浮点类型用于存储近似的小数值,位值类型用于存储位值。
  3、日期和时间数据类型:包括DATE,TIME,DATETIME和TIMESTAMP。DATE用于存储日期部分但没有时间部分的值,TIME用于存储时间部分但没有日期部分的值,DATETIME和TIMESTAMP都用于存储包含日期和时间部分的值
  4、空间数据类型:MySQL支持OpenGIS类对应的空间数据类型。这些类型包括单一几何值的类型(如GEOMETRY,POINT,LINESTRING和POLYGON)以及集合值的类型(如MULTIPOINT,MULTILINESTRING,MULTIPOLYGON和GEOMETRYCOLLECTION)。
  5、JSON数据类型:MySQL从5.7.8版本开始支持原生JSON数据类型。这种数据类型允许您更有效地存储JSON文档。

先新建一个数据库名为game

mysql> CREATE DATABASE game;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| game               |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql> 

选择使用game数据库

mysql> use game;
Database changed
mysql>

在game数据库中新建一个名为player的表,其中id为int类型,姓名字段name为varchar类型,等等

mysql> create table player (id int,name varchar(100),level int, exp int,glod decimal(10,2));
Query OK, 0 rows affected (0.02 sec)
 
mysql> show tables;  # 查看数据库中的表
+----------------+
| Tables_in_game |
+----------------+
| player         |
+----------------+
1 row in set (0.00 sec)

使用desc语句查看表

mysql> desc player;
+-------+---------------+------+-----+---------+-------+
| Field | Type          | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| id    | int           | YES  |     | NULL    |       |
| name  | varchar(100)  | YES  |     | NULL    |       |
| level | int           | YES  |     | NULL    |       |
| exp   | int           | YES  |     | NULL    |       |
| glod  | decimal(10,2) | YES  |     | NULL    |       |
+-------+---------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

mysql> 

4、修改表

修改字段类型
此时,我发现player表中,name字段的长度不够,想增加长度,这时可以使用alter语句来修改表结构
alter table后加表名,modify column表示修改列,后面加列名,varchar(200)是修改后的name字段的长度。

mysql> alter table player modify column name varchar(200);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc player;
+-------+---------------+------+-----+---------+-------+
| Field | Type          | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| id    | int           | YES  |     | NULL    |       |
| name  | varchar(200)  | YES  |     | NULL    |       |
| level | int           | YES  |     | NULL    |       |
| exp   | int           | YES  |     | NULL    |       |
| glod  | decimal(10,2) | YES  |     | NULL    |       |
+-------+---------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

mysql> 

修改字段名称
字段的名称也可以修改,此时我要把name修改为nick_name
alter table后加表名, rename column后加需要修改的字段名,to 后加修改后的字段名。

mysql> alter table player rename column name to nick_name;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc player;
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| id        | int           | YES  |     | NULL    |       |
| nick_name | varchar(200)  | YES  |     | NULL    |       |
| level     | int           | YES  |     | NULL    |       |
| exp       | int           | YES  |     | NULL    |       |
| glod      | decimal(10,2) | YES  |     | NULL    |       |
+-----------+---------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

mysql> 

添加字段。
在表中添加一个last_login字段,用来记录上次登录游戏的时间。alter table后加表名,add column后加即将被添加的字段名称,后面跟这个字段的数据类型,此处数据类型是datetime

mysql> alter table player add column last_login datetime;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc player;
+------------+---------------+------+-----+---------+-------+
| Field      | Type          | Null | Key | Default | Extra |
+------------+---------------+------+-----+---------+-------+
| id         | int           | YES  |     | NULL    |       |
| nick_name  | varchar(200)  | YES  |     | NULL    |       |
| level      | int           | YES  |     | NULL    |       |
| exp        | int           | YES  |     | NULL    |       |
| glod       | decimal(10,2) | YES  |     | NULL    |       |
| last_login | datetime      | YES  |     | NULL    |       |
+------------+---------------+------+-----+---------+-------+
6 rows in set (0.01 sec)

mysql> 

删除字段。
将刚刚添加的last_login字段删除。
alter table后加表名,drop column后加需要删除的字段名。

mysql> alter table player drop column last_login;
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc player;
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| id        | int           | YES  |     | NULL    |       |
| nick_name | varchar(200)  | YES  |     | NULL    |       |
| level     | int           | YES  |     | NULL    |       |
| exp       | int           | YES  |     | NULL    |       |
| glod      | decimal(10,2) | YES  |     | NULL    |       |
+-----------+---------------+------+-----+---------+-------+
5 rows in set (0.01 sec)

mysql> 

删除表
删除表player,drop table后加需要删除的表的名称。

mysql> drop table player;
Query OK, 0 rows affected (0.01 sec)

# 此时再查看表player,就会提示错误,表不存在
mysql> desc player;  
ERROR 1146 (42S02): Table 'game.player' doesn't exist
mysql> 

5、操作表中的数据(数据的增删改查)

把删除的表player再新建回来。

mysql> create table player (id int,name varchar(100),level int, exp int,glod decimal(10,2));
Query OK, 0 rows affected (0.02 sec)

mysql> desc player;
+-------+---------------+------+-----+---------+-------+
| Field | Type          | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| id    | int           | YES  |     | NULL    |       |
| name  | varchar(100)  | YES  |     | NULL    |       |
| level | int           | YES  |     | NULL    |       |
| exp   | int           | YES  |     | NULL    |       |
| glod  | decimal(10,2) | YES  |     | NULL    |       |
+-------+---------------+------+-----+---------+-------+
5 rows in set (0.01 sec)

mysql> 

插入数据
在表player中插入一条数据,insert into后加表名,后面再跟字段名,values后加要插入的信息。

mysql> insert into player (id, name, level, exp, glod) values (1,' 张三', 1, 1, 1);
Query OK, 1 row affected (0.00 sec)

mysql> 

没有列出的字段名将会以默认值填充。下面这条命令只插入了id, name, level这三个字段的数据,剩下的exp和glod字段将被默认值填充。

mysql> insert into player (id, name, level) values (3, '王五', 0);
Query OK, 1 row affected (0.00 sec)

mysql>

如果字段名和要插入的信息一一对应,那么字段名可以省略。

mysql> insert into player values (2,'李四', 2, 2, 2);
Query OK, 1 row affected (0.00 sec)

mysql> 

使用insert关键字,可以一次插入多条数据,多条数据之间用,隔开。

mysql> insert into player (id, name) values (4,'Tom'),(5,'Jerry');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

查询数据
查看刚才插入的数据,select后面跟要查询的列名,* 代表查询所有列,from后加要查询的表名,表示从哪个表来查询数据。

mysql> select * from player;
+------+--------+-------+------+------+
| id   | name   | level | exp  | glod |
+------+--------+-------+------+------+
|    1 | 张三   |     1 |    1 | 1.00 |
|    2 | 李四   |     2 |    2 | 2.00 |
|    3 | 王五   |     0 | NULL | NULL |
|    4 | Tom    |  NULL | NULL | NULL |
|    5 | Jerry  |  NULL | NULL | NULL |
+------+--------+-------+------+------+
5 rows in set (0.00 sec)

mysql> 

建表时,没有指定默认值,所以现在的默认值是NULL,现在修改表结构,为其中level字段指定默认值。default后面跟默认值

mysql> alter table player modify level int default 1;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> 

此时再插入一条数据,看看level的默认值是否生效

mysql> insert into player (id, name) values (6,'菜虚鲲');
Query OK, 1 row affected (0.00 sec)

mysql> select * from player;
+------+-----------+-------+------+------+
| id   | name      | level | exp  | glod |
+------+-----------+-------+------+------+
|    1 | 张三      |     1 |    1 | 1.00 |
|    2 | 李四      |     2 |    2 | 2.00 |
|    3 | 王五      |     0 | NULL | NULL |
|    4 | Tom       |  NULL | NULL | NULL |
|    5 | Jerry     |  NULL | NULL | NULL |
|    6 | 菜虚鲲    |     1 | NULL | NULL |
+------+-----------+-------+------+------+
6 rows in set (0.00 sec)

mysql> 

更新数据
现在Tom和Jerry的level还是NULL,可以使用update关键字来让他们的level变为1。
updata后加表名,set后加字段名,=后加修改后的值,where后加需要修改的数据的唯一特征。

mysql> update player set level = 1 where name = 'Tom';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update player set level = 1 where name = 'Jerry';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from player;
+------+-----------+-------+------+------+
| id   | name      | level | exp  | glod |
+------+-----------+-------+------+------+
|    1 | 张三      |     1 |    1 | 1.00 |
|    2 | 李四      |     2 |    2 | 2.00 |
|    3 | 王五      |     0 | NULL | NULL |
|    4 | Tom       |     1 | NULL | NULL |
|    5 | Jerry     |     1 | NULL | NULL |
|    6 | 菜虚鲲    |     1 | NULL | NULL |
+------+-----------+-------+------+------+
6 rows in set (0.00 sec)

mysql> 

这样每次修改一条数据太低效,把where子句去掉就可以对全部数据生效了。现在把所有玩家的exp和gold的都改为0,多个字段之间用,隔开。

mysql> update player set exp = 0, glod = 0;
Query OK, 6 rows affected (0.00 sec)
Rows matched: 6  Changed: 6  Warnings: 0

mysql> select * from player;
+------+-----------+-------+------+------+
| id   | name      | level | exp  | glod |
+------+-----------+-------+------+------+
|    1 | 张三      |     1 |    0 | 0.00 |
|    2 | 李四      |     2 |    0 | 0.00 |
|    3 | 王五      |     0 |    0 | 0.00 |
|    4 | Tom       |     1 |    0 | 0.00 |
|    5 | Jerry     |     1 |    0 | 0.00 |
|    6 | 菜虚鲲    |     1 |    0 | 0.00 |
+------+-----------+-------+------+------+
6 rows in set (0.00 sec)

mysql> 

删除数据
删除gold为0的玩家,然后所有的玩家都被删除了。
delete from后加表名,where后加筛选条件。

mysql> delete from player where glod = 0;
Query OK, 6 rows affected (0.00 sec)

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

mysql> exit;     # 退出数据库
Bye

6、数据的导入导出

数据库的导出
导出数据库game在CnetOS命令行输入以下命令,mysqldump -u root -p后加数据库名和表名,>后加导出到的目录和文件名。表名可以省略不写,这样会将数据中的所有数据都导出

[root@iZ56kkvaq4nlfhZ ~]# mysqldump -u root -p game player > game.sql
Enter password: 
[root@iZ56kkvaq4nlfhZ ~]# ls 
14290                          game.sql    pikachu
frp_0.44.0_linux_amd64.tar.gz  index.html  sqli-labs
[root@iZ56kkvaq4nlfhZ ~]# 

查看文件game.sql的内容,发现里面是一条条的sql语句,是建立这个数据库用的

[root@iZ56kkvaq4nlfhZ ~]# cat game.sql 
-- MySQL dump 10.13  Distrib 8.0.26, for Linux (x86_64)
--
-- Host: localhost    Database: game
-- ------------------------------------------------------
-- Server version       8.0.26

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `player`
--

DROP TABLE IF EXISTS `player`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `player` (
  `id` int DEFAULT NULL,
  `name` varchar(100) DEFAULT NULL,
  `level` int DEFAULT '1',
  `exp` int DEFAULT NULL,
  `glod` decimal(10,2) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `player`
文件内容太多,省略了

数据库的导入
在Linux命令行,将刚才导出的数据库game导入。在导入sql文件之前,要确保已经存在一个数据库,数据库的名字和sql文件的名字相同。
-u指定数据库的用户名,-p指定数据库密码,mysql -u root -p 后加要导入的数据库的名字,<后加需要被导进去的sql文件

[root@iZ56kkvaq4nlfhZ ~]# mysql -u root -p game <game.sql 
Enter password: 
[root@iZ56kkvaq4nlfhZ ~]# 

把练习用的的数据库导进MySQL中。需要用到的数据库放在下面了。

链接:https://pan.baidu.com/s/1tKT4I_O4m66iBwXKRFVz9Q?pwd=ti80
提取码:ti80

我将练习用的sql文件放在sql_dir 文件夹中,一会要登录数据库创建和sql文件同名的数据库

[root@iZ56kkvaq4nlfhZ buqian_log]# cd
[root@iZ56kkvaq4nlfhZ ~]# ls sql_dir/
city_data.sql  game.sql    sale.sql  world.sql
company.sql    sakila.sql  shop.sql
[root@iZ56kkvaq4nlfhZ ~]#

进入MySQL,删除数据库game中的数据,以便稍后导入game.sql

mysql> use game;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> drop table player;
Query OK, 0 rows affected (0.02 sec)

mysql> show tables;
Empty set (0.00 sec)

mysql> 

创建和sql文件同名的数据库

mysql> create database city_data;
Query OK, 1 row affected (0.00 sec)

mysql> create database sale;
Query OK, 1 row affected (0.01 sec)

mysql> create database world;
Query OK, 1 row affected (0.01 sec)

mysql> create database company;
Query OK, 1 row affected (0.00 sec)

mysql> create database sakila;
Query OK, 1 row affected (0.01 sec)

mysql> create database shop;
Query OK, 1 row affected (0.01 sec)
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| city_data          |
| company            |
| game               |
| information_schema |
| mysql              |
| performance_schema |
| sakila             |
| sale               |
| shop               |
| sys                |
| world              |
+--------------------+
11 rows in set (0.00 sec)

mysql> exit;
Bye 

导入 sql文件

[root@iZ56kkvaq4nlfhZ ~]# cd sql_dir/
[root@iZ56kkvaq4nlfhZ sql_dir]# ls
city_data.sql  game.sql    sale.sql  world.sql
company.sql    sakila.sql  shop.sql
[root@iZ56kkvaq4nlfhZ sql_dir]# 
[root@iZ56kkvaq4nlfhZ sql_dir]# mysql -u root -p city_data < city_data.sql 
Enter password: 
[root@iZ56kkvaq4nlfhZ sql_dir]# mysql -u root -p game < game.sql 
Enter password: 
[root@iZ56kkvaq4nlfhZ sql_dir]# mysql -u root -p sale < sale.sql 
Enter password: 
[root@iZ56kkvaq4nlfhZ sql_dir]# mysql -u root -p world < world.sql 
Enter password: 
[root@iZ56kkvaq4nlfhZ sql_dir]# mysql -u root -p company < company.sql 
Enter password: 
[root@iZ56kkvaq4nlfhZ sql_dir]# mysql -u root -p sakila < sa
sakila.sql  sale.sql    
[root@iZ56kkvaq4nlfhZ sql_dir]# mysql -u root -p sakila < sakila.sql 
Enter password: 
[root@iZ56kkvaq4nlfhZ sql_dir]# mysql -u root -p shop < shop.sql 
Enter password: 
[root@iZ56kkvaq4nlfhZ sql_dir]# 

三、 常用语句

1、where子句

where子句用来查找哪些满足指定标准的记录,可以同select,update,delete一起使用。
比较运算符
查找表player中level为1的玩家。除了等号之外,其他的比较运算符(<、>、>=、<=、!=等)也可以使用。

mysql> select * from player where level=1;
+------+-----------+------+---------------------+-------+------+-------+
| id   | name      | sex  | email               | level | exp  | gold  |
+------+-----------+------+---------------------+-------+------+-------+
|   17 | 吕秀才    || lvxiucai@gmail.com  |     1 |    2 |  3.00 |
|  131 | 弈星      || yixing@geekhour.net |     1 |   61 | 90.00 |
+------+-----------+------+---------------------+-------+------+-------+
2 rows in set (0.00 sec)

mysql> 

逻辑运算符
使用and连接多个条件
查找level>1且level<5的玩家。除了and之外还可以使用not和or,当三者同时使用时,其优先级是not > and > or,也可以shiyong()来改变优先级

mysql> select * from player where level > 1 and level < 5;
+------+-----------+------+-----------------------+-------+------+-------+
| id   | name      | sex  | email                 | level | exp  | gold  |
+------+-----------+------+-----------------------+-------+------+-------+
|    1 | 张三      || zhangsan@gmail.com    |     3 |   19 | 20.00 |
|    2 | 赵四儿    || zhaosier@geekhour.net |     4 |   22 | 26.00 |
+------+-----------+------+-----------------------+-------+------+-------+
2 rows in set (0.00 sec)

mysql> 

查找level大于1小于5或exp大于1小于5的玩家

mysql> select * from player where level > 1 and level < 5 or exp > 1 and exp < 5;
+------+-----------+------+-------------------------+-------+------+-------+
| id   | name      | sex  | email                   | level | exp  | gold  |
+------+-----------+------+-------------------------+-------+------+-------+
|    1 | 张三      || zhangsan@gmail.com      |     3 |   19 | 20.00 |
|    2 | 赵四儿    || zhaosier@geekhour.net   |     4 |   22 | 26.00 |
|   17 | 吕秀才    || lvxiucai@gmail.com      |     1 |    2 |  3.00 |
|   19 | 佟湘玉    || tongxiangyu@163.com     |    99 |    4 | 10.00 |
|   50 | 高启强    || gaoqiqiang@geekhour.net |    88 |    3 | 30.00 |
|  136 | 女娲      || nvwa@qq.com             |    89 |    2 | 86.00 |
+------+-----------+------+-------------------------+-------+------+-------+
6 rows in set (0.00 sec)

mysql> 

in 指定多个值
查找level为1、3、5的玩家

mysql> select * from player where level in (1,3,5);
+------+-----------+------+---------------------+-------+------+-------+
| id   | name      | sex  | email               | level | exp  | gold  |
+------+-----------+------+---------------------+-------+------+-------+
|    1 | 张三      || zhangsan@gmail.com  |     3 |   19 | 20.00 |
|   17 | 吕秀才    || lvxiucai@gmail.com  |     1 |    2 |  3.00 |
|   37 | 慕容复    || murongfu@gmail.com  |     5 |   49 | 38.00 |
|  131 | 弈星      || yixing@geekhour.net |     1 |   61 | 90.00 |
+------+-----------+------+---------------------+-------+------+-------+
4 rows in set (0.00 sec)

mysql> 

between and来指定某个字段查找范围
查找level在1到10之间的玩家(包括1和10)

这条语句等价于level >= 1 and level <= 10;
mysql> select * from player where level between 1 and 10;
+------+-----------+------+-----------------------+-------+------+-------+
| id   | name      | sex  | email                 | level | exp  | gold  |
+------+-----------+------+-----------------------+-------+------+-------+
|    1 | 张三      || zhangsan@gmail.com    |     3 |   19 | 20.00 |
|    2 | 赵四儿    || zhaosier@geekhour.net |     4 |   22 | 26.00 |
|   11 | 胡一菲    || huyifei@163.com       |     6 |   53 | 38.00 |
|   17 | 吕秀才    || lvxiucai@gmail.com    |     1 |    2 |  3.00 |
|   31 | 周伯通    || zhoubotong@163.com    |     8 |   45 | 70.00 |
|   37 | 慕容复    || murongfu@gmail.com    |     5 |   49 | 38.00 |
|   49 | 安欣      || anxin@gmail.com       |     8 |   43 | 33.00 |
|   87 | 小鱼儿    || xiaoyuer@163.com      |     6 |   55 |  4.00 |
|   91 | 余则成    || yuzecheng@163.com     |    10 |   53 | 29.00 |
|  131 | 弈星      || yixing@geekhour.net   |     1 |   61 | 90.00 |
+------+-----------+------+-----------------------+-------+------+-------+
10 rows in set (0.00 sec)

mysql> 

not 取反
查找等级不在1到10之间的玩家,not可以加在任何一个条件语句之前。

mysql> select * from player where level between 1 and 10;
+------+-----------+------+-----------------------+-------+------+-------+
| id   | name      | sex  | email                 | level | exp  | gold  |
+------+-----------+------+-----------------------+-------+------+-------+
|    1 | 张三      || zhangsan@gmail.com    |     3 |   19 | 20.00 |
|    2 | 赵四儿    || zhaosier@geekhour.net |     4 |   22 | 26.00 |
|   11 | 胡一菲    || huyifei@163.com       |     6 |   53 | 38.00 |

like 模糊查询
查找姓王,或名字中带王的玩家,可以使用%和_来进行匹配,%表示任意个字符,_任意一个字符。

名字第一个字是“王”,后面是任意多个字符。
mysql> select * from player where name like "王%";
+------+-----------+------+---------------------------+-------+------+-------+
| id   | name      | sex  | email                     | level | exp  | gold  |
+------+-----------+------+---------------------------+-------+------+-------+
|    3 | 王五      || wangwu@163.com            |    64 |   38 | 15.00 |
|    7 | 王小二    || wangxiaoer@163.com        |    70 |   30 | 54.00 |
|   33 | 王重阳    || wangchongyang@gmail.com   |    38 |   63 | 38.00 |
|   54 | 王语嫣    || wangyuyan@geekhour.net    |    71 |   97 | 85.00 |
|   82 | 王小蒙    || wangxiaomeng@geekhour.net |    95 |   77 | 44.00 |
|  169 | 王昭君    || wangzhaojun@gmail.com     |    96 |   48 | 11.00 |
+------+-----------+------+---------------------------+-------+------+-------+
6 rows in set (0.00 sec)

mysql> 

regexp 正则匹配
使用正则表达式进行匹配。

. :号表示匹配一个字符。
^ :匹配开头
$ :匹配结尾
[abc] :匹配其中任意一个字符
[a-z] :匹配范围内的任意一个字符
A|B :|表示或者匹配A或B

查找姓王,并且名字为两个字的玩家

mysql> select * from player where name regexp "^王.$";
+------+--------+------+----------------+-------+------+-------+
| id   | name   | sex  | email          | level | exp  | gold  |
+------+--------+------+----------------+-------+------+-------+
|    3 | 王五   || wangwu@163.com |    64 |   38 | 15.00 |
+------+--------+------+----------------+-------+------+-------+
1 row in set (0.00 sec)

mysql> 

匹配姓王或姓张的玩家

匹配条件也可以换成 [王张]select * from player where name regexp "[王张]";
mysql> select * from player where name regexp "王|张";
+------+-----------+------+---------------------------+-------+------+-------+
| id   | name      | sex  | email                     | level | exp  | gold  |
+------+-----------+------+---------------------------+-------+------+-------+
|    1 | 张三      || zhangsan@gmail.com        |     3 |   19 | 20.00 |
|    3 | 王五      || wangwu@163.com            |    64 |   38 | 15.00 |
|    7 | 王小二    || wangxiaoer@163.com        |    70 |   30 | 54.00 |
|   15 | 张伟      || zhangwei@163.com          |    23 |   73 | 73.00 |
|   33 | 王重阳    || wangchongyang@gmail.com   |    38 |   63 | 38.00 |
|   41 | 张无忌    || zhangwuji@gmail.com       |    26 |   20 | 26.00 |

查找邮件地址以“zhangsan”开头的玩家

mysql> select * from player where email regexp "^zhangsan";
+------+-----------+------+---------------------------+-------+------+-------+
| id   | name      | sex  | email                     | level | exp  | gold  |
+------+-----------+------+---------------------------+-------+------+-------+
|    1 | 张三      || zhangsan@gmail.com        |     3 |   19 | 20.00 |
|   46 | 张三丰    || zhangsanfeng@geekhour.net |    13 |   79 | 12.00 |
+------+-----------+------+---------------------------+-------+------+-------+
2 rows in set (0.00 sec)

mysql> 

查找邮件地址以a/b/c开头的玩家

mysql> select * from player where email regexp "^[abc]";
+------+--------------+------+--------------------------+-------+------+--------+
| id   | name         | sex  | email                    | level | exp  | gold   |
+------+--------------+------+--------------------------+-------+------+--------+
|   14 | 陈美嘉       || chenmeijia@geekhour.net  |    95 |   71 |  66.00 |
|   20 | 白展堂       || baizhantang@qq.com       |    89 |   85 |  13.00 |
|   49 | 安欣         || anxin@gmail.com          |     8 |   43 |  33.00 |
|   55 | 阿朱         || azhu@163.com             |    79 |   81 |  65.00 |
|   56 | 阿紫         || azi@qq.com               |    91 |   60 |  56.00 |
|   57 | 阿碧         || abi@gmail.com            |   100 |    9 |  92.00 |
|   88 | 包青天       || baoqingtian@qq.com       |    28 |   60 |   4.00 |
|  104 | 艾琳         || ailin@qq.com             |    86 |   73 |  22.00 |

查找邮件地址以“.net”结尾的玩家

此处也可以使用likeselect * from player where email like "%.net";
mysql> select * from player where email regexp ".net$";
+------+--------------+------+----------------------------+-------+------+--------+
| id   | name         | sex  | email                      | level | exp  | gold   |
+------+--------------+------+----------------------------+-------+------+--------+
|    2 | 赵四儿       || zhaosier@geekhour.net      |     4 |   22 |  26.00 |
|    6 | 马大帅       || madashuai@geekhour.net     |    87 |   98 |  98.00 |
|   10 | 陆展博       || luzhanbo@geekhour.net      |    98 |   51 |  62.00 |

null 空值
null值与任何值都不相等,包括null本身,所以使用null值进行判断的时候不能使用=,而要使用is
查找邮箱为空的玩家

mysql> select * from player where email is null;
+------+-----------+------+-------+-------+------+-------+
| id   | name      | sex  | email | level | exp  | gold  |
+------+-----------+------+-------+-------+------+-------+
|   12 | 吕子乔    || NULL  |    36 |  100 | 46.00 |
|   13 | 吕小布    || NULL  |    81 |   88 | 25.00 |
+------+-----------+------+-------+-------+------+-------+
2 rows in set (0.00 sec)

mysql> 

查找填写了邮箱的玩家,可以使用is not null来判断

mysql> select * from player where email is not null;
+------+--------------+------+----------------------------+-------+------+--------+
| id   | name         | sex  | email                      | level | exp  | gold   |
+------+--------------+------+----------------------------+-------+------+--------+
|    1 | 张三         || zhangsan@gmail.com         |     3 |   19 |  20.00 |
|    2 | 赵四儿       || zhaosier@geekhour.net      |     4 |   22 |  26.00 |
|    3 | 王五         || wangwu@163.com             |    64 |   38 |  15.00 |

MySQL中还提供一个专门用来比较null值的比较操作符:<=>,但是使用is来判断更直观。is在其他数据库也是通用的

mysql> select * from player where email <=> null;
+------+-----------+------+-------+-------+------+-------+
| id   | name      | sex  | email | level | exp  | gold  |
+------+-----------+------+-------+-------+------+-------+
|   12 | 吕子乔    || NULL  |    36 |  100 | 46.00 |
|   13 | 吕小布    || NULL  |    81 |   88 | 25.00 |
+------+-----------+------+-------+-------+------+-------+
2 rows in set (0.00 sec)

mysql> 

null值用is来判断,而空字符串要用=来判断。null表示没有填写值,而空字符串表示填写了个空的值
查询email为空字符串或为null的玩家

mysql> select * from player where email = "" or email is null;
+------+-----------+------+-------+-------+------+-------+
| id   | name      | sex  | email | level | exp  | gold  |
+------+-----------+------+-------+-------+------+-------+
|   12 | 吕子乔    || NULL  |    36 |  100 | 46.00 |
|   13 | 吕小布    || NULL  |    81 |   88 | 25.00 |
|  190 | 吕布      ||       |    77 |   43 | 31.00 |
+------+-----------+------+-------+-------+------+-------+
3 rows in set (0.00 sec)

mysql> 

2、order by排序

order by用来对查询结果按照某个字段进行排序。
按照等级level升序排列(默认是升序,也可以加一个ASC)

mysql> select * from player order by level;
+------+--------------+------+----------------------------+-------+------+--------+
| id   | name         | sex  | email                      | level | exp  | gold   |
+------+--------------+------+----------------------------+-------+------+--------+
|   17 | 吕秀才       || lvxiucai@gmail.com         |     1 |    2 |   3.00 |
|  131 | 弈星         || yixing@geekhour.net        |     1 |   61 |  90.00 |
|    1 | 张三         || zhangsan@gmail.com         |     3 |   19 |  20.00 |
。。。。。。。。。省略。。。。。。。。。

如果想要降序排列,则在语句后面加上DESC

mysql> mysql> select * from player order by level desc;
+------+--------------+------+----------------------------+-------+------+--------+
| id   | name         | sex  | email                      | level | exp  | gold   |
+------+--------------+------+----------------------------+-------+------+--------+
|   57 | 阿碧         || abi@gmail.com              |   100 |    9 |  92.00 |
|  208 | 独孤求败     || duguqiubai@gmail.com       |   100 |  100 |   1.00 |
|   19 | 佟湘玉       || tongxiangyu@163.com        |    99 |    4 |  10.00 |

按照多个字段排序,字段之间用, 分割。
按照level降序排列,等级相同时按exp升序排列。

mysql> select * from player order by level desc,exp;
+------+--------------+------+----------------------------+-------+------+--------+
| id   | name         | sex  | email                      | level | exp  | gold   |
+------+--------------+------+----------------------------+-------+------+--------+
|   57 | 阿碧         || abi@gmail.com              |   100 |    9 |  92.00 |
|  208 | 独孤求败     || duguqiubai@gmail.com       |   100 |  100 |   1.00 |
|   19 | 佟湘玉       || tongxiangyu@163.com        |    99 |    4 |  10.00 |

也可以按照字段序号来排序,字段level是第5列,所以按照level降序排列可以写成:

mysql> select * from player order by 5 desc;
+------+--------------+------+----------------------------+-------+------+--------+
| id   | name         | sex  | email                      | level | exp  | gold   |
+------+--------------+------+----------------------------+-------+------+--------+
|   57 | 阿碧         || abi@gmail.com              |   100 |    9 |  92.00 |
|  208 | 独孤求败     || duguqiubai@gmail.com       |   100 |  100 |   1.00 |

3、聚合函数

聚合函数用来对某列执行一些计算,比如求和、平均值、最大值、最小值等等。

MySQL中有5种常用的聚合函数:
  1、AVG():只适用于数值类型的字段或变量,不包含NULL值。它用于计算指定字段的平均值。
  2、SUM():只适用于数值类型的字段或变量,不包含NULL值。它用于计算指定字段的总和。
  3、 MAX():适用于数值类型、字符串类型、日期时间类型的字段(或变量),不包含NULL值。它用于获取指定字段在分组中的最大值。
  4、 MIN():适用于数值类型、字符串类型、日期时间类型的字段(或变量),不包含NULL值。它用于获取指定字段在分组中的最小值。
  5、 COUNT():计算指定字段在查询结构中出现的个数(不包含NULL值)。它可以统计数据表中包含的记录行的总数,或者根据查询结果返回列中包含的数据行数。
   这些聚合函数通常与GROUP BY子句一起使用,以便对数据进行分组处理。例如,你可以使用GROUP BY子句将表中的数据分成若干组,然后对每个组应用聚合函数。

计算表player中玩家的总人数

mysql> select count(*) from player;
+----------+
| count(*) |
+----------+
|      209 |
+----------+
1 row in set (0.01 sec)

查看玩家平均等级level

mysql> select avg(level) from player;
+------------+
| avg(level) |
+------------+
|    55.0813 |
+------------+
1 row in set (0.00 sec)

查看玩家金币gold的最小值

mysql> select min(gold) from player;
+-----------+
| min(gold) |
+-----------+
|      1.00 |
+-----------+
1 row in set (0.00 sec)

其他两个函数用法与此类似。

4、GROUP BY 分组

使用group by对查询结果进行分组,后面加上一个或多个列名。
查看表中的男女人数


count(*)count(sex)为例,总结COUNT(列名)COUNT(*)的区别:
  SELECT sex, COUNT(sex) FROM player GROUP BY sex;:这条语句会返回每个sex和对应的player数量。这里的COUNT(sex)只会计算sex字段非NULL的记录数。所以,你看到的结果中,NULL的计数是0,因为COUNT(sex)不会计算NULL值。

  SELECT sex, COUNT(*) FROM player GROUP BY sex;:这条语句也会返回每个sex和对应的player数量。但是,这里的COUNT(*)会计算所有的记录数,包括sex字段为NULL的记录。所以,你看到的结果中,NULL的计数是3,因为在你的数据中有3条记录的sex字段是NULL。

  总结一下,当你使用COUNT(列名)时,它只会计算那些列值非NULL的记录数。而当你使用COUNT(*)时,它会计算所有的记录数,包括那些指定列值为NULL的记录。


mysql> select sex, count(*) from player group by sex;
+------+----------+
| sex  | count(*) |
+------+----------+
||      140 |
||       65 |
| NULL |        3 |
|      |        1 |
+------+----------+
4 rows in set (0.00 sec)

mysql> select sex, count(sex) from player group by sex;
+------+------------+
| sex  | count(sex) |
+------+------------+
||        140 |
||         65 |
| NULL |          0 |
|      |          1 |
+------+------------+
4 rows in set (0.00 sec)

查看表中每个等级的玩家数量

mysql> select level, count(level) from player group by level;
+-------+--------------+
| level | count(level) |
+-------+--------------+
|     3 |            1 |
|     4 |            1 |
|    64 |            3 |
|    30 |            1 |
|    95 |            5 |

5、GROUP BY 和 HAVING

group by 经常和having一起使用,用来对分组后的结果进行筛选

将表player中的数据按等级level进行分组,只保留level大于4的结果

# having后面加条件,用来对结果进行筛选
mysql> select level, count(level) from player group by level having level > 4;
+-------+--------------+
| level | count(level) |
+-------+--------------+
|    64 |            3 |
|    30 |            1 |
|    95 |            5 |
|    87 |            2 |

将表player中的数据按等级level进行分组,只保留level大于4的结果,并按照等级数量降序排序。

mysql> select level, count(level) from player group by level having level > 4 order by count(level) desc;
+-------+--------------+
| level | count(level) |
+-------+--------------+
|    13 |            9 |
|    96 |            7 |
|    95 |            5 |
|    88 |            5 |
|    54 |            5 |
|    97 |            4 |
|    38 |            4 |

统计玩家中每个姓氏的数量,将结果按照数量来降序排列,只显示数量大于等于5的姓氏。
完成这个查询需要使用函数SUBSTR用来截取字段、字符串的一部分。
SUBSTR(字段名,开始位置,截取长度),开始位置从1开始计数。

mysql> select substr(name,1,1),count(substr(name,1,1)) from player group by substr(name,1,1) having count(substr(name,1,1)) >= 5 order by count(substr(name,1,1)) desc;
+------------------+-------------------------+
| substr(name,1,1) | count(substr(name,1,1)) |
+------------------+-------------------------+
||                      11 |
||                       8 |
||                       6 |
||                       5 |
||                       5 |
+------------------+-------------------------+
5 rows in set (0.00 sec)

# 如果只想返回上一步查询结果的前三名,可以加个LIMT 3 来实现
mysql>
mysql> select substr(name,1,1),count(substr(name,1,1)) from player group by substr(name,1,1) having count(substr(name,1,1)) >= 5 order by count(substr(name,1,1)) desc limit 3;
+------------------+-------------------------+
| substr(name,1,1) | count(substr(name,1,1)) |
+------------------+-------------------------+
||                      11 |
||                       8 |
||                       6 |
+------------------+-------------------------+
3 rows in set (0.00 sec)

mysql>

LIMIT 还可以指定一个偏移量,返回排名第四名到第六名的姓氏,此时去掉having子句,因为如果加上having子句,只会返回5个结果。limit后的第一个3表示偏移量,从第四个开始,第二个3
表示返回的数量。

mysql> select substr(name,1,1),count(substr(name,1,1)) from player group by substr(name,1,1) order by count(substr(name,1,1)) desc limit 3,3;
+------------------+-------------------------+
| substr(name,1,1) | count(substr(name,1,1)) |
+------------------+-------------------------+
||                       5 |
||                       5 |
||                       4 |
+------------------+-------------------------+
3 rows in set (0.00 sec)

mysql>

在MySQL的SELECT语句中,你不仅可以选择字段名,还可以使用各种表达式和函数。以下是一些例子:
1、算术表达式:例如,SELECT price * quantity AS total FROM orders;这将返回订单的总价(价格乘以数量)。
2、 字符串表达式:例如,SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users; 这将返回用户的全名(名和姓之间用空格分隔)。
3、日期和时间表达式:例如,SELECT DATE_ADD(birth_date, INTERVAL 1 YEAR) AS next_birthday FROM users; 这将返回用户下一次生日的日期。
4、 条件表达式:例如,SELECT IF(score >= 60, 'Pass', 'Fail') AS result FROM exams; 这将返回考试结果(如果分数大于或等于60,则为"Pass",否则为"Fail")。
5、 聚合函数:例如,SELECT COUNT(*) FROM users; 这将返回用户表中的记录数。
6、子查询:例如,SELECT (SELECT COUNT(*) FROM orders WHERE user_id = users.id) AS order_count FROM users; 这将返回每个用户的订单数。

6、DISTINCT 去重

DISTINCT关键字可以用来去除重复的记录
查询所有玩家的性别

mysql> select distinct sex from player;
+------+
| sex  |
+------+
||
||
| NULL |
|      |
+------+
4 rows in set (0.00 sec)

mysql>

7、UNION 合并查询结果

查询level为1-3的玩家

mysql> select * from player where level between 1 and 3;
+------+-----------+------+---------------------+-------+------+-------+
| id   | name      | sex  | email               | level | exp  | gold  |
+------+-----------+------+---------------------+-------+------+-------+
|    1 | 张三      || zhangsan@gmail.com  |     3 |   19 | 20.00 |
|   17 | 吕秀才    || lvxiucai@gmail.com  |     1 |    2 |  3.00 |
|  131 | 弈星      || yixing@geekhour.net |     1 |   61 | 90.00 |
+------+-----------+------+---------------------+-------+------+-------+
3 rows in set (0.00 sec)

查询exp为1-3的玩家

mysql> select * from player where exp between 1 and 3;
+------+-----------+------+-------------------------+-------+------+-------+
| id   | name      | sex  | email                   | level | exp  | gold  |
+------+-----------+------+-------------------------+-------+------+-------+
|   17 | 吕秀才    || lvxiucai@gmail.com      |     1 |    2 |  3.00 |
|   50 | 高启强    || gaoqiqiang@geekhour.net |    88 |    3 | 30.00 |
|  136 | 女娲      || nvwa@qq.com             |    89 |    2 | 86.00 |
|  145 | 大乔      || daqiao@gmail.com        |    87 |    1 | 82.00 |
+------+-----------+------+-------------------------+-------+------+-------+
4 rows in set (0.00 sec)

将这两条查询结果使用UNION合并,UNION默认会去除重复的记录。玩家“吕秀才”就被去重的,他既满足level1-3,又满足exp1-3,所以合并的时候就被去掉了一条。

mysql> select * from player where level between 1 and 3
    -> union
    -> select * from player where exp between 1 and 3;
+------+-----------+------+-------------------------+-------+------+-------+
| id   | name      | sex  | email                   | level | exp  | gold  |
+------+-----------+------+-------------------------+-------+------+-------+
|    1 | 张三      || zhangsan@gmail.com      |     3 |   19 | 20.00 |
|   17 | 吕秀才    || lvxiucai@gmail.com      |     1 |    2 |  3.00 |
|  131 | 弈星      || yixing@geekhour.net     |     1 |   61 | 90.00 |
|   50 | 高启强    || gaoqiqiang@geekhour.net |    88 |    3 | 30.00 |
|  136 | 女娲      || nvwa@qq.com             |    89 |    2 | 86.00 |
|  145 | 大乔      || daqiao@gmail.com        |    87 |    1 | 82.00 |
+------+-----------+------+-------------------------+-------+------+-------+
6 rows in set (0.00 sec)

mysql> 

如果不想去重,可以使用UNION ALL 来合并。

mysql> select * from player where level between 1 and 3 union all select * from player where exp between 1 and 3;
+------+-----------+------+-------------------------+-------+------+-------+
| id   | name      | sex  | email                   | level | exp  | gold  |
+------+-----------+------+-------------------------+-------+------+-------+
|    1 | 张三      || zhangsan@gmail.com      |     3 |   19 | 20.00 |
|   17 | 吕秀才    || lvxiucai@gmail.com      |     1 |    2 |  3.00 |
|  131 | 弈星      || yixing@geekhour.net     |     1 |   61 | 90.00 |
|   17 | 吕秀才    || lvxiucai@gmail.com      |     1 |    2 |  3.00 |
|   50 | 高启强    || gaoqiqiang@geekhour.net |    88 |    3 | 30.00 |
|  136 | 女娲      || nvwa@qq.com             |    89 |    2 | 86.00 |
|  145 | 大乔      || daqiao@gmail.com        |    87 |    1 | 82.00 |
+------+-----------+------+-------------------------+-------+------+-------+
7 rows in set (0.00 sec)

mysql> 

8、INTERSECT 合并结果集(交集)

INTERSECT在MySQL 8.0.31之后开始支持
查找level1-3和exp1-3的玩家,将结果取交集

mysql> select * from player where exp between 1 and 3
    -> intersect 
    -> select * from player where level between 1 and 3;

9、EXCEPT 合并结果集(差集)

EXCEPT在MySQL 8.0.31之后开始支持
EXCEPT查找两个结果的差集,查找等级level为1-3的玩家但经验exp不在1-3的玩家。

mysql> select * from player where exp between 1 and 3
    -> except 
    -> select * from player where level between 1 and 3;

四、子查询

子查询,也被称为内部查询或嵌套查询,是指在一条SELECT语句中嵌入了另外一条SELECT语句,子查询的结果可以作为另一个SQL语句(主查询)的数据来源或者判断条件。
查询玩家的平均等级

1、使用子查询查询数据

mysql> select avg(level) from player;
+------------+
| avg(level) |
+------------+
|    55.0813 |
+------------+
1 row in set (0.00 sec)

查询所有等级大于平均等级的玩家

mysql> select * from player where level > (select avg(level) from player);
+------+--------------+------+----------------------------+-------+------+--------+
| id   | name         | sex  | email                      | level | exp  | gold   |
+------+--------------+------+----------------------------+-------+------+--------+
|    3 | 王五         || wangwu@163.com             |    64 |   38 |  15.00 |
|    5 | 范德彪       || fandebiao@gmail.com        |    95 |   89 |  44.00 |
|    6 | 马大帅       || madashuai@geekhour.net     |    87 |   98 |  98.00 |
|    7 | 王小二       || wangxiaoer@163.com         |    70 |   30 |  54.00 |
|   10 | 陆展博       || luzhanbo@geekhour.net      |    98 |   51 |  62.00 |

查询所有玩家等级和平均等级之间的差值,ROUND函数可以四舍五入。

mysql> select level,round((select avg(level) from player)), level - round((select avg(level) from player))  from player;
+-------+----------------------------------------+------------------------------------------------+
| level | round((select avg(level) from player)) | level - round((select avg(level) from player)) |
+-------+----------------------------------------+------------------------------------------------+
|     3 |                                     55 |                                            -52 |
|     4 |                                     55 |                                            -51 |
|    64 |                                     55 |                                              9 |
|    30 |                                     55 |                                            -25 |

结果的后两列列名直接用了表达式,这样的结果不方便阅读,可以使用AS关键字给列起别名。

mysql> select level,round((select avg(level) from player)) as average, level - round((select avg(level) from player)) as diff  from player;
+-------+---------+------+
| level | average | diff |
+-------+---------+------+
|     3 |      55 |  -52 |
|     4 |      55 |  -51 |
|    64 |      55 |    9 |
|    30 |      55 |  -25 |
|    95 |      55 |   40 |

子查询可以在UPDATEDELETECREATEINSERT等各种语句中使用。

2、使用子查询创建表

使用子查询来创建一个新表。将所有等级小于5的玩家插入到一个新表player2中

mysql> create table player2 select * from player where level < 5;
Query OK, 4 rows affected (0.02 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from player2;
+------+-----------+------+-----------------------+-------+------+-------+
| id   | name      | sex  | email                 | level | exp  | gold  |
+------+-----------+------+-----------------------+-------+------+-------+
|    1 | 张三      || zhangsan@gmail.com    |     3 |   19 | 20.00 |
|    2 | 赵四儿    || zhaosier@geekhour.net |     4 |   22 | 26.00 |
|   17 | 吕秀才    || lvxiucai@gmail.com    |     1 |    2 |  3.00 |
|  131 | 弈星      || yixing@geekhour.net   |     1 |   61 | 90.00 |
+------+-----------+------+-----------------------+-------+------+-------+
4 rows in set (0.01 sec)

mysql>

3、使用子查询插入数据

将表player中,等级level在6-10的玩家插入到player2中。
可以先查询下level在6-10的玩家。

mysql> select * from player where level between 6 and 10;
+------+-----------+------+--------------------+-------+------+-------+
| id   | name      | sex  | email              | level | exp  | gold  |
+------+-----------+------+--------------------+-------+------+-------+
|   11 | 胡一菲    || huyifei@163.com    |     6 |   53 | 38.00 |
|   31 | 周伯通    || zhoubotong@163.com |     8 |   45 | 70.00 |
|   49 | 安欣      || anxin@gmail.com    |     8 |   43 | 33.00 |
|   87 | 小鱼儿    || xiaoyuer@163.com   |     6 |   55 |  4.00 |
|   91 | 余则成    || yuzecheng@163.com  |    10 |   53 | 29.00 |
+------+-----------+------+--------------------+-------+------+-------+
5 rows in set (0.00 sec)

mysql>

将这些记录插入到表player2中

mysql> insert into player2 select * from player where level between 6 and 10;
Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> select * from player2;
+------+-----------+------+-----------------------+-------+------+-------+
| id   | name      | sex  | email                 | level | exp  | gold  |
+------+-----------+------+-----------------------+-------+------+-------+
|    1 | 张三      || zhangsan@gmail.com    |     3 |   19 | 20.00 |
|    2 | 赵四儿    || zhaosier@geekhour.net |     4 |   22 | 26.00 |
|   17 | 吕秀才    || lvxiucai@gmail.com    |     1 |    2 |  3.00 |
|  131 | 弈星      || yixing@geekhour.net   |     1 |   61 | 90.00 |
|   11 | 胡一菲    || huyifei@163.com       |     6 |   53 | 38.00 |
|   31 | 周伯通    || zhoubotong@163.com    |     8 |   45 | 70.00 |
|   49 | 安欣      || anxin@gmail.com       |     8 |   43 | 33.00 |
|   87 | 小鱼儿    || xiaoyuer@163.com      |     6 |   55 |  4.00 |
|   91 | 余则成    || yuzecheng@163.com     |    10 |   53 | 29.00 |
+------+-----------+------+-----------------------+-------+------+-------+
9 rows in set (0.00 sec)

mysql> 

4、子查询与EXISTS 判断查询结果

EXISTS用来判断一个查询是否有结果,返回值只有0和1两种。
查询是否有等级大于100的玩家。结果为0,所以不存在

mysql> select exists(select * from player where level > 100);
+------------------------------------------------+
| exists(select * from player where level > 100) |
+------------------------------------------------+
|                                              0 |
+------------------------------------------------+
1 row in set (0.00 sec)

mysql>

查询是否存在等级大于10的玩家。返回值是1,说明存在。

mysql> select exists(select * from player where level > 10);
+-----------------------------------------------+
| exists(select * from player where level > 10) |
+-----------------------------------------------+
|                                             1 |
+-----------------------------------------------+
1 row in set (0.00 sec)

mysql> 

五、表关联

在MySQL中,表关联是一种将两个或多个表中的行结合起来的操作。这通常是通过在这些表之间的某些列(通常是具有相同名称和数据类型的列)上进行比较来完成的。
表关联用来查询多个表中的数据,关联的表之间必须有相同的字段,一般会使用表的主键和外键来关联。

MySQL支持以下几种类型的表关联:
内连接(INNER JOIN):只返回两个表中满足连接条件的行。
左连接(LEFT JOIN):返回左表的所有行,即使右表没有匹配的行,右表没有匹配的数据用NULL填充。
右连接(RIGHT JOIN):返回右表的所有行,即使左表没有匹配的行,左表没有匹配的数据用NULL填充。

查看存储装备的表equip,三个字分别是装备的id、名称以及所属玩家的id

mysql> desc equip;
+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| id        | int          | YES  |     | NULL    |       |
| name      | varchar(100) | YES  |     | NULL    |       |
| player_id | int          | YES  |     | NULL    |       |
+-----------+--------------+------+-----+---------+-------+
3 rows in set (0.01 sec)

mysql> 

1、内连接

内连接就是使用INNER JOIN 关键字来指定关联的表,然后是ON关键字和两个表中关联的字段,最后可以加上WHERE关键字和查询条件。
现在结果中既包含玩家的信息,又包含玩家对应装备的信息,它们之间使用玩家id这个字段来关联起来。

mysql> select * from player
    -> inner join equip
    -> on player.id = equip.player_id;
+------+-----------+------+---------------------+-------+------+-------+------+-----------------+-----------+
| id   | name      | sex  | email               | level | exp  | gold  | id   | name            | player_id |
+------+-----------+------+---------------------+-------+------+-------+------+-----------------+-----------+
|   76 | 林克      || linke@qq.com        |    48 |   12 | 11.00 |    6 | 大师之剑        |        76 |
|  157 | 张飞      || zhangfei@gmail.com  |    76 |   36 | 80.00 |    2 | 丈八蛇矛        |       157 |
|  161 | 孙悟空    || sunwukong@gmail.com |    74 |   32 | 23.00 |    7 | 金箍棒          |       161 |
|  177 | 关羽      || guanyu@gmail.com    |    19 |   60 | 36.00 |    1 | 青龙偃月刀      |       177 |
|  186 | 曹操      || caocao@geekhour.net |    70 |   15 | 27.00 |    3 | 七星宝刀        |       186 |
|  190 | 吕布      ||                     |    77 |   43 | 31.00 |    9 | 赤兔马          |       190 |
|  190 | 吕布      ||                     |    77 |   43 | 31.00 |    8 | 方天画戟        |       190 |
+------+-----------+------+---------------------+-------+------+-------+------+-----------------+-----------+
7 rows in set (0.00 sec)

mysql> 

2、左连接

使用左连接来关联这两个表。此时,结果中包含了玩家表中所有数据,然后是玩家对应的装备信息,有装备的话就显示装备信息,没有就用NULL来填充。

mysql> select * from player left join equip on player.id = equip.player_id;
+------+--------------+------+----------------------------+-------+------+--------+------+-----------------+-----------+
| id   | name         | sex  | email                      | level | exp  | gold   | id   | name            | player_id |
+------+--------------+------+----------------------------+-------+------+--------+------+-----------------+-----------+
|    1 | 张三         || zhangsan@gmail.com         |     3 |   19 |  20.00 | NULL | NULL            |      NULL |
|    2 | 赵四儿       || zhaosier@geekhour.net      |     4 |   22 |  26.00 | NULL | NULL            |      NULL |
|    3 | 王五         || wangwu@163.com             |    64 |   38 |  15.00 | NULL | NULL            |      NULL |
|    4 | 刘能         || liuneng@qq.com             |    30 |   95 |   1.00 | NULL | NULL            |      NULL |
|    5 | 范德彪       || fandebiao@gmail.com        |    95 |   89 |  44.00 | NULL | NULL            |      NULL |
|    6 | 马大帅       || madashuai@geekhour.net     |    87 |   98 |  98.00 | NULL | NULL            |      NULL |
。。。。。。。省略。。。。。。。。

3、右连接

右连接是查询右表中的所有数据和左表中匹配的数据,左表中没有的数据用NULL来填充。
上面的两个表改成右连接

mysql> select * from player right join equip on player.id = equip.player_id;
+------+-----------+------+---------------------+-------+------+-------+------+-----------------+-----------+
| id   | name      | sex  | email               | level | exp  | gold  | id   | name            | player_id |
+------+-----------+------+---------------------+-------+------+-------+------+-----------------+-----------+
|  177 | 关羽      || guanyu@gmail.com    |    19 |   60 | 36.00 |    1 | 青龙偃月刀      |       177 |
|  157 | 张飞      || zhangfei@gmail.com  |    76 |   36 | 80.00 |    2 | 丈八蛇矛        |       157 |
|  186 | 曹操      || caocao@geekhour.net |    70 |   15 | 27.00 |    3 | 七星宝刀        |       186 |
| NULL | NULL      | NULL | NULL                |  NULL | NULL |  NULL |    4 | 长剑            |      NULL |
| NULL | NULL      | NULL | NULL                |  NULL | NULL |  NULL |    5 | 铁盾            |      NULL |
|   76 | 林克      || linke@qq.com        |    48 |   12 | 11.00 |    6 | 大师之剑        |        76 |
|  161 | 孙悟空    || sunwukong@gmail.com |    74 |   32 | 23.00 |    7 | 金箍棒          |       161 |
|  190 | 吕布      ||                     |    77 |   43 | 31.00 |    8 | 方天画戟        |       190 |
|  190 | 吕布      ||                     |    77 |   43 | 31.00 |    9 | 赤兔马          |       190 |
+------+-----------+------+---------------------+-------+------+-------+------+-----------------+-----------+
9 rows in set (0.00 sec)

mysql>

4、使用WHERE关键字来代替JION ON

表连接除了使用JOINON关键字来指定关联的字段之外,还可以使用WHERE关键字来指定。
还是上面的两个表,把JOIN去掉,表名后面加上,然后在WHERE后面加上关联的条件,结果是一样的。

mysql> select * from player, equip where player.id = equip.player_id;
+------+-----------+------+---------------------+-------+------+-------+------+-----------------+-----------+
| id   | name      | sex  | email               | level | exp  | gold  | id   | name            | player_id |
+------+-----------+------+---------------------+-------+------+-------+------+-----------------+-----------+
|   76 | 林克      || linke@qq.com        |    48 |   12 | 11.00 |    6 | 大师之剑        |        76 |
|  157 | 张飞      || zhangfei@gmail.com  |    76 |   36 | 80.00 |    2 | 丈八蛇矛        |       157 |
|  161 | 孙悟空    || sunwukong@gmail.com |    74 |   32 | 23.00 |    7 | 金箍棒          |       161 |
|  177 | 关羽      || guanyu@gmail.com    |    19 |   60 | 36.00 |    1 | 青龙偃月刀      |       177 |
|  186 | 曹操      || caocao@geekhour.net |    70 |   15 | 27.00 |    3 | 七星宝刀        |       186 |
|  190 | 吕布      ||                     |    77 |   43 | 31.00 |    9 | 赤兔马          |       190 |
|  190 | 吕布      ||                     |    77 |   43 | 31.00 |    8 | 方天画戟        |       190 |
+------+-----------+------+---------------------+-------+------+-------+------+-----------------+-----------+
7 rows in set (0.00 sec)

也可以在表名后面加上别名,使用别名来指定关联的条件,player的别名指定为p,equip的别名指定为e。

mysql> select * from player p, equip e where p.id = e.player_id;
+------+-----------+------+---------------------+-------+------+-------+------+-----------------+-----------+
| id   | name      | sex  | email               | level | exp  | gold  | id   | name            | player_id |
+------+-----------+------+---------------------+-------+------+-------+------+-----------------+-----------+
|   76 | 林克      || linke@qq.com        |    48 |   12 | 11.00 |    6 | 大师之剑        |        76 |
|  157 | 张飞      || zhangfei@gmail.com  |    76 |   36 | 80.00 |    2 | 丈八蛇矛        |       157 |
|  161 | 孙悟空    || sunwukong@gmail.com |    74 |   32 | 23.00 |    7 | 金箍棒          |       161 |
|  177 | 关羽      || guanyu@gmail.com    |    19 |   60 | 36.00 |    1 | 青龙偃月刀      |       177 |
|  186 | 曹操      || caocao@geekhour.net |    70 |   15 | 27.00 |    3 | 七星宝刀        |       186 |
|  190 | 吕布      ||                     |    77 |   43 | 31.00 |    9 | 赤兔马          |       190 |
|  190 | 吕布      ||                     |    77 |   43 | 31.00 |    8 | 方天画戟        |       190 |
+------+-----------+------+---------------------+-------+------+-------+------+-----------------+-----------+
7 rows in set (0.00 sec)

mysql>

5、多表关联

game数据库中还有个存放技能的表skill

6、笛卡尔积

笛卡尔积,也被称为笛卡尔乘积或直积,是在数学中,两个集合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)}

如果连接没有指定条件,或者条件不正确时,就会产生笛卡尔积。
比如将上面的查询条件去掉,就会产生以下结果。可以看到,结果中的每一条数据都会和另一个表中的数据进行组合。

mysql> select * from player p, equip e;
+------+--------------+------+----------------------------+-------+------+--------+------+-----------------+-----------+
| id   | name         | sex  | email                      | level | exp  | gold   | id   | name            | player_id |
+------+--------------+------+----------------------------+-------+------+--------+------+-----------------+-----------+
|    1 | 张三         || zhangsan@gmail.com         |     3 |   19 |  20.00 |    9 | 赤兔马          |       190 |
|    1 | 张三         || zhangsan@gmail.com         |     3 |   19 |  20.00 |    8 | 方天画戟        |       190 |
|    1 | 张三         || zhangsan@gmail.com         |     3 |   19 |  20.00 |    7 | 金箍棒          |       161 |
|    1 | 张三         || zhangsan@gmail.com         |     3 |   19 |  20.00 |    6 | 大师之剑        |        76 |
|    1 | 张三         || zhangsan@gmail.com         |     3 |   19 |  20.00 |    5 | 铁盾            |      NULL |
|    1 | 张三         || zhangsan@gmail.com         |     3 |   19 |  20.00 |    4 | 长剑            |      NULL |
|    1 | 张三         || zhangsan@gmail.com         |     3 |   19 |  20.00 |    3 | 七星宝刀        |       186 |
|    1 | 张三         || zhangsan@gmail.com         |     3 |   19 |  20.00 |    2 | 丈八蛇矛        |       157 |
|    1 | 张三         || zhangsan@gmail.com         |     3 |   19 |  20.00 |    1 | 青龙偃月刀      |       177 |
|    2 | 赵四儿       || zhaosier@geekhour.net      |     4 |   22 |  26.00 |    9 | 赤兔马          |       190 |
|    2 | 赵四儿       || zhaosier@geekhour.net      |     4 |   22 |  26.00 |    8 | 方天画戟        |       190 |
|    2 | 赵四儿       || zhaosier@geekhour.net      |     4 |   22 |  26.00 |    7 | 金箍棒          |       161 |
|    2 | 赵四儿       || zhaosier@geekhour.net      |     4 |   22 |  26.00 |    6 | 大师之剑        |        76 |
|    2 | 赵四儿       || zhaosier@geekhour.net      |     4 |   22 |  26.00 |    5 | 铁盾            |      NULL |
|    2 | 赵四儿       || zhaosier@geekhour.net      |     4 |   22 |  26.00 |    4 | 长剑            |      NULL |
|    2 | 赵四儿       || zhaosier@geekhour.net      |     4 |   22 |  26.00 |    3 | 七星宝刀        |       186 |
|    2 | 赵四儿       || zhaosier@geekhour.net      |     4 |   22 |  26.00 |    2 | 丈八蛇矛        |       157 |
|    2 | 赵四儿       || zhaosier@geekhour.net      |     4 |   22 |  26.00 |    1 | 青龙偃月刀      |       177 |
|    3 | 王五         || wangwu@163.com             |    64 |   38 |  15.00 |    9 | 赤兔马          |       190 |
|    3 | 王五         || wangwu@163.com             |    64 |   38 |  15.00 |    8 | 方天画戟        |       190 |
|    3 | 王五         || wangwu@163.com             |    64 |   38 |  15.00 |    7 | 金箍棒          |       161 |
|    3 | 王五         || wangwu@163.com             |    64 |   38 |  15.00 |    6 | 大师之剑        |        76 |
|    3 | 王五         || wangwu@163.com             |    64 |   38 |  15.00 |    5 | 铁盾            |      NULL |
|    3 | 王五         || wangwu@163.com             |    64 |   38 |  15.00 |    4 | 长剑            |      NULL |
|    3 | 王五         || wangwu@163.com             |    64 |   38 |  15.00 |    3 | 七星宝刀        |       186 |
|    3 | 王五         || wangwu@163.com             |    64 |   38 |  15.00 |    2 | 丈八蛇矛        |       157 |
|    3 | 王五         || wangwu@163.com             |    64 |   38 |  15.00 |    1 | 青龙偃月刀      |       177 |
|    4 | 刘能         || liuneng@qq.com             |    30 |   95 |   1.00 |    9 | 赤兔马          |       190 |
|    4 | 刘能         || liuneng@qq.com             |    30 |   95 |   1.00 |    8 | 方天画戟        |       190 |
|    4 | 刘能         || liuneng@qq.com             |    30 |   95 |   1.00 |    7 | 金箍棒          |       161 |
|    4 | 刘能         || liuneng@qq.com             |    30 |   95 |   1.00 |    6 | 大师之剑        |        76 |
|    4 | 刘能         || liuneng@qq.com             |    30 |   95 |   1.00 |    5 | 铁盾            |      NULL |
|    4 | 刘能         || liuneng@qq.com             |    30 |   95 |   1.00 |    4 | 长剑            |      NULL |
|    4 | 刘能         || liuneng@qq.com             |    30 |   95 |   1.00 |    3 | 七星宝刀        |       186 |
|    4 | 刘能         || liuneng@qq.com             |    30 |   95 |   1.00 |    2 | 丈八蛇矛        |       157 |
|    4 | 刘能         || liuneng@qq.com             |    30 |   95 |   1.00 |    1 | 青龙偃月刀      |       177 |

六、索引

索引是一种用来提高查询效率的数据结构,它可以帮助我们快速定位到我们想要的数据。如果没有索引,就只能从头开始遍历所有的数据,直到找到满足条件的数据,当数据量非常大时,查询效率会很低。

1、 CREATE INDEX 创建索引

索引可以在建表时创建,也可以在建表后指定。
创建索引的格式如下:

# 其中,CREATE INDEX是创建索引的关键字 
# [] 内是可选的索引类型,UNIQUE表示唯一索引
# FULLTEXT表示全文索引
# SPATIAL 表示空间索引
# index_name 表示索引的名称
# ON 关键字后面加表名,表示要在哪张表上创建索引
# 括号括起来一个或多个字段,这些字段名表示要对哪些字段创建索引
# 一般会对主键字段或经常查询的字段创建索引
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name ON tbl_name (index_col_name....)

创建表fast

mysql> create table fast (id int,name varchar(255),age int,email varchar(255)); 
Query OK, 0 rows affected (0.01 sec)

mysql> 

在MySQL命令行中输入以下命令,这将创建一个名为insert_data的存储过程,每次插入10条数据,共插入两千万条数据。

DELIMITER $$
CREATE PROCEDURE insert_data()
BEGIN
  DECLARE i INT DEFAULT 1;
  WHILE i <= 20000000 DO
    INSERT INTO fast (id, name, age, email) 
    VALUES (i, CONCAT('Name', i), FLOOR(1 + RAND() * 100), CONCAT('email', i, '@example.com')),
           (i+1, CONCAT('Name', i+1), FLOOR(1 + RAND() * 100), CONCAT('email', i+1, '@example.com')),
           (i+2, CONCAT('Name', i+2), FLOOR(1 + RAND() * 100), CONCAT('email', i+2, '@example.com')),
           (i+3, CONCAT('Name', i+3), FLOOR(1 + RAND() * 100), CONCAT('email', i+3, '@example.com')),
           (i+4, CONCAT('Name', i+4), FLOOR(1 + RAND() * 100), CONCAT('email', i+4, '@example.com')),
           (i+5, CONCAT('Name', i+5), FLOOR(1 + RAND() * 100), CONCAT('email', i+5, '@example.com')),
           (i+6, CONCAT('Name', i+6), FLOOR(1 + RAND() * 100), CONCAT('email', i+6, '@example.com')),
           (i+7, CONCAT('Name', i+7), FLOOR(1 + RAND() * 100), CONCAT('email', i+7, '@example.com')),
           (i+8, CONCAT('Name', i+8), FLOOR(1 + RAND() * 100), CONCAT('email', i+8, '@example.com')),
           (i+9, CONCAT('Name', i+9), FLOOR(1 + RAND() * 100), CONCAT('email', i+9, '@example.com'));
    SET i = i + 10;
  END WHILE;
END$$
DELIMITER ;

运行以下命令来调用存储过程并开始插入数据,开始插入数据,共两千万条。执行时间较长。

CALL insert_data();

执行的时间太长了,现在插入几百万条数据了,够用了,现在把这个插入进程停止掉

# 查看进程
mysql> SHOW PROCESSLIST;
+----+-----------------+-----------+------+---------+---------+----------------------------+------------------------------------------------------------------------------------------------------+
| Id | User            | Host      | db   | Command | Time    | State                      | Info                                                                                                 |
+----+-----------------+-----------+------+---------+---------+----------------------------+------------------------------------------------------------------------------------------------------+
|  5 | event_scheduler | localhost | NULL | Daemon  | 1604482 | Waiting on empty queue     | NULL                                                                                                 |
| 36 | root            | localhost | game | Query   |       0 | waiting for handler commit | INSERT INTO fast (id, name, age, email) 
    VALUES (i, CONCAT('Name', i), FLOOR(1 + RAND() * 100),  |
| 37 | root            | localhost | game | Query   |       0 | init                       | SHOW PROCESSLIST                                                                                     |
+----+-----------------+-----------+------+---------+---------+----------------------------+------------------------------------------------------------------------------------------------------+
3 rows in set (0.00 sec)

# 进程对应的id为36,杀掉
mysql> kill 36;
Query OK, 0 rows affected (0.00 sec)

# 再查看,进程已被干掉
mysql> SHOW PROCESSLIST;
+----+-----------------+-----------+------+---------+---------+------------------------+------------------+
| Id | User            | Host      | db   | Command | Time    | State                  | Info             |
+----+-----------------+-----------+------+---------+---------+------------------------+------------------+
|  5 | event_scheduler | localhost | NULL | Daemon  | 1604548 | Waiting on empty queue | NULL             |
| 37 | root            | localhost | game | Query   |       0 | init                   | SHOW PROCESSLIST |
+----+-----------------+-----------+------+---------+---------+------------------------+------------------+
2 rows in set (0.00 sec)

mysql> 

查看表fast中的数据条数

mysql> select count(*) from fast;
+----------+
| count(*) |
+----------+
|  4966660 |
+----------+
1 row in set (0.78 sec)

在没有创建索引的情况下,对表fast进行查询,耗时3.82 sec

mysql> select * from fast  where email like 'email263118%' order by id;
+---------+-------------+------+--------------------------+
| id      | name        | age  | email                    |
+---------+-------------+------+--------------------------+
|  263118 | Name263118  |   36 | email263118@example.com  |
| 2631180 | Name2631180 |   75 | email2631180@example.com |
| 2631181 | Name2631181 |   32 | email2631181@example.com |
| 2631182 | Name2631182 |   37 | email2631182@example.com |
| 2631183 | Name2631183 |   88 | email2631183@example.com |
| 2631184 | Name2631184 |   27 | email2631184@example.com |
| 2631185 | Name2631185 |   73 | email2631185@example.com |
| 2631186 | Name2631186 |   80 | email2631186@example.com |
| 2631187 | Name2631187 |   83 | email2631187@example.com |
| 2631188 | Name2631188 |   74 | email2631188@example.com |
| 2631189 | Name2631189 |   20 | email2631189@example.com |
+---------+-------------+------+--------------------------+
11 rows in set (3.82 sec)

mysql>

给fast表的email字段创建一个索引,索引名称为email_index

mysql> create index email_index on fast( email);
Query OK, 0 rows affected (28.63 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql>

2、查看索引

使用SHOW INDEX FROM后面加上表名来查询

mysql> show index from fast;
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| fast  |          1 | email_index |            1 | email       | A         |     4849809 |     NULL |   NULL | YES  | BTREE      |         |               | YES     | NULL       |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
1 row in set (0.02 sec)

mysql>

使用索引再来执行刚才的查询语句

3、使用索引

现在已经创建了索引,使用在没有创建索引时的查询命令,再来查询一次,耗时0.00 sec,一瞬间就返回了查询结果,而刚才没有使用索引时的查询时间是3.82sec,可见在数据量非常巨大时,使用索引可以大大减少查询时间,提高查询效率。

mysql> select * from fast  where email like 'email263118%' order by id;
+---------+-------------+------+--------------------------+
| id      | name        | age  | email                    |
+---------+-------------+------+--------------------------+
|  263118 | Name263118  |   36 | email263118@example.com  |
| 2631180 | Name2631180 |   75 | email2631180@example.com |
| 2631181 | Name2631181 |   32 | email2631181@example.com |
| 2631182 | Name2631182 |   37 | email2631182@example.com |
| 2631183 | Name2631183 |   88 | email2631183@example.com |
| 2631184 | Name2631184 |   27 | email2631184@example.com |
| 2631185 | Name2631185 |   73 | email2631185@example.com |
| 2631186 | Name2631186 |   80 | email2631186@example.com |
| 2631187 | Name2631187 |   83 | email2631187@example.com |
| 2631188 | Name2631188 |   74 | email2631188@example.com |
| 2631189 | Name2631189 |   20 | email2631189@example.com |
+---------+-------------+------+--------------------------+
11 rows in set (0.00 sec)

mysql>

4、删除索引 DROP INDEX

删除索引使用DROP INDEX语句,后面加索引名称,然后是ON关键字和表的名称。
删除刚才创建的索引email_index

mysql> drop index email_index on fast;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

# 删除索引后再查看索引,此时为空
mysql> show index from fast;
Empty set (0.00 sec)

mysql

5、在修改表时创建索引

使用ADD INDEX语句加表名,括号内加要建立索引的字段,来添加索引。

ALTER TABLE fast ADD INDEX name_index (name);

也可以在建表时添加索引。

七、视图

视图是一种虚拟存在的表,它本身并不包含数据,而是作为一个查询语句,保存在数据字典中。当查询视图时,它会根据查询语句的定义,来动态的生成数据。

1、创建视图

创建一个玩家表中等级在前5的排行榜视图
CREATE VIEW后面加上视图的名称,AS关键字后面加上要查询的SELECT语句
从表player中创建一个视图,包含等级前五的玩家

mysql> create view top5
    -> as
    -> select * from player order by level desc limit 5;
Query OK, 0 rows affected (0.01 sec)

mysql>

2、视图的使用

视图的使用和正常的数据表是一样的。可以使用select语句来查询视图。

mysql> select * from top5;
+------+--------------+------+----------------------+-------+------+-------+
| id   | name         | sex  | email                | level | exp  | gold  |
+------+--------------+------+----------------------+-------+------+-------+
|   57 | 阿碧         || abi@gmail.com        |   100 |    9 | 92.00 |
|  208 | 独孤求败     || duguqiubai@gmail.com |   100 |  100 |  1.00 |
|   19 | 佟湘玉       || tongxiangyu@163.com  |    99 |    4 | 10.00 |
|  129 | 米莱狄       || milaidi@qq.com       |    99 |   93 | 31.00 |
|   64 | 风清扬       || fengqingyang@qq.com  |    99 |   80 | 81.00 |
+------+--------------+------+----------------------+-------+------+-------+
5 rows in set (0.00 sec)

mysql>

当表中数据发生变化时,视图中的数据也会相应变化。
比如此时把第一名的等级改为10,然后执行update语句,再来查询视图,视图中的数据也会发生变化,视图中的数据是动态的。

mysql> update player set level = 10 where id = 64;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from top5;
+------+--------------+------+----------------------+-------+------+-------+
| id   | name         | sex  | email                | level | exp  | gold  |
+------+--------------+------+----------------------+-------+------+-------+
|   57 | 阿碧         || abi@gmail.com        |   100 |    9 | 92.00 |
|  208 | 独孤求败     || duguqiubai@gmail.com |   100 |  100 |  1.00 |
|   19 | 佟湘玉       || tongxiangyu@163.com  |    99 |    4 | 10.00 |
|  129 | 米莱狄       || milaidi@qq.com       |    99 |   93 | 31.00 |
|  164 | 娜可露露     || nakelulu@qq.com      |    99 |   16 | 33.00 |
+------+--------------+------+----------------------+-------+------+-------+
5 rows in set (0.00 sec)

mysql>

3、修改视图

修改视图使用ALTER VIEW语句后面加上视图名称,然后是AS关键字和新的语句
现在把数据改成从小到大排序

mysql> alter view top5
    -> as
    -> select  * from player order by level limit 5;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from top5;
+------+-----------+------+-----------------------+-------+------+-------+
| id   | name      | sex  | email                 | level | exp  | gold  |
+------+-----------+------+-----------------------+-------+------+-------+
|   17 | 吕秀才    || lvxiucai@gmail.com    |     1 |    2 |  3.00 |
|  131 | 弈星      || yixing@geekhour.net   |     1 |   61 | 90.00 |
|    1 | 张三      || zhangsan@gmail.com    |     3 |   19 | 20.00 |
|    2 | 赵四儿    || zhaosier@geekhour.net |     4 |   22 | 26.00 |
|   37 | 慕容复    || murongfu@gmail.com    |     5 |   49 | 38.00 |
+------+-----------+------+-----------------------+-------+------+-------+
5 rows in set (0.00 sec)

mysql>

4、删除视图

使用DROP VIEW语句,后面加上要删除的视图名称。
删除视图top5文章来源地址https://www.toymoban.com/news/detail-708378.html

mysql> drop view top5;
Query OK, 0 rows affected (0.00 sec)

mysql>

到了这里,关于MySQL基础【学习至基本语句】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MySQL 数据库实用指南:测试数据准备、SQL语句规范与基本操作

    欢迎来到小K的MySQL专栏,本节将为大家准备MySQL测试数据、以及带来SQL语句规范、数据库的基本操作的详细讲解 要学习SQL查询语句,首先必须解决一个问题,数据问题。为了方便大家学习阅读我的文章,在这里提供了一个test.sql文件 ✨ 登录MySQL,输入 source xxx/test.sql 导入sql文

    2024年02月08日
    浏览(66)
  • 【Mysql】数据库基础与基本操作

    🌇个人主页:平凡的小苏 📚学习格言:命运给你一个低的起点,是想看你精彩的翻盘,而不是让你自甘堕落,脚下的路虽然难走,但我还能走,比起向阳而生,我更想尝试逆风翻盘 。 🛸 Mysql专栏 : Mysql内功修炼基地 家人们更新不易,你们的👍点赞👍和⭐关注⭐真的对我

    2024年02月13日
    浏览(35)
  • 【Mysql数据库从0到1】-入门基础篇--mysql基本使用

    mysql5.7和之前版本,默认字符集为latin1,插入中文字符会出现乱码。在使用5.7及之前的版本时候需要将字符编码修改为utf8字符集,utf8字符集指的是utf8mb3。 从mysql8.0开始,数据库默认字符编码改为utf8mb4。 Mysql 5.7 默认身份插件是 mysql_native_password Mysql 8.0 默认的身份插件是 cac

    2024年02月07日
    浏览(39)
  • 【MySQL数据库重点】第二节:MySQL基础知识(基本操作)

    目录 一:数据库的操作 1.显示数据库 2.创建数据库 3.使用数据库 4.删除数据库 二:常用数据类型 1.数值类型:整型和浮点型 2.字符串类型 3.日期类型 三:表的操作 1.查看表结构 2.创建表 3.删除表 1.显示数据库 语法: show databases;  2.创建数据库 (1)简化语法 create database 数

    2024年02月08日
    浏览(43)
  • MySQL数据库增删改查及聚合查询SQL语句学习汇总

    目录 数据库增删改查SQL语句 MySQL数据库指令 1.查询数据库 2.创建数据库 3.删除数据库 4.选择数据库 创建表table   查看所有表 创建表 查看指定表的结构 删除表 数据库命令进行注释 增删改查(CRUD)详细说明 增加 SQL库提供了关于时间的函数:now()  查询 查询表作列与列之间进

    2024年02月09日
    浏览(66)
  • Mysql 数据库DQL 数据查询语言 SELECT 基本查询、条件查询、聚合查询、分组查询、排序查询、分页查询——包含DQL所有查询语句。吐血分享。

    DQL:数据查询语言; 用来对表内的数据进行查找 。Database Query Language SQL语句分为:基本查询、条件查询、聚合查询、分组查询、排序查询、分页查询。  可以发现name字段就只剩下一个张三了;   条件: 条件查询—比较运算符 比较运算符 功能 大于 = 大于等于 小于 = 小于等

    2024年01月19日
    浏览(45)
  • MySQL数据库学习【基础篇】

    下方链接使用科学上网速度可能会更加快一点哦! 请点击查看数据库MySQL笔记大全 DDL: 数据定义语言,用来定义数据库对象(数据库、表、字段) DML: 数据操作语言,用来对数据库表中的数据进行增删改 DQL: 数据查询语言,用来查询数据库中表的记录 DCL: 数据控制语言,用来

    2024年02月11日
    浏览(29)
  • MySQL基础(三)基本的SELECT语句

    1.1 SQL背景知识 1946 年,世界上第一台电脑诞生,如今,借由这台电脑发展起来的互联网已经自成江湖。在这几十年里,无数的技术、产业在这片江湖里沉浮,有的方兴未艾,有的已经几幕兴衰。但在这片浩荡的波动里,有一门技术从未消失,甚至“老当益壮”,那就是 SQL。

    2024年02月03日
    浏览(23)
  • MySQL-03.基本的SELECT语句(基础)

    课程中,第二章是MySQL环境搭建,因为我之前安装过MySQL5.7的环境,然后就直接下载8.0版本的zip,直接安装的,就没看视频,所以没有第二章笔记。这里给出MySQL社区版下载地址。 1.1 SQL背景知识 1974年,IBM研究员发布了一篇揭开数据库技术的论文《SEQUEL:一门结构化的英语查询

    2024年02月05日
    浏览(28)
  • MySQL-03基本的SELECT语句(基础)

    课程中,第二章是MySQL环境搭建,因为我之前安装过MySQL5.7的环境,然后就直接下载8.0版本的zip,直接安装的,就没看视频,所以没有第二章笔记。这里给出MySQL社区版下载地址。 1.1 SQL背景知识 1974年,IBM研究员发布了一篇揭开数据库技术的论文《SEQUEL:一门结构化的英语查询

    2024年02月05日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包