MySql的安装、配置以及学习SQL常用语法

1. 进入官网下载

最新版本:https://dev.mysql.com/downloads/mysql/
5.7版本:https://dev.mysql.com/downloads/mysql/5.7.html#downloads
5.6版本:https://dev.mysql.com/downloads/mysql/5.6.html#downloads
5.5版本:https://dev.mysql.com/downloads/mysql/5.5.html#downloads

下载zip压缩包64位版本,我用最新版本的数据库进行介绍
使用压缩包进行安装,可以自定义数据库位置
在这里插入图片描述

2. 解压到自己的文件目录下

我解压在 D:\developer_tools下,加上文件夹名称就是 D:\developer_tools\mysql-8.0.16-winx64
在这里插入图片描述

3. 配置 MySQL 的配置文件(可选)

8.0往后的不需要配置mysql文件了,8.0之前的都需要配置

打开刚刚解压的文件夹 D:\developer_tools\mysql-8.0.16-winx64 ,在该文件夹下创建 my.ini 配置文件,编辑 my.ini 配置以下基本信息:

[mysqld]
# 设置mysql客户端默认字符集
default-character-set=utf8
 
[mysqld]
# 设置3306端口
port = 3306
# 设置mysql的安装目录
basedir=D:\developer_tools\mysql-5.7.26-winx64
# 设置 mysql数据库的数据的存放目录,MySQL 8+ 不需要以下配置,系统自己生成即可,否则有可能报错
datadir=D:\developer_tools\mysql-5.7.26-winx64\data
# 允许最大连接数
max_connections=20
# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB

或者使用以下节简版

[mysql]
default-character-set = utf8

[mysqld]
port = 3306
max_connections = 20
character-set-server = UTF8MB4
default-storage-engine = INNODB

4. 启动MySQL数据库

以管理员身份打开 cmd 命令行工具,切换目录:

cd D:\developer_tools\mysql-8.0.16-winx64\bin
cd D:\developer_tools\mysql-5.7.26-winx64\bin

初始化数据库:

mysqld --initialize --console

执行完成后,会输出 root 用户的初始默认密码,如:

2019-07-12T13:33:20.762834Z 0 [System] [MY-013169] [Server] D:\developer_tools\mysql-8.0.16-winx64\bin\mysqld.exe (mysqld 8.0.16) initializing of server in progress as process 1748
2019-07-12T13:33:20.764372Z 0 [ERROR] [MY-010457] [Server] --initialize specified but the data directory has files in it. Aborting.
2019-07-12T13:33:20.764382Z 0 [ERROR] [MY-013236] [Server] Newly created data directory D:\developer_tools\mysql-8.0.16-winx64\data\ is unusable. You can safely remove it.
2019-07-12T13:33:20.770659Z 0 [ERROR] [MY-010119] [Server] Aborting
2019-07-12T13:33:20.770753Z 0 [System] [MY-010910] [Server] D:\developer_tools\mysql-8.0.16-winx64\bin\mysqld.exe: Shutdown complete (mysqld 8.0.16)  MySQL Community Server - GPL.
D:\developer_tools\mysql-8.0.16-winx64\bin>mysqld --initialize --console
2019-07-12T13:33:36.414394Z 0 [System] [MY-013169] [Server] D:\developer_tools\mysql-8.0.16-winx64\bin\mysqld.exe (mysqld 8.0.16) initializing of server in progress as process 2672
2019-07-12T13:33:39.480617Z 5 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: Xhok8!dPzLdz
2019-07-12T13:33:40.463858Z 0 [System] [MY-013170] [Server] D:\developer_tools\mysql-8.0.16-winx64\bin\mysqld.exe (mysqld 8.0.16) initializing of server has completed

Xhok8!dPzLdz 就是随机密码

输入以下安装命令:

mysqld install

启动输入以下命令即可:

net start mysql

注意: 在 5.7 需要初始化 data 目录:

cd C:\web\mysql-8.0.11\bin
mysqld --initialize-insecure

初始化后再运行 net start mysql 即可启动 mysql。

如图所示,mysql已经开启
在这里插入图片描述

5. 登录MySQL

mysql -h 主机名 -u 用户名 -p

参数说明:

-h : 指定客户端所要登录的 MySQL 主机名, 登录本机(localhost 或 127.0.0.1)该参数可以省略;
-u : 登录的用户名;
-p : 告诉服务器将会使用一个密码来登录, 如果所要登录的用户名密码为空, 可以忽略此选项。

如果我们要登录本机的 MySQL 数据库,只需要输入以下命令即可:

mysql -u root -p

按回车确认, 如果安装正确且 MySQL 正在运行, 会得到以下响应:

Enter password:

然后输入密码,成功登录
在这里插入图片描述

6. 修改登录密码

在执行SQL脚本之前,会让你先改密码:

mysql> show databases;
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.

MySQL修改密码语句

ALTER USER ‘root’@‘localhost’ IDENTIFIED WITH mysql_native_password BY ‘新密码’;

本人修改如下:

ALTER USER ‘root’@‘localhost’ IDENTIFIED WITH mysql_native_password BY ‘root’;

mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root';
Query OK, 0 rows affected (0.01 sec)

OK!成功修改!
在这里插入图片描述
测试一下sql语句好不好用,没问题!

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

mysql> use mysql
Database changed
mysql> show tables;
+---------------------------+
| Tables_in_mysql           |
+---------------------------+
| columns_priv              |
| component                 |
| db                        |
| default_roles             |
| engine_cost               |
| func                      |
| general_log               |
| global_grants             |
| gtid_executed             |
| help_category             |
| help_keyword              |
| help_relation             |
| help_topic                |
| innodb_index_stats        |
| innodb_table_stats        |
| password_history          |
| plugin                    |
| procs_priv                |
| proxies_priv              |
| role_edges                |
| server_cost               |
| servers                   |
| slave_master_info         |
| slave_relay_log_info      |
| slave_worker_info         |
| slow_log                  |
| tables_priv               |
| time_zone                 |
| time_zone_leap_second     |
| time_zone_name            |
| time_zone_transition      |
| time_zone_transition_type |
| user                      |
+---------------------------+
33 rows in set (0.00 sec)

mysql> desc user;
+--------------------------+-----------------------------------+------+-----+-----------------------+-------+
| Field                    | Type                              | Null | Key | Default               | Extra |
+--------------------------+-----------------------------------+------+-----+-----------------------+-------+
| Host                     | char(60)                          | NO   | PRI |                       |       |
| User                     | char(32)                          | NO   | PRI |                       |       |
| Select_priv              | enum('N','Y')                     | NO   |     | N                     |       |
| Insert_priv              | enum('N','Y')                     | NO   |     | N                     |       |
| Update_priv              | enum('N','Y')                     | NO   |     | N                     |       |
| Delete_priv              | enum('N','Y')                     | NO   |     | N                     |       |
| Create_priv              | enum('N','Y')                     | NO   |     | N                     |       |
| Drop_priv                | enum('N','Y')                     | NO   |     | N                     |       |
| Reload_priv              | enum('N','Y')                     | NO   |     | N                     |       |
| Shutdown_priv            | enum('N','Y')                     | NO   |     | N                     |       |
| Process_priv             | enum('N','Y')                     | NO   |     | N                     |       |
| File_priv                | enum('N','Y')                     | NO   |     | N                     |       |
| Grant_priv               | enum('N','Y')                     | NO   |     | N                     |       |
| References_priv          | enum('N','Y')                     | NO   |     | N                     |       |
| Index_priv               | enum('N','Y')                     | NO   |     | N                     |       |
| Alter_priv               | enum('N','Y')                     | NO   |     | N                     |       |
| Show_db_priv             | enum('N','Y')                     | NO   |     | N                     |       |
| Super_priv               | enum('N','Y')                     | NO   |     | N                     |       |
| Create_tmp_table_priv    | enum('N','Y')                     | NO   |     | N                     |       |
| Lock_tables_priv         | enum('N','Y')                     | NO   |     | N                     |       |
| Execute_priv             | enum('N','Y')                     | NO   |     | N                     |       |
| Repl_slave_priv          | enum('N','Y')                     | NO   |     | N                     |       |
| Repl_client_priv         | enum('N','Y')                     | NO   |     | N                     |       |
| Create_view_priv         | enum('N','Y')                     | NO   |     | N                     |       |
| Show_view_priv           | enum('N','Y')                     | NO   |     | N                     |       |
| Create_routine_priv      | enum('N','Y')                     | NO   |     | N                     |       |
| Alter_routine_priv       | enum('N','Y')                     | NO   |     | N                     |       |
| Create_user_priv         | enum('N','Y')                     | NO   |     | N                     |       |
| Event_priv               | enum('N','Y')                     | NO   |     | N                     |       |
| Trigger_priv             | enum('N','Y')                     | NO   |     | N                     |       |
| Create_tablespace_priv   | enum('N','Y')                     | NO   |     | N                     |       |
| ssl_type                 | enum('','ANY','X509','SPECIFIED') | NO   |     |                       |       |
| ssl_cipher               | blob                              | NO   |     | NULL                  |       |
| x509_issuer              | blob                              | NO   |     | NULL                  |       |
| x509_subject             | blob                              | NO   |     | NULL                  |       |
| max_questions            | int(11) unsigned                  | NO   |     | 0                     |       |
| max_updates              | int(11) unsigned                  | NO   |     | 0                     |       |
| max_connections          | int(11) unsigned                  | NO   |     | 0                     |       |
| max_user_connections     | int(11) unsigned                  | NO   |     | 0                     |       |
| plugin                   | char(64)                          | NO   |     | caching_sha2_password |       |
| authentication_string    | text                              | YES  |     | NULL                  |       |
| password_expired         | enum('N','Y')                     | NO   |     | N                     |       |
| password_last_changed    | timestamp                         | YES  |     | NULL                  |       |
| password_lifetime        | smallint(5) unsigned              | YES  |     | NULL                  |       |
| account_locked           | enum('N','Y')                     | NO   |     | N                     |       |
| Create_role_priv         | enum('N','Y')                     | NO   |     | N                     |       |
| Drop_role_priv           | enum('N','Y')                     | NO   |     | N                     |       |
| Password_reuse_history   | smallint(5) unsigned              | YES  |     | NULL                  |       |
| Password_reuse_time      | smallint(5) unsigned              | YES  |     | NULL                  |       |
| Password_require_current | enum('N','Y')                     | YES  |     | NULL                  |       |
| User_attributes          | json                              | YES  |     | NULL                  |       |
+--------------------------+-----------------------------------+------+-----+-----------------------+-------+
51 rows in set (0.00 sec)

7. 配置环境变量

虽然MySQL安装成功,但是每次都切换到D:\developer_tools\mysql-8.0.16-winx64\bin下来执行相关操作是很麻烦的,配置环境变量后就可方便的操作MySQL了。
右键‘计算机’->‘属性’->‘高级系统设置’->‘环境变量’,在系统变量下找到path,点击编辑按钮进入编辑path对话框,在变量值里面前面加上MySQL的解压路径下的bin目录。

在这里插入图片描述

8. MySQL的开启和关闭

电脑的服务里有Mysql,打开就可以了,mysql的服务请不要随意关闭,否则不能使用。

Windows 系统下
在 Windows 系统下,打开命令窗口(cmd),进入 MySQL 安装目录的 bin 目录。

启动:

cd c:/mysql/bin
mysqld --console

关闭:

cd c:/mysql/bin
mysqladmin -uroot shutdown

进入数据库管理,命令行模式

mysql -u root -p

9. 创建数据库

create DATABASE RUNOOB;

或者

CREATE DATABASE IF NOT EXISTS RUNOOB DEFAULT CHARSET utf8 COLLATE
utf8_general_ci;

创建数据库,该命令的作用:

  1. 如果数据库不存在则创建,存在则不创建。
  2. 创建RUNOOB数据库,并设定编码集为utf8

10. 删除数据库

mysqladmin -u root -p drop RUNOOB

执行以上删除数据库命令后,会出现一个提示框,来确认是否真的删除数据库:

Dropping the database is potentially a very bad thing to do.
Any data stored in the database will be destroyed.

Do you really want to drop the 'RUNOOB' database [y/N] y
Database "RUNOOB" dropped

11. 选择数据库

mysql> use RUNOOB;
Database changed

12. 创建数据库

以下为创建MySQL数据表的SQL通用语法:

CREATE TABLE table_name (column_name column_type);

以下例子中我们将在 RUNOOB 数据库中创建数据表runoob_tbl:

CREATE TABLE IF NOT EXISTS `runoob_tbl`(
   `runoob_id` INT UNSIGNED AUTO_INCREMENT,
   `runoob_title` VARCHAR(100) NOT NULL,
   `runoob_author` VARCHAR(40) NOT NULL,
   `submission_date` DATE,
   PRIMARY KEY ( `runoob_id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

实例解析:

如果你不想字段为 NULL 可以设置字段的属性为 NOT NULL, 在操作数据库时如果输入该字段的数据为NULL ,就会报错。
AUTO_INCREMENT定义列为自增的属性,一般用于主键,数值会自动加1。
PRIMARY KEY关键字用于定义列为主键。 您可以使用多列来定义主键,列间以逗号分隔。
ENGINE 设置存储引擎,CHARSET 设置编码。

命令行创建表

root@host# mysql -u root -p
Enter password:*******
mysql> use RUNOOB;
Database changed
mysql> CREATE TABLE runoob_tbl(
   -> runoob_id INT NOT NULL AUTO_INCREMENT,
   -> runoob_title VARCHAR(100) NOT NULL,
   -> runoob_author VARCHAR(40) NOT NULL,
   -> submission_date DATE,
   -> PRIMARY KEY ( runoob_id )
   -> )ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.16 sec)
mysql>

执行成功后,就可以通过命令行查看表结构

mysql> show tables;
+------------------+
| Tables_in_runoob |
+------------------+
| runoob_tbl       |
+------------------+
1 row in set (0.00 sec)

mysql> desc runoob_tbl;
+-----------------+------------------+------+-----+---------+----------------+
| Field           | Type             | Null | Key | Default | Extra          |
+-----------------+------------------+------+-----+---------+----------------+
| runoob_id       | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| runoob_title    | varchar(100)     | NO   |     | NULL    |                |
| runoob_author   | varchar(40)      | NO   |     | NULL    |                |
| submission_date | date             | YES  |     | NULL    |                |
+-----------------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

注意:

创建 MySql 的表时,表名和字段名外面的符号 ` 不是单引号,而是英文输入法状态下的反单引号,也就是键盘左上角 esc 按键下面的那一个 ~ 按键,坑惨了。

反引号是为了区分 MySql 关键字与普通字符而引入的符号,一般的,表名与字段名都使用反引号。

13. 删除数据表

以下为删除MySQL数据表的通用语法:

DROP TABLE table_name ;

以下实例删除了数据表runoob_tbl

root@host# mysql -u root -p
Enter password:*******
mysql> use RUNOOB;
Database changed
mysql> DROP TABLE runoob_tbl
Query OK, 0 rows affected (0.8 sec)
mysql>

执行成功后,我们使用以下命令,就看不到 runoob_tbl 表了

mysql> show tables;
Empty set (0.01 sec)

强化巩固:(很重要)

第一部分:

删除表内数据,用 delete。格式为:

delete from 表名 where 删除条件;

实例:删除学生表内姓名为张三的记录。

delete from student where T_name = “张三”;

清除表内数据,保存表结构,用 truncate。格式为:

truncate table 表名;

实例:清除学生表内的所有数据。

truncate table student;

删除表用 drop,就是啥都没了。格式为:

drop table 表名;

实例:删除学生表。

drop table student;

1、当你不再需要该表时, 用 drop;

2、当你仍要保留该表,但要删除所有记录时, 用 truncate;

3、当你要删除部分记录时, 用 delete。

第二部分:

MySQL 删除表的几种情况:

1、drop table table_name : 删除表全部数据和表结构,立刻释放磁盘空间,不管是 Innodb 和 MyISAM;

实例,删除学生表:

drop table student;

2、truncate table table_name : 删除表全部数据,保留表结构,立刻释放磁盘空间 ,不管是 Innodb 和 MyISAM;

实例,删除学生表:

truncate table student;

3、delete from table_name : 删除表全部数据,表结构不变,对于 MyISAM 会立刻释放磁盘空间,InnoDB 不会释放磁盘空间;

实例,删除学生表:

delete from student;

4、delete from table_name where xxx : 带条件的删除,表结构不变,不管是 innodb 还是 MyISAM 都不会释放磁盘空间;

实例,删除学生表中姓名为 “张三” 的数据:

delete from student where T_name = “张三”;

5、delete 操作以后,使用 optimize table table_name 会立刻释放磁盘空间,不管是 innodb 还是 myisam;

实例,删除学生表中姓名为 “张三” 的数据:

delete from student where T_name = “张三”;

实例,释放学生表的表空间:

optimize table student;

6、delete from 表以后虽然未释放磁盘空间,但是下次插入数据的时候,仍然可以使用这部分空间。

14. 插入数据

以下为向MySQL数据表插入数据通用的 INSERT INTO SQL语法:

INSERT INTO table_name ( field1, field2,…fieldN )
VALUES
( value1, value2,…valueN );

如果数据是字符型,必须使用单引号或者双引号,如:“value”。

我使用的插入语句:

INSERT INTO runoob_tbl
(runoob_title, runoob_author, submission_date)
VALUES
(“学习 PHP”, “菜鸟教程”, NOW());

INSERT INTO runoob_tbl
(runoob_title, runoob_author, submission_date)
VALUES
(“学习 MySQL”, “菜鸟教程”, NOW());

INSERT INTO runoob_tbl
(runoob_title, runoob_author, submission_date)
VALUES
(“JAVA 教程”, “RUNOOB.COM”, “2019-07-13”);

命令行插入数据:

root@host# mysql -u root -p password;
Enter password:*******
mysql> use RUNOOB;
Database changed
mysql> INSERT INTO runoob_tbl
    -> (runoob_title, runoob_author, submission_date)
    -> VALUES
    -> ("学习 PHP", "菜鸟教程", NOW());
Query OK, 1 rows affected, 1 warnings (0.01 sec)
mysql> INSERT INTO runoob_tbl
    -> (runoob_title, runoob_author, submission_date)
    -> VALUES
    -> ("学习 MySQL", "菜鸟教程", NOW());
Query OK, 1 rows affected, 1 warnings (0.01 sec)
mysql> INSERT INTO runoob_tbl
    -> (runoob_title, runoob_author, submission_date)
    -> VALUES
    -> ("JAVA 教程", "RUNOOB.COM", "2019-07-13");
Query OK, 1 rows affected (0.00 sec)
mysql>

在以上实例中,我们并没有提供 runoob_id 的数据,因为该字段我们在创建表的时候已经设置它为 AUTO_INCREMENT(自动增加) 属性。 所以,该字段会自动递增而不需要我们去设置。实例中 NOW() 是一个 MySQL 函数,该函数返回日期和时间。

读取数据表:

select * from runoob_tbl;

输出结果为:

mysql> select * from runoob_tbl;                 );
+-----------+--------------+---------------+-----------------+
| runoob_id | runoob_title | runoob_author | submission_date |
+-----------+--------------+---------------+-----------------+
|         1 | 学习 PHP     | 菜鸟教程      | 2019-07-13      |
|         2 | 学习 MySQL   | 菜鸟教程      | 2019-07-13      |
|         3 | JAVA 教程    | RUNOOB.COM    | 2019-07-13      |
+-----------+--------------+---------------+-----------------+
3 rows in set (0.00 sec)

强化巩固:

添加数据的时候可以规定列进行添加。

如果所有的列都要添加数据可以不规定列进行添加数据:

mysql> INSERT INTO runoob_tbl
-> VALUES
-> (0, “JAVA 教程”, “RUNOOB.COM”, ‘2019-07-13’);

第一列如果没有设置主键自增(PRINARY KEY AUTO_INCREMENT)的话添加第一列数据比较容易错乱,要不断的查询表看数据。

如果添加过主键自增(PRINARY KEY AUTO_INCREMENT)第一列在增加数据的时候,可以写为0或者null,这样添加数据可以自增, 从而可以添加全部数据,而不用特意规定那几列添加数据

15. 查询数据

以下为在MySQL数据库中查询数据通用的 SELECT 语法:

SELECT column_name,column_name
FROM table_name
[WHERE Clause]
[LIMIT N][ OFFSET M]
  • 查询语句中你可以使用一个或者多个表,表之间使用逗号(,)分割,并使用WHERE语句来设定查询条件。
  • SELECT命令可以读取一条或者多条记录。
  • 你可以使用星号(*)来代替其他字段,SELECT语句会返回表的所有字段数据
  • 你可以使用 WHERE语句来包含任何条件。
  • 你可以使用 LIMIT 属性来设定返回的记录数。
  • 你可以通过OFFSET指定SELECT语句开始查询的数据偏移量。默认情况下偏移量为0。

查询语句:

select * from runoob_tbl;

查询内容:

mysql> select * from runoob_tbl;                 );
+-----------+--------------+---------------+-----------------+
| runoob_id | runoob_title | runoob_author | submission_date |
+-----------+--------------+---------------+-----------------+
|         1 | 学习 PHP     | 菜鸟教程      | 2019-07-13      |
|         2 | 学习 MySQL   | 菜鸟教程      | 2019-07-13      |
|         3 | JAVA 教程    | RUNOOB.COM    | 2019-07-13      |
+-----------+--------------+---------------+-----------------+
3 rows in set (0.00 sec)

16 WHERE 子句

以下是 SQL SELECT 语句使用 WHERE 子句从数据表中读取数据的通用语法:

SELECT field1, field2,…fieldN FROM table_name1, table_name2…
[WHERE condition1 [AND [OR]] condition2…

  • 查询语句中你可以使用一个或者多个表,表之间使用逗号, 分割,并使用WHERE语句来设定查询条件。
  • 你可以在 WHERE子句中指定任何条件。
  • 你可以使用 AND 或者 OR 指定一个或多个条件。
  • WHERE 子句也可以运用于 SQL 的 DELETE 或者UPDATE 命令。
  • WHERE 子句类似于程序语言中的 if 条件,根据 MySQL 表中的字段值来读取指定的数据。

命令提示符中读取数据:

SQL SELECT WHERE 子句:

SELECT * from runoob_tbl WHERE runoob_author=‘菜鸟教程’;

输出结果:

mysql> select * from runoob_tbl where runoob_author='菜鸟教程';
+-----------+--------------+---------------+-----------------+
| runoob_id | runoob_title | runoob_author | submission_date |
+-----------+--------------+---------------+-----------------+
|         1 | 学习 PHP     | 菜鸟教程      | 2019-07-13      |
|         2 | 学习 MySQL   | 菜鸟教程      | 2019-07-13      |
+-----------+--------------+---------------+-----------------+
2 rows in set (0.00 sec)

MySQL 的 WHERE 子句的字符串比较是不区分大小写的。 你可以使用 BINARY 关键字来设定 WHERE 子句的字符串比较是区分大小写的。

如下实例:

BINARY 关键字

mysql> SELECT * from runoob_tbl WHERE BINARY runoob_author='runoob.com';
Empty set (0.01 sec)
 
mysql> SELECT * from runoob_tbl WHERE BINARY runoob_author='RUNOOB.COM';
+-----------+--------------+---------------+-----------------+
| runoob_id | runoob_title | runoob_author | submission_date |
+-----------+--------------+---------------+-----------------+
|         3 | JAVA 教程    | RUNOOB.COM    | 2019-07-13      |
+-----------+--------------+---------------+-----------------+
1 row in set (0.00 sec)

实例中使用了 BINARY 关键字,是区分大小写的,所以 runoob_author=‘runoob.com’ 的查询条件是没有数据的。

强化巩固:

where: 数据库中常用的是where关键字,用于在初始表中筛选查询。它是一个约束声明,用于约束数据,在返回结果集之前起作用。

group by: 对select查询出来的结果集按照某个字段或者表达式进行分组,获得一组组的集合,然后从每组中取出一个指定字段或者表达式的值。

having: 用于对where和group by查询出来的分组经行过滤,查出满足条件的分组结果。它是一个过滤声明,是在查询返回结果集以后对查询结果进行的过滤操作。

执行顺序

select –>where –> group by–> having–>order by

17 UPDATE 更新

以下是 UPDATE 命令修改 MySQL 数据表数据的通用 SQL 语法:

UPDATE table_name SET field1=new-value1, field2=new-value2 [WHERE Clause]

  • 你可以同时更新一个或多个字段。
  • 你可以在 WHERE 子句中指定任何条件。
  • 你可以在一个单独表中同时更新数据。

SQL UPDATE 语句:

UPDATE runoob_tbl SET runoob_title=‘学习 C++’ WHERE runoob_id=3;

以下实例将更新数据表中 runoob_id 为 3 的 runoob_title 字段值:

mysql> update runoob_tbl set runoob_title='学习C++' where runoob_id=3;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT * from runoob_tbl WHERE runoob_id=3;
+-----------+--------------+---------------+-----------------+
| runoob_id | runoob_title | runoob_author | submission_date |
+-----------+--------------+---------------+-----------------+
|         3 | 学习C++      | RUNOOB.COM    | 2019-07-13      |
+-----------+--------------+---------------+-----------------+
1 row in set (0.00 sec)

强化巩固:

第一部分:

update 语句可用来修改表中的数据, 简单来说基本的使用形式为:

update 表名称 set 列名称=新值 where 更新条件;

以下是在表 students 中的实例:

将 id 为 5 的手机号改为默认的 - : update students set tel=default where id=5;

将所有人的年龄增加 1: update students set age=age+1;

将手机号为 13288097888 的姓名改为 “小明”, 年龄改为 19: update students set name=“小明”, age=19 where tel=“13288097888”;

第二部分:

UPDATE替换某个字段中的某个字符

当我们需要将字段中的特定字符串批量修改为其他字符串时,可已使用以下操作:

UPDATE table_name SET field=REPLACE(field, ‘old-string’, ‘new-string’) [WHERE Clause]

实例:

以下实例将更新 runoob_id 为 3 的runoob_title 字段值的 “C++” 替换为 “Python”:

UPDATE runoob_tbl SET runoob_title = REPLACE(runoob_title, ‘C++’,‘Python’) where runoob_id = 3;

18. DELETE 语句

以下是 SQL DELETE 语句从 MySQL 数据表中删除数据的通用语法:

DELETE FROM table_name [WHERE Clause]

  • 如果没有指定 WHERE 子句,MySQL 表中的所有记录将被删除。
  • 你可以在 WHERE 子句中指定任何条件。
  • 您可以在单个表中一次性删除记录。

当你想删除数据表中指定的记录时 WHERE 子句是非常有用的。

以下实例将删除 runoob_tbl 表中 runoob_id 为3 的记录:

DELETE FROM runoob_tbl WHERE runoob_id=3;

DELETE 语句:

mysql> use RUNOOB;
Database changed
mysql> DELETE FROM runoob_tbl WHERE runoob_id=3;
Query OK, 1 row affected (0.01 sec)

强化巩固:

第一部分:

delete 语句用于删除表中的数据, 基本用法为:
delete from 表名称 where 删除条件;
以下是在表 students 中的实例:
删除 id 为 3 的行: delete from students where id=3;
删除所有年龄小于 21 岁的数据: delete from students where age<20;
删除表中的所有数据: delete from students;

第二部分:

delete,drop,truncate 都有删除表的作用,区别在于:

1、delete 和 truncate 仅仅删除表数据,drop 连表数据和表结构一起删除,打个比方,delete 是单杀,truncate 是团灭,drop 是把电脑摔了。
2、delete 是 DML 语句,操作完以后如果没有不想提交事务还可以回滚,truncate 和 drop 是 DDL 语句,操作完马上生效,不能回滚,打个比方,delete 是发微信说分手,后悔还可以撤回,truncate 和 drop 是直接扇耳光说滚,不能反悔。
3、执行的速度上,drop>truncate>delete,打个比方,drop 是神舟火箭,truncate 是和谐号动车,delete 是自行车。

19. LIKE 子句

我们知道在 MySQL 中使用 SQL SELECT 命令来读取数据, 同时我们可以在 SELECT 语句中使用 WHERE 子句来获取指定的记录。

WHERE 子句中可以使用等号 = 来设定获取数据的条件,如 “runoob_author = ‘RUNOOB.COM’”。

但是有时候我们需要获取 runoob_author 字段含有 “COM” 字符的所有记录,这时我们就需要在 WHERE 子句中使用 SQL LIKE 子句。

SQL LIKE 子句中使用百分号 %字符来表示任意字符,类似于UNIX或正则表达式中的星号 *。

如果没有使用百分号 %, LIKE 子句与等号 = 的效果是一样的。

以下是 SQL SELECT 语句使用 LIKE 子句从数据表中读取数据的通用语法:

SELECT field1, field2,…fieldN FROM table_name WHERE field1 LIKE
condition1 [AND [OR]] filed2 = ‘somevalue’

  • 你可以在 WHERE 子句中指定任何条件。
  • 你可以在 WHERE 子句中使用LIKE子句。
  • 你可以使用LIKE子句代替等号 =。
  • LIKE 通常与 % 一同使用,类似于一个元字符的搜索。
  • 你可以使用 AND 或者 OR 指定一个或多个条件。
  • 你可以在DELETE 或 UPDATE 命令中使用 WHERE…LIKE 子句来指定条件。

以下是我们将 runoob_tbl 表中获取 runoob_author 字段中以 COM 为结尾的的所有记录:

SELETE * from runoob_tbl WHERE runoob_author LIKE ‘%COM’;

SQL LIKE 语句:

mysql> use RUNOOB;
Database changed
mysql> SELECT * from runoob_tbl  WHERE runoob_author LIKE '%COM';
+-----------+--------------+---------------+-----------------+
| runoob_id | runoob_title | runoob_author | submission_date |
+-----------+--------------+---------------+-----------------+
|         4 | JAVA 教程    | RUNOOB.COM    | 2019-07-13      |
+-----------+--------------+---------------+-----------------+
1 row in set (0.00 sec)

强化巩固:

第一部分:

like 匹配/模糊匹配,会与 % 和 _ 结合使用。

'%a'     //以a结尾的数据
'a%'     //以a开头的数据
'%a%'    //含有a的数据
'_a_'    //三位且中间字母是a的
'_a'     //两位且结尾字母是a的
'a_'     //两位且开头字母是a的

查询以 java 字段开头的信息。

SELECT * FROM position WHERE name LIKE ‘java%’;

查询包含 java 字段的信息。

SELECT * FROM position WHERE name LIKE ‘%java%’;

查询以 java 字段结尾的信息。

SELECT * FROM position WHERE name LIKE ‘%java’;

第二部分:

在 where like 的条件查询中,SQL 提供了四种匹配方式。

  • %:表示任意 0 个或多个字符。可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示。
  • _:表示任意单个字符。匹配单个任意字符,它常用来限制表达式的字符长度语句。
  • [ ]:表示括号内所列字符中的一个(类似正则表达式)。指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个。
  • [ ^ ] :表示不在括号所列之内的单个字符。其取值和 [ ] 相同,但它要求所匹配对象为指定字符以外的任一个字符。
  • 查询内容包含通配符时,由于通配符的缘故,导致我们查询特殊字符 “%”、“_”、“[” 的语句无法正常实现,而把特殊字符用 “[ ]”括起便可正常查询。

20. UNION 操作符

MySQL UNION 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中。多个 SELECT 语句会删除重复的数据。

MySQL UNION 操作符语法格式

SELECT expression1, expression2, … expression_n FROM tables [WHERE
conditions] UNION [ALL | DISTINCT] SELECT expression1, expression2,
… expression_n FROM tables [WHERE conditions];

参数

  • expression1, expression2, … expression_n: 要检索的列。

  • tables: 要检索的数据表。

  • WHERE conditions: 可选, 检索条件。

  • DISTINCT: 可选,删除结果集中重复的数据。默认情况下 UNION 操作符已经删除了重复数据,所以 DISTINCT修饰符对结果没啥影响。

  • ALL: 可选,返回所有结果集,包含重复数据。

演示数据库

在本教程中,我们将使用 RUNOOB 样本数据库。

下面是选自 “Websites” 表的数据:

mysql> SELECT * FROM Websites;
+----+--------------+---------------------------+-------+---------+
| id | name         | url                       | alexa | country |
+----+--------------+---------------------------+-------+---------+
| 1  | Google       | https://www.google.cm/    | 1     | USA     |
| 2  | 淘宝          | https://www.taobao.com/   | 13    | CN      |
| 3  | 菜鸟教程      | http://www.runoob.com/    | 4689  | CN      |
| 4  | 微博          | http://weibo.com/         | 20    | CN      |
| 5  | Facebook     | https://www.facebook.com/ | 3     | USA     |
| 7  | stackoverflow | http://stackoverflow.com/ |   0 | IND     |
+----+---------------+---------------------------+-------+---------+

下面是 “apps” APP 的数据:

mysql> SELECT * FROM apps;
+----+------------+-------------------------+---------+
| id | app_name   | url                     | country |
+----+------------+-------------------------+---------+
|  1 | QQ APP     | http://im.qq.com/       | CN      |
|  2 | 微博 APP   | http://weibo.com/       | CN      |
|  3 | 淘宝 APP   | https://www.taobao.com/ | CN      |
+----+------------+-------------------------+---------+
3 rows in set (0.00 sec)

SQL UNION 实例

下面的 SQL 语句从 “Websites” 和 “apps” 表中选取所有不同的country(只有不同的值):

SELECT country FROM Websites
UNION
SELECT country FROM apps
ORDER BY country;

执行以上 SQL 输出结果如下:
在这里插入图片描述

SQL UNION ALL 实例

下面的 SQL 语句使用 UNION ALL 从 “Websites” 和 “apps” 表中选取所有的country(也有重复的值):

SELECT country FROM Websites
UNION ALL
SELECT country FROM apps
ORDER BY country;

执行以上 SQL 输出结果如下:
在这里插入图片描述

带有 WHERE 的 SQL UNION ALL

下面的 SQL 语句使用 UNION ALL 从 “Websites” 和 “apps” 表中选取所有的中国(CN)的数据(也有重复的值):

实例

SELECT country, name FROM Websites
WHERE country=‘CN’
UNION ALL
SELECT country, app_name FROM apps
WHERE
country=‘CN’
ORDER BY country;

执行以上 SQL 输出结果如下:
在这里插入图片描述
强化巩固:

UNION 语句: 用于将不同表中相同列中查询的数据展示出来;(不包括重复数据)

UNION ALL 语句: 用于将不同表中相同列中查询的数据展示出来;(包括重复数据)

使用形式如下:

SELECT 列名称 FROM 表名称 UNION SELECT 列名称 FROM 表名称 ORDER BY 列名称;
SELECT 列名称 FROM 表名称 UNION ALL SELECT 列名称 FROM 表名称 ORDER BY 列名称;

21. 排序

以下是 SQL SELECT 语句使用 ORDER BY 子句将查询数据排序后再返回数据:

SELECT field1, field2,…fieldN
FROM table_name1, table_name2…
ORDERBY field1 [ASC [DESC][默认 ASC]], [field2…] [ASC [DESC][默认 ASC]]

  • 你可以使用任何字段来作为排序的条件,从而返回排序后的查询结果。
  • 你可以设定多个字段来排序。
  • 你可以使用 ASC 或 DESC关键字来设置查询结果是按升序或降序排列。 默认情况下,它是按升序排列。
  • 你可以添加 WHERE…LIKE 子句来设置条件。

以下将在 SQL SELECT 语句中使用 ORDER BY 子句来读取MySQL 数据表 runoob_tbl 中的数据:

尝试以下实例,结果将按升序及降序排列。

SELECT * FROM runoob_tbl ORDER BY submission_date;

默认asc,升序排序。

mysql> use RUNOOB;
Database changed
mysql> SELECT * from runoob_tbl ORDER BY submission_date ASC;
+-----------+--------------+---------------+-----------------+
| runoob_id | runoob_title | runoob_author | submission_date |
+-----------+--------------+---------------+-----------------+
|         3 | JAVA 教程    | RUNOOB.COM    | 2019-07-11      |
|         2 | 学习 MySQL   | 菜鸟教程      | 2019-07-12      |
|         1 | 学习 PHP     | 菜鸟教程      | 2019-07-13      |
+-----------+--------------+---------------+-----------------+
3 rows in set (0.00 sec)

读取 runoob_tbl 表中所有数据并按 submission_date 字段的降序(desc)排列。

SELECT * FROM runoob_tbl ORDER BY submission_date DESC;

mysql> select * from runoob_tbl order by submission_date desc;
+-----------+--------------+---------------+-----------------+
| runoob_id | runoob_title | runoob_author | submission_date |
+-----------+--------------+---------------+-----------------+
|         1 | 学习 PHP     | 菜鸟教程      | 2019-07-13      |
|         2 | 学习 MySQL   | 菜鸟教程      | 2019-07-12      |
|         3 | JAVA 教程    | RUNOOB.COM    | 2019-07-11      |
+-----------+--------------+---------------+-----------------+
3 rows in set (0.00 sec)

强化巩固:

MySQL 排序我们知道从 MySQL 表中使用 SQL SELECT 语句来读取:

MySQL 拼音排序

如果字符集采用的是 gbk(汉字编码字符集),直接在查询语句后边添加 ORDER BY:

SELECT *
FROM runoob_tbl
ORDER BY runoob_title;

如果字符集采用的是 utf8(万国码),需要先对字段进行转码然后排序:

SELECT *
FROM runoob_tbl
ORDER BY CONVERT(runoob_title using gbk);

22. GROUP BY 语句

GROUP BY 语句根据一个或多个列对结果集进行分组。

在分组的列上我们可以使用 COUNT, SUM, AVG 等函数。

GROUP BY 语法

SELECT column_name, function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name;

实例演示

本章节实例使用到了以下表结构及数据,使用前我们可以先将以下数据导入数据库中。

SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
--  Table structure for `employee_tbl`
-- ----------------------------
DROP TABLE IF EXISTS `employee_tbl`;
CREATE TABLE `employee_tbl` (
  `id` int(11) NOT NULL,
  `name` char(10) NOT NULL DEFAULT '',
  `date` datetime NOT NULL,
  `singin` tinyint(4) NOT NULL DEFAULT '0' COMMENT '登录次数',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `employee_tbl`
-- ----------------------------
BEGIN;
INSERT INTO `employee_tbl` VALUES ('1', '小明', '2016-04-22 15:25:33', '1'), ('2', '小王', '2016-04-20 15:25:47', '3'), ('3', '小丽', '2016-04-19 15:26:02', '2'), ('4', '小王', '2016-04-07 15:26:14', '4'), ('5', '小明', '2016-04-11 15:26:40', '4'), ('6', '小明', '2016-04-04 15:26:54', '2');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;

在navicat中导入,以下为详细操作:
在这里插入图片描述
导入成功后,执行以下 SQL 语句:

mysql> set names utf8;
mysql> SELECT * FROM employee_tbl;
+----+--------+---------------------+--------+
| id | name   | date                | singin |
+----+--------+---------------------+--------+
|  1 | 小明 | 2016-04-22 15:25:33 |      1 |
|  2 | 小王 | 2016-04-20 15:25:47 |      3 |
|  3 | 小丽 | 2016-04-19 15:26:02 |      2 |
|  4 | 小王 | 2016-04-07 15:26:14 |      4 |
|  5 | 小明 | 2016-04-11 15:26:40 |      4 |
|  6 | 小明 | 2016-04-04 15:26:54 |      2 |
+----+--------+---------------------+--------+
6 rows in set (0.00 sec)

注意:如果有中文乱码问题请将utf8改成gbk

set names utf8;

接下来我们使用 GROUP BY 语句 将数据表按名字进行分组,并统计每个人有多少条记录:

SELECT name,COUNT(*) FROM employee_tbl GROUP BY name;

mysql> SELECT name,COUNT(*) FROM employee_tbl GROUP BY name;
+------+----------+
| name | COUNT(*) |
+------+----------+
| 小明 |        3 |
| 小王 |        2 |
| 小丽 |        1 |
+------+----------+
3 rows in set (0.00 sec)

使用 WITH ROLLUP

WITH ROLLUP 可以实现在分组统计数据基础上再进行相同的统计(SUM,AVG,COUNT…)。

例如我们将以上的数据表按名字进行分组,再统计每个人登录的次数:

SELECT name,SUM(singin) as singin_count FROM employee_tbl GROUP BY name WITH ROLLUP;

mysql> SELECT name, SUM(singin) as singin_count FROM  employee_tbl GROUP BY name WITH ROLLUP;
+--------+--------------+
| name   | singin_count |
+--------+--------------+
| 小丽 |            2 |
| 小明 |            7 |
| 小王 |            7 |
| NULL   |           16 |
+--------+--------------+
4 rows in set (0.00 sec)

其中记录 NULL 表示所有人的登录次数。

我们可以使用 coalesce 来设置一个可以取代 NUll 的名称,coalesce 语法:

select coalesce(a,b,c);

参数说明:如果a== null,则选择b;如果b==null,则选择c;如果a!=null,则选择a;如果a b c 都为null ,则返回为null(没意义)。
以下实例中如果名字为空我们使用总数代替:

mysql> SELECT coalesce(name, '总数'), SUM(singin) as singin_count FROM  employee_tbl GROUP BY name WITH ROLLUP;
+--------------------------+--------------+
| coalesce(name, '总数') | singin_count |
+--------------------------+--------------+
| 小丽                   |            2 |
| 小明                   |            7 |
| 小王                   |            7 |
| 总数                   |           16 |
+--------------------------+--------------+
4 rows in set (0.01 sec)

23. 连接的使用(逐渐深入)

在前几章节中,我们已经学会了如何在一张表中读取数据,这是相对简单的,但是在真正的应用中经常需要从多个数据表中读取数据。

本章节我们将向大家介绍如何使用 MySQL 的 JOIN 在两个或多个表中查询数据。

你可以在 SELECT, UPDATE 和 DELETE 语句中使用 Mysql 的 JOIN 来联合多表查询。

JOIN 按照功能大致分为如下三类:

  • INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录。
  • LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录。
  • RIGHT JOIN(右连接): 与 LEFT JOIN 相反,用于获取右表所有记录,即使左表没有对应匹配的记录。
mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a INNER JOIN tcount_tbl b ON a.runoob_author=b.runoob_author;
+-----------+---------------+--------------+
| runoob_id | runoob_author | runoob_count |
+-----------+---------------+--------------+
|         1 | 菜鸟教程      |           10 |
|         2 | 菜鸟教程      |           10 |
|         3 | RUNOOB.COM    |           20 |
|         4 | RUNOOB.COM    |           20 |
+-----------+---------------+--------------+
4 rows in set (0.00 sec)

首先,创建一张新的表,用navicat执行以下语句:

/*
 Navicat MySQL Data Transfer

 Source Server         : 127.0.0.1
 Source Server Version : 50621
 Source Host           : localhost
 Source Database       : RUNOOB

 Target Server Version : 50621
 File Encoding         : utf-8

 Date: 04/13/2017 14:25:12 PM
*/

SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
--  Table structure for `runoob_tbl`
-- ----------------------------
DROP TABLE IF EXISTS `runoob_tbl`;
CREATE TABLE `runoob_tbl` (
  `runoob_id` int(11) NOT NULL AUTO_INCREMENT,
  `runoob_title` varchar(100) NOT NULL,
  `runoob_author` varchar(40) NOT NULL,
  `submission_date` date DEFAULT NULL,
  PRIMARY KEY (`runoob_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `runoob_tbl`
-- ----------------------------
BEGIN;
INSERT INTO `runoob_tbl` VALUES ('1', '学习 PHP', '菜鸟教程', '2017-04-12'), ('2', '学习 MySQL', '菜鸟教程', '2017-04-12'), ('3', '学习 Java', 'RUNOOB.COM', '2015-05-01'), ('4', '学习 Python', 'RUNOOB.COM', '2016-03-06'), ('5', '学习 C', 'FK', '2017-04-05');
COMMIT;

-- ----------------------------
--  Table structure for `tcount_tbl`
-- ----------------------------
DROP TABLE IF EXISTS `tcount_tbl`;
CREATE TABLE `tcount_tbl` (
  `runoob_author` varchar(255) NOT NULL DEFAULT '',
  `runoob_count` int(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `tcount_tbl`
-- ----------------------------
BEGIN;
INSERT INTO `tcount_tbl` VALUES ('菜鸟教程', '10'), ('RUNOOB.COM ', '20'), ('Google', '22');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;

执行后,会生成一张新的表格, tcount_tbl。

实例 INNER JOIN 内连接,等值连接

我们在RUNOOB数据库中有两张表 tcount_tbl 和 runoob_tbl。两张数据表数据如下:

mysql> use RUNOOB;
Database changed

mysql> SELECT * from runoob_tbl;
+-----------+---------------+---------------+-----------------+
| runoob_id | runoob_title  | runoob_author | submission_date |
+-----------+---------------+---------------+-----------------+
| 1         | 学习 PHP    | 菜鸟教程  | 2017-04-12      |
| 2         | 学习 MySQL  | 菜鸟教程  | 2017-04-12      |
| 3         | 学习 Java   | RUNOOB.COM    | 2015-05-01      |
| 4         | 学习 Python | RUNOOB.COM    | 2016-03-06      |
| 5         | 学习 C      | FK            | 2017-04-05      |
+-----------+---------------+---------------+-----------------+
5 rows in set (0.01 sec)

mysql> SELECT * FROM tcount_tbl;
+---------------+--------------+
| runoob_author | runoob_count |
+---------------+--------------+
| 菜鸟教程       | 10           |
| RUNOOB.COM    | 20           |
| Google        | 22           |
+---------------+--------------+
3 rows in set (0.01 sec)

接下来我们就使用MySQL的INNER JOIN(也可以省略 INNER 使用 JOIN,效果一样) 来连接以上两张表来读取runoob_tbl表中所有runoob_author字段在tcount_tbl表对应的runoob_count字段值:
(a表是runoob_tbl,b表是tcount_tbl)

INNER JOIN

mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a INNER JOIN tcount_tbl b ON a.runoob_author=b.runoob_author;
+-----------+---------------+--------------+
| runoob_id | runoob_author | runoob_count |
+-----------+---------------+--------------+
|         1 | 菜鸟教程      |           10 |
|         2 | 菜鸟教程      |           10 |
|         3 | RUNOOB.COM    |           20 |
|         4 | RUNOOB.COM    |           20 |
+-----------+---------------+--------------+
4 rows in set (0.00 sec)

以上 SQL 语句等价于WHERE子句:

mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a, tcount_tbl b WHERE a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1           | 菜鸟教程         | 10             |
| 2           | 菜鸟教程         | 10             |
| 3           | RUNOOB.COM      | 20             |
| 4           | RUNOOB.COM      | 20             |
+-------------+-----------------+----------------+
4 rows in set (0.01 sec)

在这里插入图片描述

实例 LEFT JOIN 左连接

MySQL left join 与 join 有所不同。 MySQL LEFT JOIN 会读取左边数据表的全部数据,即便右边表无对应数据。

尝试以下实例,以 runoob_tbl 为左表,tcount_tbl 为右表,理解 MySQL LEFT JOIN 的应用:

mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a LEFT JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1           | 菜鸟教程   	    | 10             |
| 2           | 菜鸟教程  	    | 10             |
| 3           | RUNOOB.COM      | 20             |
| 4           | RUNOOB.COM      | 20             |
| 5           | FK              | NULL           |
+-------------+-----------------+----------------+
5 rows in set (0.01 sec)

以上实例中使用了 LEFT JOIN,该语句会读取左边的数据表 runoob_tbl 的所有选取的字段数据,即便在右侧表 tcount_tbl中 没有对应的 runoob_author 字段值。
在这里插入图片描述

实例 RIGHT JOIN 右连接

MySQL RIGHT JOIN 会读取右边数据表的全部数据,即便左边边表无对应数据。

尝试以下实例,以 runoob_tbl 为左表,tcount_tbl 为右表,理解MySQL RIGHT JOIN的应用:

mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a RIGHT JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1           | 菜鸟教程         | 10             |
| 2           | 菜鸟教程         | 10             |
| 3           | RUNOOB.COM      | 20             |
| 4           | RUNOOB.COM      | 20             |
| NULL        | NULL            | 22             |
+-------------+-----------------+----------------+
5 rows in set (0.01 sec)

以上实例中使用了 RIGHT JOIN,该语句会读取右边的数据表 tcount_tbl 的所有选取的字段数据,即便在左侧表 runoob_tbl 中没有对应的runoob_author 字段值。
在这里插入图片描述

24. NULL 值处理

我们已经知道 MySQL 使用 SQL SELECT 命令及 WHERE 子句来读取数据表中的数据,但是当提供的查询条件字段为 NULL 时,该命令可能就无法正常工作。

为了处理这种情况,MySQL提供了三大运算符:

  • IS NULL: 当列的值是 NULL,此运算符返回 true。
  • IS NOT NULL: 当列的值不为 NULL, 运算符返回 true。
  • <=>: 比较操作符(不同于=运算符),当比较的的两个值为 NULL 时返回 true。
    关于 NULL 的条件比较运算是比较特殊的。你不能使用 = NULL 或 != NULL 在列中查找 NULL 值 。

在 MySQL 中,NULL 值与任何其它值的比较(即使是 NULL)永远返回 false,即 NULL = NULL 返回false 。

MySQL 中处理 NULL 使用 IS NULL 和 IS NOT NULL 运算符。

注意:

select * , columnName1+ifnull(columnName2,0) from tableName;

columnName1,columnName2 为 int 型,当 columnName2 中,有值为 null 时,columnName1+columnName2=null, ifnull(columnName2,0) 把 columnName2 中 null 值转为 0。

在命令提示符中使用 NULL 值
以下实例中假设数据库 RUNOOB 中的表 runoob_test_tbl 含有两列 runoob_author 和 runoob_count, runoob_count 中设置插入NULL值。

尝试以下实例:

创建数据表 runoob_test_tbl

root@host# mysql -u root -p password;
Enter password:*******
mysql> use RUNOOB;
Database changed
mysql> create table runoob_test_tbl
    -> (
    -> runoob_author varchar(40) NOT NULL,
    -> runoob_count  INT
    -> );
Query OK, 0 rows affected (0.05 sec)
mysql> INSERT INTO runoob_test_tbl (runoob_author, runoob_count) values ('RUNOOB', 20);
mysql> INSERT INTO runoob_test_tbl (runoob_author, runoob_count) values ('菜鸟教程', NULL);
mysql> INSERT INTO runoob_test_tbl (runoob_author, runoob_count) values ('Google', NULL);
mysql> INSERT INTO runoob_test_tbl (runoob_author, runoob_count) values ('FK', 20);
 
mysql> SELECT * from runoob_test_tbl;
+---------------+--------------+
| runoob_author | runoob_count |
+---------------+--------------+
| RUNOOB        | 20           |
| 菜鸟教程 	    | NULL         |
| Google        | NULL         |
| FK            | 20           |
+---------------+--------------+
4 rows in set (0.01 sec)

以下实例中你可以看到 = 和 != 运算符是不起作用的:

mysql> SELECT * FROM runoob_test_tbl WHERE runoob_count = NULL;
Empty set (0.00 sec)
mysql> SELECT * FROM runoob_test_tbl WHERE runoob_count != NULL;
Empty set (0.01 sec)

查找数据表中 runoob_test_tbl 列是否为 NULL,必须使用 IS NULLIS NOT NULL,如下实例:

mysql> SELECT * FROM runoob_test_tbl WHERE runoob_count IS NULL;
+---------------+--------------+
| runoob_author | runoob_count |
+---------------+--------------+
| 菜鸟教程 	    | NULL         |
| Google        | NULL         |
+---------------+--------------+
2 rows in set (0.01 sec)
 
mysql> SELECT * from runoob_test_tbl WHERE runoob_count IS NOT NULL;
+---------------+--------------+
| runoob_author | runoob_count |
+---------------+--------------+
| RUNOOB        | 20           |
| FK            | 20           |
+---------------+--------------+
2 rows in set (0.01 sec)

在前面的章节我们已经了解到MySQL可以通过 LIKE …% 来进行模糊匹配。

MySQL 同样也支持其他正则表达式的匹配, MySQL中使用 REGEXP 操作符来进行正则表达式匹配。

25. 正则表达式

下表中的正则模式可应用于 REGEXP 操作符中。

模式描述
^匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 ‘\n’ 或 ‘\r’ 之后的位置。
$匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 ‘\n’ 或 ‘\r’ 之前的位置。
.匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用象 ‘[.\n]’ 的模式。
[…]字符集合。匹配所包含的任意一个字符。例如, ‘[abc]’ 可以匹配 “plain” 中的 ‘a’。
[^…]负值字符集合。匹配未包含的任意字符。例如, ‘[^abc]’ 可以匹配 “plain” 中的’p’。
p1|p2|p3匹配 p1 或 p2 或 p3。例如,‘z|food’ 能匹配 “z” 或 “food”。’(z|f)ood’ 则匹配 “zood” 或 “food”。
*匹配前面的子表达式零次或多次。例如,zo* 能匹配 “z” 以及 “zoo”。* 等价于{0,}。
+匹配前面的子表达式一次或多次。例如,‘zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。
{n}n 是一个非负整数。匹配确定的 n 次。例如,‘o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。
{n,m}m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。

了解以上的正则需求后,我们就可以根据自己的需求来编写带有正则表达式的SQL语句。以下我们将列出几个小实例(表名:person_tbl )来加深我们的理解:

查找name字段中以’st’为开头的所有数据:

mysql> SELECT name FROM person_tbl WHERE name REGEXP '^st';

查找name字段中以’ok’为结尾的所有数据:

mysql> SELECT name FROM person_tbl WHERE name REGEXP 'ok$';

查找name字段中包含’mar’字符串的所有数据:

mysql> SELECT name FROM person_tbl WHERE name REGEXP 'mar';

查找name字段中以元音字符开头或以’ok’字符串结尾的所有数据:

mysql> SELECT name FROM person_tbl WHERE name REGEXP '^[aeiou]|ok$';

26. 事务

MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!

  • 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
  • 事务处理可以用来维护数据库的完整性,保证成批的 SQL语句要么全部执行,要么全部不执行。
  • 事务用来管理 insert,update,delete 语句

一般来说,事务是必须满足4个条件(ACID):原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)

  • 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

  • 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。

  • 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。

  • 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。

事务控制语句:

BEGIN 或 START TRANSACTION 显式地开启一个事务;

  • COMMIT 也可以使用 COMMIT WORK,不过二者是等价的。

  • COMMIT 会提交事务,并使已对数据库进行的所有修改成为永久性的;

  • ROLLBACK 也可以使用 ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;

  • SAVEPOINT identifier,SAVEPOINT 允许在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT;

  • RELEASE SAVEPOINT identifier 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;

  • ROLLBACK TO identifier 把事务回滚到标记点;

  • SET TRANSACTION 用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。

MYSQL 事务处理主要有两种方法:

1、用 BEGIN, ROLLBACK, COMMIT来实现

  • BEGIN 开始一个事务
  • ROLLBACK 事务回滚
  • COMMIT 事务确认

2、直接用 SET 来改变 MySQL 的自动提交模式:

SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT=1 开启自动提交

事务测试

mysql> use RUNOOB;
Database changed
mysql> CREATE TABLE runoob_transaction_test( id int(5)) engine=innodb;  # 创建数据表
Query OK, 0 rows affected (0.04 sec)
 
mysql> select * from runoob_transaction_test;
Empty set (0.01 sec)
 
mysql> begin;  # 开始事务
Query OK, 0 rows affected (0.00 sec)
 
mysql> insert into runoob_transaction_test value(5);
Query OK, 1 rows affected (0.01 sec)
 
mysql> insert into runoob_transaction_test value(6);
Query OK, 1 rows affected (0.00 sec)
 
mysql> commit; # 提交事务
Query OK, 0 rows affected (0.01 sec)
 
mysql>  select * from runoob_transaction_test;
+------+
| id   |
+------+
| 5    |
| 6    |
+------+
2 rows in set (0.01 sec)
 
mysql> begin;    # 开始事务
Query OK, 0 rows affected (0.00 sec)
 
mysql>  insert into runoob_transaction_test values(7);
Query OK, 1 rows affected (0.00 sec)
 
mysql> rollback;   # 回滚
Query OK, 0 rows affected (0.00 sec)
 
mysql>   select * from runoob_transaction_test;   # 因为回滚所以数据没有插入
+------+
| id   |
+------+
| 5    |
| 6    |
+------+
2 rows in set (0.01 sec)
 
mysql>

强化巩固

使用保留点 SAVEPOINT

savepoint 是在数据库事务处理中实现“子事务”(subtransaction),也称为嵌套事务的方法。事务可以回滚到 savepoint 而不影响 savepoint 创建前的变化, 不需要放弃整个事务。

ROLLBACK 回滚的用法可以设置保留点 SAVEPOINT,执行多条操作时,回滚到想要的那条语句之前。

使用 SAVEPOINT

SAVEPOINT savepoint_name;    // 声明一个 savepoint
ROLLBACK TO savepoint_name;  // 回滚到savepoint

删除 SAVEPOINT

保留点再事务处理完成(执行一条 ROLLBACK 或 COMMIT)后自动释放。

MySQL5 以来,可以用:

RELEASE SAVEPOINT savepoint_name;  // 删除指定保留点

27. ALTER命令

当我们需要修改数据表名或者修改数据表字段时,就需要使用到MySQL ALTER命令。

开始本章教程前让我们先创建一张表,表名为:testalter_tbl。

root@host# mysql -u root -p password;
Enter password:*******
mysql> use RUNOOB;
Database changed
mysql> create table testalter_tbl
    -> (
    -> i INT,
    -> c CHAR(1)
    -> );
Query OK, 0 rows affected (0.05 sec)
mysql> SHOW COLUMNS FROM testalter_tbl;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| i     | int(11) | YES  |     | NULL    |       |
| c     | char(1) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)

删除,添加或修改表字段

如下命令使用了 ALTER 命令及 DROP 子句来删除以上创建表的 i 字段:

mysql> ALTER TABLE testalter_tbl DROP i;

如果数据表中只剩余一个字段则无法使用DROP来删除字段。

MySQL 中使用 ADD 子句来向数据表中添加列,如下实例在表 testalter_tbl 中添加 i 字段,并定义数据类型:

mysql> ALTER TABLE testalter_tbl ADD i INT;

执行以上命令后,i 字段会自动添加到数据表字段的末尾。

mysql> SHOW COLUMNS FROM testalter_tbl;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| c     | char(1) | YES  |     | NULL    |       |
| i     | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)

如果你需要指定新增字段的位置,可以使用MySQL提供的关键字 FIRST (设定位第一列), AFTER 字段名(设定位于某个字段之后)。

尝试以下 ALTER TABLE 语句, 在执行成功后,使用 SHOW COLUMNS 查看表结构的变化:

ALTER TABLE testalter_tbl DROP i;
ALTER TABLE testalter_tbl ADD i INT FIRST;
ALTER TABLE testalter_tbl DROP i;
ALTER TABLE testalter_tbl ADD i INT AFTER c;

FIRST 和 AFTER 关键字可用于 ADD 与 MODIFY 子句,所以如果你想重置数据表字段的位置就需要先使用 DROP 删除字段然后使用 ADD 来添加字段并设置位置。

修改字段类型及名称

如果需要修改字段类型及名称, 你可以在ALTER命令中使用 MODIFY 或 CHANGE 子句 。

例如,把字段 c 的类型从 CHAR(1) 改为 CHAR(10),可以执行以下命令:

mysql> ALTER TABLE testalter_tbl MODIFY c CHAR(10);

使用 CHANGE 子句, 语法有很大的不同。 在 CHANGE 关键字之后,紧跟着的是你要修改的字段名,然后指定新字段名及类型。尝试如下实例:

mysql> ALTER TABLE testalter_tbl CHANGE i j BIGINT;
mysql> ALTER TABLE testalter_tbl CHANGE j j INT;

ALTER TABLE 对 Null 值和默认值的影响
当你修改字段时,你可以指定是否包含值或者是否设置默认值。

以下实例,指定字段 j 为 NOT NULL 且默认值为100 。

mysql> ALTER TABLE testalter_tbl 
    -> MODIFY j BIGINT NOT NULL DEFAULT 100;

如果你不设置默认值,MySQL会自动设置该字段默认为 NULL。

修改字段默认值

你可以使用 ALTER 来修改字段的默认值,尝试以下实例:

mysql> ALTER TABLE testalter_tbl ALTER i SET DEFAULT 1000;
mysql> SHOW COLUMNS FROM testalter_tbl;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| c     | char(1) | YES  |     | NULL    |       |
| i     | int(11) | YES  |     | 1000    |       |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)

你也可以使用 ALTER 命令及 DROP子句来删除字段的默认值,如下实例:

mysql> ALTER TABLE testalter_tbl ALTER i DROP DEFAULT;
mysql> SHOW COLUMNS FROM testalter_tbl;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| c     | char(1) | YES  |     | NULL    |       |
| i     | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)
Changing a Table Type:

修改数据表类型,可以使用 ALTER 命令及 TYPE 子句来完成。尝试以下实例,我们将表 testalter_tbl 的类型修改为 MYISAM :

注意:查看数据表类型可以使用 SHOW TABLE STATUS 语句。

mysql> ALTER TABLE testalter_tbl ENGINE = MYISAM;
mysql>  SHOW TABLE STATUS LIKE 'testalter_tbl'\G
*************************** 1. row ****************
           Name: testalter_tbl
           Type: MyISAM
     Row_format: Fixed
           Rows: 0
 Avg_row_length: 0
    Data_length: 0
Max_data_length: 25769803775
   Index_length: 1024
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2007-06-03 08:04:36
    Update_time: 2007-06-03 08:04:36
     Check_time: NULL
 Create_options:
        Comment:
1 row in set (0.00 sec)

修改表名

如果需要修改数据表的名称,可以在 ALTER TABLE 语句中使用 RENAME 子句来实现。

尝试以下实例将数据表 testalter_tbl 重命名为 alter_tbl:

mysql> ALTER TABLE testalter_tbl RENAME TO alter_tbl;

ALTER 命令还可以用来创建及删除MySQL数据表的索引,该功能我们会在接下来的章节中介绍。

强化巩固:

如下命令使用了 ALTER 命令及 DROP 子句来删除以上创建表的 i 字段:

alter其他用途:

修改存储引擎:修改为myisam

alter table tableName engine=myisam;

删除外键约束:keyName是外键别名

alter table tableName drop foreign key keyName;

修改字段的相对位置:这里name1为想要修改的字段,type1为该字段原来类型,first和after二选一,这应该显而易见,first放在第一位,after放在name2字段后面

alter table tableName modify name1 type1 first|after name2;

28. 复制表

如果我们需要完全的复制MySQL的数据表,包括表的结构,索引,默认值等。 如果仅仅使用CREATE TABLE … SELECT 命令,是无法实现的。

本章节将为大家介绍如何完整的复制MySQL数据表,步骤如下:

  • 使用 SHOW CREATE TABLE 命令获取创建数据表(CREATE TABLE) 语句,该语句包含了原数据表的结构,索引等。
  • 复制以下命令显示的SQL语句,修改数据表名,并执行SQL语句,通过以上命令 将完全的复制数据表结构。
  • 如果你想复制表的内容,你就可以使用 INSERT INTO … SELECT 语句来实现。

尝试以下实例来复制表 runoob_tbl 。

步骤一:

获取数据表的完整结构。

mysql> SHOW CREATE TABLE runoob_tbl \G;
*************************** 1. row ***************************
       Table: runoob_tbl
Create Table: CREATE TABLE `runoob_tbl` (
  `runoob_id` int(11) NOT NULL auto_increment,
  `runoob_title` varchar(100) NOT NULL default '',
  `runoob_author` varchar(40) NOT NULL default '',
  `submission_date` date default NULL,
  PRIMARY KEY  (`runoob_id`),
  UNIQUE KEY `AUTHOR_INDEX` (`runoob_author`)
) ENGINE=InnoDB 
1 row in set (0.00 sec)

ERROR:
No query specified

步骤二:

修改SQL语句的数据表名,并执行SQL语句。

mysql> CREATE TABLE `clone_tbl` (
  -> `runoob_id` int(11) NOT NULL auto_increment,
  -> `runoob_title` varchar(100) NOT NULL default '',
  -> `runoob_author` varchar(40) NOT NULL default '',
  -> `submission_date` date default NULL,
  -> PRIMARY KEY  (`runoob_id`),
  -> UNIQUE KEY `AUTHOR_INDEX` (`runoob_author`)
-> ) ENGINE=InnoDB;
Query OK, 0 rows affected (1.80 sec)

步骤三:

执行完第二步骤后,你将在数据库中创建新的克隆表 clone_tbl。 如果你想拷贝数据表的数据你可以使用 INSERT INTO… SELECT 语句来实现。

mysql> INSERT INTO clone_tbl (runoob_id,
    ->                        runoob_title,
    ->                        runoob_author,
    ->                        submission_date)
    -> SELECT runoob_id,runoob_title,
    ->        runoob_author,submission_date
    -> FROM runoob_tbl;
Query OK, 3 rows affected (0.07 sec)
Records: 3  Duplicates: 0  Warnings: 0

执行以上步骤后,你将完整的复制表,包括表结构及表数据。

强化巩固:

第一部分:

另一种完整复制表的方法:

CREATE TABLE targetTable LIKE sourceTable;
INSERT INTO targetTable SELECT * FROM sourceTable;

其他:

可以拷贝一个表中其中的一些字段:

CREATE TABLE newadmin AS
(
    SELECT username, password FROM admin
)

可以将新建的表的字段改名:

CREATE TABLE newadmin AS
(  
    SELECT id, username AS uname, password AS pass FROM admin
)

可以拷贝一部分数据:

CREATE TABLE newadmin AS
(
    SELECT * FROM admin WHERE LEFT(username,1) = 's'
)

可以在创建表的同时定义表中的字段信息:

CREATE TABLE newadmin
(
    id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY
)
AS
(
    SELECT * FROM admin
)  

第二部分:

来给大家区分下mysql复制表的两种方式。

第一、只复制表结构到新表

create table 新表 select * from 旧表 where 1=2

或者

create table 新表 like 旧表

第二、复制表结构及数据到新表

create table 新表 select * from 旧表

29. 序列使用

MySQL 序列是一组整数:1, 2, 3, …,由于一张数据表只能有一个字段自增主键, 如果你想实现其他字段也实现自动增加,就可以使用MySQL序列来实现。

本章我们将介绍如何使用MySQL的序列。

使用 AUTO_INCREMENT

MySQL 中最简单使用序列的方法就是使用 MySQL AUTO_INCREMENT 来定义列。

以下实例中创建了数据表 insect, insect 表中 id 无需指定值可实现自动增长。

mysql> CREATE TABLE insect
    -> (
    -> id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    -> PRIMARY KEY (id),
    -> name VARCHAR(30) NOT NULL, # type of insect
    -> date DATE NOT NULL, # date collected
    -> origin VARCHAR(30) NOT NULL # where collected
);
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO insect (id,name,date,origin) VALUES
    -> (NULL,'housefly','2001-09-10','kitchen'),
    -> (NULL,'millipede','2001-09-10','driveway'),
    -> (NULL,'grasshopper','2001-09-10','front yard');
Query OK, 3 rows affected (0.02 sec)
Records: 3  Duplicates: 0  Warnings: 0
mysql> SELECT * FROM insect ORDER BY id;
+----+-------------+------------+------------+
| id | name        | date       | origin     |
+----+-------------+------------+------------+
|  1 | housefly    | 2001-09-10 | kitchen    |
|  2 | millipede   | 2001-09-10 | driveway   |
|  3 | grasshopper | 2001-09-10 | front yard |
+----+-------------+------------+------------+
3 rows in set (0.00 sec)

获取AUTO_INCREMENT值

在MySQL的客户端中你可以使用 SQL中的LAST_INSERT_ID( ) 函数来获取最后的插入表中的自增列的值。

JAVA实例

public void testNextValue() {
	try {
		String MySQL = "jdbc:mysql://localhost/hibernate";
		Class.forName("com.mysql.jdbc.Driver");
		java.sql.Connection conn = DriverManager.getConnection(MySQL, "root", "root");
		String sql = "insert into testnotnull values(null, ?, ?)";
		java.sql.PreparedStatement pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
		conn.setAutoCommit(false);
		int i = 1;
		pstmt.setInt(i++, 234);
		pstmt.setString(i++, "sdfsdf");
		pstmt.executeUpdate();
		ResultSet rs = pstmt.getGeneratedKeys();
		System.out.println("The value is ");
		if(rs.next()) {
			System.out.println(rs.getInt(1));
		}
		conn.commit();
		conn.setAutoCommit(true);
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		//do close....
	}
}

如果只是单纯的想要获取Auto_increment的最大值,可用

select max(id) from testnotnull;

或 show table status from hibernate like ‘testnotnull’;获取其中的Auto_increment的值。

重置序列

如果你删除了数据表中的多条记录,并希望对剩下数据的AUTO_INCREMENT列进行重新排列,那么你可以通过删除自增的列,然后重新添加来实现。 不过该操作要非常小心,如果在删除的同时又有新记录添加,有可能会出现数据混乱。操作如下所示:

mysql> ALTER TABLE insect DROP id;
mysql> ALTER TABLE insect
    -> ADD id INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
    -> ADD PRIMARY KEY (id);

设置序列的开始值

一般情况下序列的开始值为1,但如果你需要指定一个开始值100,那我们可以通过以下语句来实现:

mysql> CREATE TABLE insect
    -> (
    -> id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    -> PRIMARY KEY (id),
    -> name VARCHAR(30) NOT NULL, 
    -> date DATE NOT NULL,
    -> origin VARCHAR(30) NOT NULL
)engine=innodb auto_increment=100 charset=utf8;

或者你也可以在表创建成功后,通过以下语句来实现:

mysql> ALTER TABLE t AUTO_INCREMENT = 100;

强化巩固:

使用函数创建自增序列管理表(批量使用自增表,设置初始值,自增幅度)

第一步:创建Sequence管理表 sequence

DROP TABLE IF EXISTS sequence; 
CREATE TABLE sequence ( 
name VARCHAR(50) NOT NULL, 
current_value INT NOT NULL, 
increment INT NOT NULL DEFAULT 1, 
PRIMARY KEY (name) 
) ENGINE=InnoDB;

第二步:创建取当前值的函数 currval

DROP FUNCTION IF EXISTS currval; 
DELIMITER $ 
CREATE FUNCTION currval (seq_name VARCHAR(50)) 
RETURNS INTEGER
LANGUAGE SQL 
DETERMINISTIC 
CONTAINS SQL 
SQL SECURITY DEFINER 
COMMENT ''
BEGIN
DECLARE value INTEGER; 
SET value = 0; 
SELECT current_value INTO value 
FROM sequence
WHERE name = seq_name; 
RETURN value; 
END
$ 
DELIMITER ;

第三步:创建取下一个值的函数 nextval

DROP FUNCTION IF EXISTS nextval; 
DELIMITER $ 
CREATE FUNCTION nextval (seq_name VARCHAR(50)) 
RETURNS INTEGER
LANGUAGE SQL 
DETERMINISTIC 
CONTAINS SQL 
SQL SECURITY DEFINER 
COMMENT ''
BEGIN
UPDATE sequence
SET current_value = current_value + increment 
WHERE name = seq_name; 
RETURN currval(seq_name); 
END
$ 
DELIMITER;

第四步:创建更新当前值的函数 setval

DROP FUNCTION IF EXISTS setval; 
DELIMITER $ 
CREATE FUNCTION setval (seq_name VARCHAR(50), value INTEGER) 
RETURNS INTEGER
LANGUAGE SQL 
DETERMINISTIC 
CONTAINS SQL 
SQL SECURITY DEFINER 
COMMENT ''
BEGIN
UPDATE sequence
SET current_value = value 
WHERE name = seq_name; 
RETURN currval(seq_name); 
END
$ 
DELIMITER ;

测试函数功能

当上述四步完成后,可以用以下数据设置需要创建的sequence名称以及设置初始值和获取当前值和下一个值。

INSERT INTO sequence VALUES ('TestSeq', 0, 1);
----添加一个sequence名称和初始值,以及自增幅度  添加一个名为TestSeq 的自增序列

SELECT SETVAL('TestSeq', 10);
---设置指定sequence的初始值    这里设置TestSeq 的初始值为10

SELECT CURRVAL('TestSeq');  
--查询指定sequence的当前值   这里是获取TestSeq当前值

SELECT NEXTVAL('TestSeq');  
--查询指定sequence的下一个值  这里是获取TestSeq下一个值

30. 处理重复数据

有些 MySQL 数据表中可能存在重复的记录,有些情况我们允许重复数据的存在,但有时候我们也需要删除这些重复的数据。

本章节我们将为大家介绍如何防止数据表出现重复数据及如何删除数据表中的重复数据。

防止表中出现重复数据

你可以在 MySQL 数据表中设置指定的字段为 PRIMARY KEY(主键) 或者 UNIQUE(唯一) 索引来保证数据的唯一性。

让我们尝试一个实例:下表中无索引及主键,所以该表允许出现多条重复记录。

CREATE TABLE person_tbl
(
    first_name CHAR(20),
    last_name CHAR(20),
    sex CHAR(10)
);

如果你想设置表中字段 first_name,last_name 数据不能重复,你可以设置双主键模式来设置数据的唯一性, 如果你设置了双主键,那么那个键的默认值不能为 NULL,可设置为 NOT NULL。如下所示:

CREATE TABLE person_tbl
(
   first_name CHAR(20) NOT NULL,
   last_name CHAR(20) NOT NULL,
   sex CHAR(10),
   PRIMARY KEY (last_name, first_name)
);

如果我们设置了唯一索引,那么在插入重复数据时,SQL 语句将无法执行成功,并抛出错。

INSERT IGNORE INTO 与 INSERT INTO 的区别就是 INSERT IGNORE 会忽略数据库中已经存在的数据,如果数据库没有数据,就插入新的数据,如果有数据的话就跳过这条数据。这样就可以保留数据库中已经存在数据,达到在间隙中插入数据的目的。

以下实例使用了 INSERT IGNORE INTO,执行后不会出错,也不会向数据表中插入重复数据:

mysql> INSERT IGNORE INTO person_tbl (last_name, first_name)
    -> VALUES( 'Jay', 'Thomas');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT IGNORE INTO person_tbl (last_name, first_name)
    -> VALUES( 'Jay', 'Thomas');
Query OK, 0 rows affected (0.00 sec)

INSERT IGNORE INTO 当插入数据时,在设置了记录的唯一性后,如果插入重复数据,将不返回错误,只以警告形式返回。 而 REPLACE INTO 如果存在 primary 或 unique 相同的记录,则先删除掉。再插入新记录。

另一种设置数据的唯一性方法是添加一个 UNIQUE 索引,如下所示:

CREATE TABLE person_tbl
(
   first_name CHAR(20) NOT NULL,
   last_name CHAR(20) NOT NULL,
   sex CHAR(10),
   UNIQUE (last_name, first_name)
);

统计重复数据
以下我们将统计表中 first_name 和 last_name的重复记录数:

mysql> SELECT COUNT(*) as repetitions, last_name, first_name
    -> FROM person_tbl
    -> GROUP BY last_name, first_name
    -> HAVING repetitions > 1;

以上查询语句将返回 person_tbl 表中重复的记录数。 一般情况下,查询重复的值,请执行以下操作:

  • 确定哪一列包含的值可能会重复。
  • 在列选择列表使用COUNT(*)列出的那些列。
  • 在GROUP BY子句中列出的列。
  • HAVING子句设置重复数大于1。

过滤重复数据

如果你需要读取不重复的数据可以在 SELECT 语句中使用 DISTINCT 关键字来过滤重复数据。

mysql> SELECT DISTINCT last_name, first_name
    -> FROM person_tbl;

你也可以使用 GROUP BY 来读取数据表中不重复的数据:

mysql> SELECT last_name, first_name
    -> FROM person_tbl
    -> GROUP BY (last_name, first_name);

删除重复数据

如果你想删除数据表中的重复数据,你可以使用以下的SQL语句:

mysql> CREATE TABLE tmp SELECT last_name, first_name, sex FROM person_tbl  GROUP BY (last_name, first_name, sex);
mysql> DROP TABLE person_tbl;
mysql> ALTER TABLE tmp RENAME TO person_tbl;

当然你也可以在数据表中添加 INDEX(索引) 和 PRIMAY KEY(主键)这种简单的方法来删除表中的重复记录。方法如下:

mysql> ALTER IGNORE TABLE person_tbl
    -> ADD PRIMARY KEY (last_name, first_name);

强化巩固:

select 列名1,count(1as count 
from 表名
group by  列名1
having count>1  and 其他条件

select 列名1,列名2,count(1as count 
from 表名
group by  列名1,列名2 
having count>1  and 其他条件

原理:先按照要查询出现重复数据的列,进行分组查询。count > 1 代表出现 2 次或 2 次以上。

示例:

/*查询重复数据*/
select serialnum,cdate,count(*) as count 
from m_8_customer_temp_20180820bak 
group by serialnum,cdate having  count>1 and cdate>='2018-08-20 00:00:00';

31. 导出数据

导出表作为原始数据

导出 SQL 格式的数据
导出 SQL 格式的数据到指定文件,如下所示:

$ mysqldump -u root -p RUNOOB runoob_tbl > dump.txt
password ******

将数据表及数据库拷贝至其他主机
如果你需要将数据拷贝至其他的 MySQL 服务器上, 你可以在 mysqldump 命令中指定数据库名及数据表。

在源主机上执行以下命令,将数据备份至 dump.txt 文件中:

$ mysqldump -u root -p database_name table_name > dump.txt
password *****

如果完整备份数据库,则无需使用特定的表名称。

如果你需要将备份的数据库导入到MySQL服务器中,可以使用以下命令,使用以下命令你需要确认数据库已经创建:

$ mysqldump -u root -p database_name table_name > dump.txt
password *****

你也可以使用以下命令将导出的数据直接导入到远程的服务器上,但请确保两台服务器是相通的,是可以相互访问的:

$ mysqldump -u root -p database_name \
       | mysql -h other-host.com database_name

以上命令中使用了管道来将导出的数据导入到指定的远程主机上。

32. 导入数据

1. mysql 命令导入
使用 mysql 命令导入语法格式为:

mysql -u用户名 -p密码 < 要导入的数据库数据(runoob.sql)

实例:

# mysql -uroot -p123456 < runoob.sql

以上命令将将备份的整个数据库 runoob.sql 导入。

2. source 命令导入

source 命令导入数据库需要先登录到数库终端:

mysql> create database abc;      # 创建数据库
mysql> use abc;                  # 使用已创建的数据库 
mysql> set names utf8;           # 设置编码
mysql> source /home/abc/abc.sql  # 导入备份数据库

3. 使用 mysqlimport 导入数据

mysqlimport客户端提供了LOAD DATA INFILEQL语句的一个命令行接口。mysqlimport的大多数选项直接对应LOAD DATA INFILE子句。

从文件 dump.txt 中将数据导入到 mytbl 数据表中, 可以使用以下命令:

$ mysqlimport -u root -p --local database_name dump.txt
password *****

mysqlimport命令可以指定选项来设置指定格式,命令语句格式如下:

$ mysqlimport -u root -p --local --fields-terminated-by=":" \
   --lines-terminated-by="\r\n"  database_name dump.txt
password *****

mysqlimport 语句中使用 --columns 选项来设置列的顺序:

$ mysqlimport -u root -p --local --columns=b,c,a \
    database_name dump.txt
password *****

33. 卸载

管理员运行cmd输入
net stop mysql //关闭mysql数据库
sc delete mysql //这里的mysql是你要删除的服务名,通过该命令就可以删除相关的服务。

在文件夹右键删除即可,没有被占用提示。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值