值得收藏的 MySQL 超全知识点总结

文章目录


1、MySQL 的相关概念介绍

注意,MySQL 的操作都是无法撤销的,所以每一步都要小心,特别是更新,修改数据(除非用 事务,或者 要多备份)

注意,当我们用 SELECT 去查询的时候,是以对象数据的键,去查询的,因为有 键,那么查询比较快(B+ 树),所以需要说,用键去索引。也因此,键是要唯一的

MySQL 为关系型数据库(Relational Database Management System), 这种所谓的"关系型"可以理解为"表格"的概念,一个关系型数据库由一个或数个表格组成

其实也就是,一个 MySQL 数据库(文件)类似于 excel 文件,而一个库里面,可以有多个表。而每个表里面,有字段(对应的属性),然后表中的每一行,存的就是数据信息。

  • 数据存放到表中,表再放到库中
  • 一个库可以由多张表,每张表具有唯一的表名用来标识自己
  • 表中有一个或多个列,列又称为“字段”,也就是第一行,表示了每一列存的数据的意义(比如 学号,姓名等等)
  • 表中每一行数据,相当于 C++ 中“对象”,也就是具体到 每一个事物的具体数据。

下图是一个,表 的例子:

在这里插入图片描述

  • 表头(header),也就是 字段;表示这一列的意义(同时也会限制了对应的数据类型,比如 姓名那一列的就是字符串)
  • 列(row):具有相同数据类型的数据的集合;
  • 行(col):每一行用来描述某个人/物的具体信息(相当于是具体到 对象上,比如图中的每一行就是每一个学生的信息)
  • 键(key):表中用来识别某个特定的人\物的方法, 键的值在当前列中具有唯一性。(其实相当于是对具体对象人的标识符,因此要唯一性,比如图中,id 可以认为是学号,每个学号是独立的,所以可以作为键。但是名字就不能,万一出现重名的)。选择键,一定要是唯一的,而且那一列不能非空,这样子才有唯一标识性
  • 值(value): 行的具体信息, 每个值必须与该列(字段指定的)的数据类型相同;

只要设定的键不同,其他数据即使一样,也是认为是不同的数据


2、MySQL 的基本组成

和Linux 的shell 脚本一样。我们一般在 shell 上使用指令,都是一条一条的。在 MySQL 的时候,指令也是一条一条的。

但是我们可以通过写脚本(指令的结合体,类似写 cpp 一样),写成一个可以批处理的文件,这样子执行脚本,就会执行里面的指令。
同样的,也可以在控制台上,一条一条的执行指令,不用到脚本。

2.0、注释

单行注释:# 注释文字
多行注释:/* 注释文字 */

2.1、标识符

类似 CPP,标识符就是给变量,表,库起名,一般都是用:标识符由字母、数字或下划线(_)组成,且第一个字符必须是字母或下划线。

2.2、区分大小写(不同操作系统不一样)

对于 Windows 而言,不区分大小写,比如 SELECT 就相当于是 select

对于 Linux,就是会区分大小写

  • 数据库名与表名是严格区分大小写的;
  • 表的别名是严格区分大小写的;
  • 列名与列的别名在所有的情况下均是忽略大小写的;
  • 变量名也是严格区分大小写的;

一般来说,习惯性给 关键字,函数之类的大写,然后其他的一般小写,比如别名,库名,表名之类的。

2.3、关键字

MySQL 的关键字众多,这里不一一列出,在学习中学习。这些关键字有自己特定的含义,尽量避免作为标识符。

2.4、语句(指令)

MySQL 语句是组成 MySQL 脚本的基本单位,每条语句能完成特定的操作,他是由 SQL 标准语句 + MySQL 扩展语句组成

每一行的语句结束,都加上 ;,表示这一行指令输入结束。不加 ;,会提示让你继续输入。

每条命令根据需要,可以进行缩进,或者换行(建议关键字放一行,要要查询的放一行)。

2.5、函数

对于MySQL,也有一些函数可以使用的(比如像 SUM,AVG,求某一列(字段)的最大值,平均值)

MySQL 函数用来实现数据库操作的一些高级功能, 这些函数大致分为以下几类:字符串函数、数学函数、日期时间函数、搜索函数、加密函数、信息函数。


3、MySQL 中的数据类型

这个在另一个文章里面介绍了:MySQL 数据库的数据类型

4、操作 数据库

4.1、启动/关闭 MySQL 服务

windows的,命令行下运行:(cmd 或者 powershell)

启动服务net start mysql
关闭服务net stop mysql
卸载sc delete mysql

Linux

查看 MySQL 服务

方法一:ps -ef | grep mysql
方法二:netstat -nlp

启动MySQL 服务

命令行方式:

cd /usr/bin
./mysqld_safe &

服务方式:

service mysql start

// 如果服务已经启动中,可以用下面指令使其 重启服务
service mysql restart

关闭 MySQL 服务

命令行方式:mysqladmin -u root shutdown

服务方式:service mysql stop

4.2、登陆到 MySQL

当 MySQL 服务已经运行的时候,我们就可以通过 cmd、shell(甚至CPP代码)来登陆到 数据库中。

同样的,登陆的时候,需要 用户名 和 密码,其登陆指令为:

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

# -h 后面,
  • -h:用于指定客户端所要登录的MySQL主机名(也就是,mysql服务是运行在哪个 IP 地址的主机上的),如果是 当前机器上的MySQL服务,该参数可以省略
  • -u:所要登陆的用户名(root用户,或者其他创建的MySQL服务中的用户)
  • -p:告诉服务器将会使用一个密码来登录

当回车之后,会得到要输入密码的响应,此时输入密码即可。

然后命令提示符会一直以 mysql> 加一个闪烁的光标等待命令的输入, 输入 exit 或 quit 退出登录。(表明我们此时已经登陆到了,MySQL 数据库中了)

例子

mysql -u root -p
# 这个是,因为没有 -h,所以相当于是,登陆到本机上的 MySQL 数据库中

mysql -h 192.168.2.1 -u root -p
# 这个是登陆到,192.168.2.1 这个IP 对应的机器上的,MySQL 数据库中

4.3、修改登陆密码

有几种方法:

方法一:借助 MySQL 第三方图形化界面软件 来修改

  1. 先登陆到对应数据库中
  2. 点击上方的用户
  3. 选择要更改的用户名,点击上方的编辑用户
  4. 然后输入新密码,点击保存即可。

方法二:用 SET PASSWORD 命令

首先先登陆到 MySQL 中。

格式:mysql> set password for 用户名@localhost = password('新密码');

例子:mysql> set password for root@localhost = password('123');

方法三:用 mysqladmin

不用先 登陆到 MySQL

格式:mysqladmin -u用户名 -p旧密码 password 新密码

例子:mysqladmin -uroot -p123456 password 123

方法四:用UPDATE直接编辑user表

我们发现,其实 MySQL 的登录用户的信息,也是保存在一个 数据库的表中,是保存在 mysql 库 的 user 表中。

因此,我们直接对其 user 表进程修改。

要先登陆到 MySQL

mysql> use mysql;  
mysql> update user set password=password('123') where user='root' and host='localhost';  
mysql> flush privileges; 

先进入到 对应的 mysql库,然后直接更新 user 表。最后要多那一句,这样子用户的更改密码后才有效(否则要手动重启 MySQL 服务器)

方法五:忘记 root 密码时,可以这样

以 Windows 为例(上面的四种方法,都是可以在 Linux 或者 Windows 上使用)

目前的这个,是以 Windows 为例的,具体 Linux 可不可以用,还没试过。

  1. 关闭正在运行的MySQL服务。
  2. 打开DOS窗口,转到mysql\bin目录。
  3. 输入mysqld --skip-grant-tables 回车。--skip-grant-tables 的意思是启动MySQL服务的时候跳过权限表认证。
  4. 再开一个DOS窗口(因为刚才那个DOS窗口已经不能动了),转到mysql\bin目录。
  5. 输入mysql回车,如果成功,将出现MySQL提示符 >。
  6. 连接权限数据库: use mysql;
  7. 改密码:update user set password=password("123") where user="root";(别忘了最后加分号) 。
  8. 刷新权限(必须步骤):flush privileges; 。
  9. 退出 quit
  10. 注销系统,再进入,使用用户名root和刚才设置的新密码123登录

4.4、MySQL 用户设置

在MySQL 中,记录登陆的账户密码,其实也是用一个 mysql 库中的 user 表 来记录的(同样可以用 SELECT 查询用户信息,INSERT INTO 增加新用户,DELETE 删除用户)

类似于 Linux,MySQL 也是一开始有一个超级榕湖 root,其可以创建其他用户(这样子,其他用户有权限设置,同时也可以访问该数据库)

需要添加 MySQL 用户,你只需要在 mysql 数据库中的 user 表添加新用户即可

例子(以 Linux的)

以下为添加用户的的实例,用户名为 guest,密码为 guest123,并授权用户可进行 SELECT, INSERT 和 UPDATE操作权限(创建用户,并授权):

root@host# mysql -u root -p
Enter password:*******
mysql> use mysql;
Database changed

# 增加新用户
mysql> INSERT INTO user 
          (host, user, password, 
           select_priv, insert_priv, update_priv) 
           VALUES ('localhost', 'guest', 
           PASSWORD('guest123'), 'Y', 'Y', 'Y');
Query OK, 1 row affected (0.20 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 1 row affected (0.01 sec)

mysql> SELECT host, user, password FROM user WHERE user = 'guest';
+-----------+---------+------------------+
| host      | user    | password         |
+-----------+---------+------------------+
| localhost | guest | 6f8c114b58f2ce9e |
+-----------+---------+------------------+
1 row in set (0.00 sec)
  • 在添加用户时,请注意使用MySQL提供的 PASSWORD() 函数来对密码进行加密(如果这个函数没有了,可以用 MD5()来加密)。 你可以在以上实例看到用户密码加密后为: 6f8c114b58f2ce9e.
  • 在注意需要执行 FLUSH PRIVILEGES 语句。 这个命令执行后会重新载入授权表。如果你不使用该命令,你就无法使用新创建的用户来连接 mysql 服务器,除非你 重启mysql服务器。
  • 你可以在创建用户时,为用户指定权限,在对应的权限列中,在插入语句中设置为 ‘Y’ 即可,用户权限列表如下:
    • select_priv
    • insert_priv
    • update_priv
    • delete_priv
    • create_priv
    • drop_priv
    • reload_priv
    • shutdown_priv
    • process_priv
    • file_priv
    • grant_priv
    • references_priv
    • index_priv
    • alter_priv

4.5、创建一个数据库:CREATE

使用 create database 语句可完成对数据库的创建, 创建命令的格式如下

CREATE DATABASE [IF NOT EXISTS] 数据库名 [其他选项];

# [] 表示这个参数,可以有,也可以没有
# IF NOT EXISTS 表示,如果创建的数据库已经存在,就不用再创建。如果不存在,就创建
# 关键字,我们一般用大写
# 其他选项是可选的,可以有,也可以没有。其选项一般用于设置创建的这个数据库的一些属性
# 语句最后,要加上 ; 分号,表示这一行指令输入结束

比如说,我们需要创建一个名为 testdb 的数据库, 在命令行下执行以下命令:

CREATE DATABASE IF NOT EXISTS testdb CHARACTER SET utf8;

# 这个是,创建了一个 testdb 的数据库,同时指定了 编码为 utf8 编码(也可以是 gbk 编码)
# 指定数据库编码,就是 一个可选选项
# 其中,我们关键字都是大写

创建成功时会得到 Query OK, 1 row affected(0.02 sec) 的响应

注意MySQL语句以分号(;)作为语句的结束,若在语句结尾不添加分号时,命令提示符会以 -> 提示你继续输入(有个别特例, 但加分号是一定不会错的)

4.6、选择所要操作的数据库:USE

我们要操作数据库里面的信息时,必须先选择(进入)到这个数据库文件中

上面创建数据库,类似创建一个 excel 文件,然后我们需要对 excel 文件操作,那就要打开。那么我们也就是要打开 – 选择 数据库,才能对数据库继续操作

我们在登陆到 MySQL 后,可以用命令来选择指定数据库

USE 数据库名;

比如我们进入上面创建的数据库

USE testdb;

选择成功后会提示: Database changed

如果是已经在一个数据库中,想要切换另一个数据库,也是直接用 USE 即可切换到 另一个指定的数据库

4.7、删除一个数据库:DROP

删除数据库意味着数据库中的所有数据和关联对象将被永久删除,并且无法撤消

相当于删除了,整个 excel 文件

要删除数据库,请使用DROP DATABASE语句,如下所示

DROP DATABASE [IF EXISTS] 数据库名;

# [] 表示这个选项参数,可以选择使用,也可以不使用
# IF EXISTS 表示,检查这个东西,在不在,只有在了,我们才进行删除对应的数据库。

例子,还是删除我们上面那个创建的数据库 testdb,即:

DROP DATABASE IF EXISTS testdb;

4.8、查看已经创建的所有数据库:SHOW

SHOW DATABASES语句显示 MySQL 数据库服务器中的所有数据库。

您可以使用SHOW DATABASES语句来查看您要创建的数据库,或者在创建新数据库之前查看数据库服务器上的所有数据库(也可以是是在选择进入数据库,或者删除数据库的时候,可以先查看,然后再进入/删除 对应的数据库)

例子

mysql> show databases;    # 查看所有数据库

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| mytestdb           |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

4.9、取别名:AS或空格

我们知道,有的时候,数据库名,或者后面的 表的字段,或者我们要操作 的东西很长,那么此时我们就可以给他们 起别名

  • 便于理解
  • 如果要查询的字段有重名的情况,使用别名可以区分开来

方法一:使用 AS

SELECT 100%98 AS 结果;
SELECT last_name AS, first_name ASFROM employees;

# 这样子,我们后面就可以利用 别名 来进行操作。

方法二:直接空格代替 AS(相当于直接省略了 AS)

SELECT last_name 姓, first_name 名 FROM employees;

#案例:查询salary,显示结果为output
SELECT salary AS 'output' FROM employees;

5、操作 表

5.1、创建数据库表:CREATE TABLE

使用 CREATE TABLE (create table) 语句可完成对表的创建, CREATE TABLE 的常见形式:

CREATE TABLE [IF NOT EXISTS] 表名称(
        表头列声明
) engine=table_type;

首先,指定要在 CREATE TABLE 子句之后创建的表的名称。表名在数据库中必须是唯一的。IF NOT EXISTS是语句的可选部分,允许您检查正在创建的表是否已存在于数据库中。如果要创建的表已经存在,MySQL将忽略整个语句,不会创建任何新的表。强烈建议在每个 CREATE TABLE 语句中使用 IF NOT EXISTS 来防止创建已存在的新表而产生错误。

其次,括号中指定表的列表。字段的列用逗号(,)分隔。

最后,需要为engine子句中的表指定存储引擎。一般用默认值,就是不写明即可,默认是 InnoDB

关于 表头列表声明,在表头列声明,比如有 学号,姓名,性别等字段声明,每个字段声明,一般由如下组成(然后多个字段,就是组合,每个字段之间,用 , 隔开即可)

column_name data_type[size] [UNSIGNED] [NOT NULL|NULL] [DEFAULT value] [AUTO_INCREMENT] [PRIMARY KEY]

# [] 都是可选项
# 最重要就是,一开始的,字段的名,对应设置的数据类型(有一些数据类型有限制 size 的),然后后面都是可选项
# 后面的都是设置,这个 字段的属性

字段属性可以设为

字段属性含义
NULL数据列(字段)可包含 NULL 值
NOT NULL数据列(字段)不允许包含 NULL 值
DEFAULT默认值,也就是这个字段后面对象的值,无说明就是设为默认值
PRIMARY KEY主键,只能有一个
AUTO_INCREMENT自动递增,适用于整数类型。指示每当将新行插入到表中时,列的值会自动增加。每个表都有一个且只有一个
UNSIGNED无符号

例子

CREATE TABLE IF NOT EXISTS students
(
    id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    name CHAR(8) NOT NULL,
    sex CHAR(4) NOT NULL,
    age TINYINT UNSIGNED NOT NULL,
    tel CHAR(13) NULL default '-'
);

例子解释

CREATE TABLE IF NOT EXISTS tablename(columns) 为创建数据库表的命令,列(字段)的名称以及该列(字段)的数据类型将在括号内完成;

括号内声明了5列内容,id、name、sex、age、tel为每列的名称,,后面跟的是数据类型描述,列与列的描述之间用逗号(,)隔开;

id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY行进行介绍:

  • “id” 为列的名称;
  • “INT” 指定该列的类型为 int(取值范围为 -8388608到8388607), 在后面我们又用 “UNSIGNED” 加以修饰, 表示该类型为无符号型, 此时该列的取值范围为 0到16777215;
  • “NOT NULL” 说明该列的值不能为空, 必须要填, 如果不指定该属性, 默认可为空;
  • “AUTO_INCREMENT” 需在整数列中使用, 其作用是在插入数据时若该列为 NULL, MySQL将自动产生一个比现存值更大的唯一标识符值。在每张表中仅能有一个这样的值且所在列必须为索引列。
  • “primary key” 表示该列是表的主键, 本列的值必须唯一(键是唯一性,这列的值,不能出现重复), MySQL将自动索引该列(也就是,我们查找数据,虽然是找其他字段的值,但是都是根据 键 来索引查找的)。
  • 下面的 char(8) 表示存储的字符长度为8, tinyint的取值范围为 -127到128, default 属性指定当该列值为空时的默认值。

这些数据类型和对应属性都在另一篇文章中说了:MySQL 的数据类型

有时候,很长的命令,直接输入在 命令行的时候,容易出错。所以可以通过用 脚本的方式,具体看后面 脚本的介绍

5.2、向表中插入数据:INSERT INTO

INSERT INTO 语句可以用来将一行或多行数据插到数据库表中, 使用的一般形式如下:

INSERT INTO 表名 [(列名1, 列名2, 列名3, ...)] VALUES (1,2,3, ...);

也就是,我们给 表名 的那个表增加数据

  • 其中,如果 [] 是可选参数,当没有写明是 列(字段)名时,默认是给所有 列 都增加了数据(即 VALUES 中的数据是对应所有列的)
  • 如果注明了 列名,那么此时,我们可以选择,只给这些对应的列增加数据(那么剩下的这行数据中的其他列,就是 NULL 或者 用该列的默认值)

例子

INSERT INTO students VALUES(NULL, "王刚", "男", 20, "13811371377");
# 忽略了 [] 列名,也就是 所有列都添加数据
# 还是一开始学生的那个表,依次是 id,name,sex,age,tel。
# id 虽然设置了NULL,但是 id 是AUTO_INCREMENT,所以会自动有一个值


INSERT INTO students (name, sex, age) VALUES("孙丽华", "女", 21);
# 这里限定了 列明,也就是我们只添加部分数据。
# 对于 id,tel 没有添加。而 id 是会自动赋值,tel 有默认值

5.3、更新表中的数据:UPDATE

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

UPDATE 表名
SET 
    column_name1 = expr1,
    column_name2 = expr2,
    (列名称 = 新值)
WHERE
    更新条件;

请注意,WHERE 子句非常重要,所以不应该忘记指定更新的条件。有时,您可能只想改变一行;但是,可能会忘记写上 WHERE 子句,导致意外更新表中的所有行。

例子

UPDATE students 
SET 
    tel = default 
WHERE 
    id=5;
# 将 id = 5 的那些数据的 tel 设置为 其默认值

UPDATE students 
SET 
    age = age + 1;
# 将所有数据(无 WHERE 限制)的 age 都增加 1

UPDATE students 
SET 
    name = '张伟鹏', 
    age = 19 
WHERE 
    tel = '13288097888' ;
# 将 手机号为要求的那些数据,更改名字 和 年龄

5.4、删除表中数据

5.4.1、删除表中数据,不删除表:delete

DELETE 语句用于删除表中的数据, 基本用法为

DELETE FROM 表名称 
WHERE 删除条件;

如果没有限制条件 WHERE,那就是删除整个表中的所有数据(只是删除数据,而原来的表头,字段,表还是在的)

如果有限制条件,那就是删除满足限制条件的那些数据

其中,还可以和 ORDER BY(排序)和 LIMIT(限制删除前几条数据)结合在一起。

例子

DELETE FROM customers
ORDER BY customerName
LIMIT 10;
# 客户名称按字母排序客户,并删除前 10 个客户

DELETE FROM customers
WHERE country = 'France'
ORDER BY creditLimit
LIMIT 5;
# 选择法国(France)的客户,按升序按信用额度(creditLimit)进行排序,并删除前5个客户

还可以是多表的删除,和 后边的 连接一起结合使用

5.4.2、删除表中数据,不删除表:truncate

TRUNCATE TABLE 表名;

删除 表名 对应的这个 表中的数据。(只是删除数据,而原来的表头,字段,表还是在

5.4.3、删除表中数据,删除整个表:drop

DROP TABLE 表名;

注意,这个是,删除整个表,也就是说,除了删除了数据内容,还会将这个 表 直接销毁,也就没这个表了。

5.4.4、delete、truncate、drop 的区别(面试题

相同点

truncate 和不带 where 子句的 delete,以及 drop 都会删除表内的数据

不同点

  1. truncate 和 delete 只删除数据不删除表的结构(字段等都还在);drop 语句将删除表的结构(也就是整个 表 都没了,字段也没了)
  2. delete 语句是数据库操作语言(dml),这操作会放到rollback segement 中,事务提交之后才生效;如果有相应的 trigger,执行的时候将被触发。truncate、drop 是数据库定义语言(ddl)操作立即生效,原数据不放到 rollback segment 中,不能回滚,操作不触发 trigger。
  3. delete 语句不影响表所占用的 extent,高水线(high watermark)保持原位置不动
    显然 drop 语句将表所占用的空间全部释放。
    truncate 语句缺省情况下见空间释放到 minextents个 extent,除非使用reuse storage;truncate 会将高水线复位(回到最开始)。
  4. 速度,一般来说: drop> truncate > delete
  5. 安全性:小心使用 drop 和 truncate,尤其没有备份的时候.否则哭都来不及

5.4.5、delete、truncate 的区别(面试题

前面说了,delete 和 truncate 都是只删除数据,不删除表的结构,但他们之间还是有小区分的。

  1. delete可以加where条件,truncate不可以。
  2. truncate删除,效率高一些。DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。
  3. 假如要删除的表中有自增长列,如果用delete删除后,再插入数据,自增长列的值从断点开始。而truncate删除后,再插入数据,自增长列的值从1开始。
  4. truncate删除没有返回值,delete删除有返回值。
  5. truncate删除不能回滚,delete删除可以回滚。

5.5、查询该数据库中所有的表:SHOW TABLES

在已经进入某个数据库中,想看这个库里面有哪些表格,就可以用下面的命令:

SHOW TABLES;

6、从表中查询数据

去重

SELECT DISTINCT department_id FROM employees;
# 查询员工表涉及到的所有部门编号(不重复的显示)

DISTINCT 关键字 可以让显示的结果,去重。

6.1、基本查询表中的数据指令:SELECT

当我们数据库中有数据了,我们需要查询,获取数据时,可以用 SELECT 语句,其基本用法为:

SELECT 
    column_1, column_2, ...
FROM
    table_1
[查询条件];
# 需要从 table_1 中,获取到 列名为 column_1, column_2, ... 的数据(并显示出来)
# 如果有 额外的查询条件,就要满足,这个后面会继续分析

如果要查询 表中的所有内容(所有列),就使用 通配符 * 来SELECT * FROM tablename

举个例子

要查询 students 表中所有学生的名字和年龄,那么就是 SELECT name, age FROM students;,其执行结果如下:

mysql> select name, age from students;
+--------+-----+
| name   | age |
+--------+-----+
| 王刚   |  20 |
| 孙丽华 |  21 |
| 王永恒 |  23 |
| 郑俊杰 |  19 |
| 陈芳   |  22 |
| 张伟朋 |  21 |
+--------+-----+
6 rows in set (0.00 sec)

注意了,我们 不仅可以查询到 对应的字段,我们还可以对字段进行处理后,再显示(这里还可以结合 别名

mysql> select name, age * 10 十倍年纪 from stu;
+------+----------+
| name | 十倍年纪 |
+------+----------+
||      200 |
||      200 |
||      200 |
||      180 |
+------+----------+
4 rows in set (0.00 sec)

# 我们将 age * 10 再显示出来,但是我们显示的时候,给其取了别名,那么显示出来的时候,就是用别名显示。
# 十倍年纪,相当于是一个 标识符,而不是字符串,所以是直接写。

关于 [查询条件]

实际上,我们的查询条件,可以有很多种类型,不单单是 WHERE,还可以用其他的,甚至 MySQL 的函数也可以,大概为下面那些:

SELECT 
    column_1, column_2, ...
FROM
    table_1
[INNER | LEFT |RIGHT] JOIN table_2 ON conditions
WHERE
    conditions
GROUP BY column_1
HAVING group_conditions
ORDER BY 排序列表 [asc / desc]
LIMIT offset, length;

语句中的SELECTFROM语句是必须的,其他部分是可选的。

  • SELECT之后是逗号分隔列或星号(*)的列表,表示要返回所有列。
  • FROM指定要查询数据的表或视图。
  • JOIN根据某些连接条件从其他表中获取数据。(连接查询)
  • WHERE过滤结果集中的行。(条件查询
  • GROUP BY将一组行组合成小分组,并对每个小分组应用聚合函数。(分组查询
  • HAVING过滤器基于GROUP BY子句定义的小分组。
  • ORDER BY指定用于排序的列的列表。(排序查询
  • LIMIT限制返回行的数量。(分页查询

这些都在紧接着的小节来讲解

6.2、通过条件筛选查询:WHERE

SELECT 
    column_1, column_2, ...
FROM
    table_1
[INNER | LEFT |RIGHT] JOIN table_2 ON conditions
WHERE
    conditions
GROUP BY column_1
HAVING group_conditions
ORDER BY 排序列表 [asc / desc]
LIMIT offset, length;

发现,在使用 SELECT 查询的时候,我们可以用 WHERE 来限制,我们想查询到的数据,满足一定的条件(比如,是男的,是女的)

关于 WHERE 的时候,一般是(也不仅仅是 SELECT 才可以用,前面讲的 UPDATE 中 也可以结合 WHERE 使用):

SELECT
	查询列表
FROM
	表名
WHERE
	筛选条件;

其总共分为三类:

  • 按条件表达式筛选。包括:>, <, =, !=, <>, >=, <=,(!= 和 <>都可以表示不等于)
  • 按逻辑表达式筛选and, or, not 分别得意思就是,与,或,非。
  • 模糊查询。会包括 LIKE, BETWEEN AND, IN, IS NULL, IS NOT NULL

6.2.1、按条件表达式筛选

包括:>, <, =, !=, <>, >=, <=,(!= 和 <>都可以表示不等于)

注意,这里判断 等于是 =,而不是 ==

#案例1:查询 工资 > 12000 的员工信息
SELECT
	*
FROM
	employees
WHERE
	salary > 12000;

	
#案例2:查询部门编号 不等于90号 的员工名和部门编号
SELECT
	last_name,
	department_id
FROM
	employees
WHERE
	department_id != 90;
# != 也可以换成 <>

6.2.2、按逻辑表达式筛选

and, or, not 分别的意思就是,与,或,非。

#案例1:查询工资在10000到20000之间的员工名,工资和奖金
SELECT
	last_name,
	salary,
	commission_pct
FROM
	employees
WHERE
	salary >= 10000 AND salary <= 20000;
# 因为是要找 一个范围,所以用 AND,相当于是 && 连接

	
#案例2:查询部门编号不在90-110之间,或者工资高于15000的员工信息
SELECT
	*
FROM
	employees
WHERE
	department_id < 90 OR department_id > 110 OR salary > 15000;
# 根据要求,应该是 小于 90,或者大于 110;或者大于 150
# OR 相当于是 || 

6.2.3、模糊查询(结合在 WHERE 中使用的)

包括 LIKE, BETWEEN AND, IN, IS NULL, IS NOT NULL

6.2.3.1、LIKE:判断是否模糊匹配字符串
/*
一般和通配符搭配使用。通配符:
	% 任意多个字符,包含0个
	_ 任意单个字符

*/
# 案例1:查询员工名中包含 字符a 的员工信息
SELECT
	*
FROM
	employees
WHERE
	last_name LIKE '%a%';	
# 因为我们是要查找名字中有 a,也就是 名字 中要有 a
# 那么就是 %a%,无论前面后面有没有其他字符(甚至无),只要出现 a 就可以


#案例2:查询员工名中 第3个字符为n,第五个字符为l 的员工名和工资
SELECT
	last_name,
	salary
FROM
	employees
WHERE
	last_name LIKE '__n_l%';
# 那就是要求,判断条件 WHERE 中,员工名 要是 __n_l% 的结构(因为后面可以是任意多个字符,所以是 %)
	
	
#案例3:查询员工名中 第二个字符为_ 的员工名(转义字符)	
SELECT
	last_name
FROM 
	employees
WHERE 	 
	last_name LIKE '_\_%';	
# 因为 _ 是特殊字符,那么要判断 _ 就需要是 \_,转义字符
# 那么就是 _\_% 即可,第二个是 字符是 _
6.2.3.2、BETWEEN AND:判断是否在一个区间
/*
BETWEEN a AND b,其实就是 [a, b],包含边界值
两个临界值顺序不能调换

*/

#案例1:查询员工编号在100到120之间的员工信息
SELECT
	*
FROM
	employees
WHERE
	employee_id BETWEEN 100 AND 120;
	
# 相当于是
SELECT
	*
FROM
	employees
WHERE
	employee_id >= 100 AND employee_id <= 120;
6.2.3.3、IN:判断是不是列表中的某一项
/*
含义:用于判断某字段的值是否属于in列表中的某一项
特点:
	①使用in提高语句简洁度
	②in列表的值类型必须统一或者兼容
	③不支持通配符
*/

#案例:查询员工的工种编号是 IT_PROT, AD_VP, AD_PRES中 的一个的员工名和工种编号
SELECT
	last_name,
	job_id
FROM
	employees
WHERE
	job_id IN ('IT_PROT' ,'AD_VP' , 'AD_VP');

# 相当于----------------------------------------------------
SELECT
	last_name,
	job_id
FROM
	employees
WHERE
	job_id='IT_PROT' OR job_id='AD_VP' OR job_id='AD_VP';
6.2.3.4、IS NULL:判断值是不是NULL

因为判断 是不是 NULL 值,无法用 =, !=, <> 来判断,所以,只能用 IS NULLIS NOT NULL 来判断,对应的,是不是 NULL 值。

#案例1:查询没有奖金的员工名和奖金率
SELECT
	last_name,
	commission_pct
FROM
	employees
WHERE
	commission_pct IS NULL;

6.3、排序查询(返回结果按要求排序显示):ORDER BY

SELECT 
    column_1, column_2, ...
FROM
    table_1
[INNER | LEFT |RIGHT] JOIN table_2 ON conditions
WHERE
    筛选条件
GROUP BY column_1
HAVING group_conditions
ORDER BY 排序列表 [asc / desc]
LIMIT offset, length;

这里面,有一个 ORDER BY,就是说,我们获取到的数据,显示的时候,可以按照我们要求以 column_1 来排序(升序、降序)来显示

语法如下:

SELECT 
    column_1, column_2, ...
FROM
    table_1
WHERE
    筛选条件
ORDER BY 排序列表 [asc / desc]

# 1、asc代表升序,desc代表降序,默认不写是升序
# 2、order by子句中可以支持单个字段、多个字段、表达式、函数、别名
# 3、order by 子句一般是放在查询语句的最后面,但在limit子句 之前

例子

# 案例1:查询员工信息,要求工资从高到低排序
SELECT * 
FROM employees 
ORDER BY salary DESC;
# 以 salary 从高到低的显示。从高到低就是 降序。


#案例2:查询部门编号 >=90 的员工信息,按入职时间的先后进行排序
SELECT *
FROM employees
WHERE department_id >= 90
ORDER BY hiredate ASC;


#案例3:按年薪高低显示员工的信息和年薪
SELECT *, salary*12*(1+IFNULL(commission_pct,0)) AS 年薪
FROM employees
ORDER BY salary*12*(1+IFNULL(commission_pct,0)) DESC;
# 这里除了原本的所有字段 * 显示,还显示多一列 年薪(起别名的)。也是安装这个来排序
# 其实后面 ORDER BY salary*12*(1+IFNULL(commission_pct,0)) 可以写成
# ORDER BY 年薪, 相当于下面这个:
SELECT *, salary*12*(1+IFNULL(commission_pct,0)) AS 年薪
FROM employees
ORDER BY 年薪 DESC;


#案例4:按姓名的长度显示员工的姓名和工资 [按函数排序]
SELECT LENGTH(last_name) AS 字节长度, last_name,salary
FROM employees
ORDER BY 字节长度 DESC;
# 利用函数,计算 姓名的长度,从而可以排序


#案例6:查询员工信息,要求先按工资升序,再按员工编号降序 [按多个字段排序]
SELECT * 
FROM employees
ORDER BY salary ASC, employee_id DESC;
# 整体按工资排序,工资相同时,按员工编号降序
# 排序的要求,可以是多个结合,按照前后优先级判断。

6.4、连接查询(多个表中读取数据):JOIN

我们之前,都是在一张表中,读取(查看)数据。那么如果我们想要在多个 表中 查询数据,就可以用到 JOIN 来实现,语法大致如下:

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

SELECT 
    column_1, column_2, ...
FROM
    table_1
[INNER | LEFT | RIGHT] JOIN table_2 ON conditions
WHERE
    conditions

从中可以发现,JOIN 有三类:

  • INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系(相交信息)的记录。
  • LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录
  • RIGHT JOIN(右连接): 与 LEFT JOIN 相反,用于获取右表所有记录,即使左表没有对应匹配的记录

用实例来讲解,会清楚。假设有两个表:

mysql> use RUNOOB;
Database changed
mysql> SELECT * FROM tcount_tbl;
+---------------+--------------+
| runoob_author | runoob_count |
+---------------+--------------+
| 菜鸟教程  | 10           |
| RUNOOB.COM    | 20           |
| Google        | 22           |
+---------------+--------------+
3 rows in set (0.01 sec)
 
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)

6.4.1、INNER JOIN(内连接,或等值连接)

image

读取的,要求两个表中都存在的数据,假如 一个有,另一个没有,那就不能读取。

现在,我们想要读取 runoob_tbl 表中所有 runoob_author 字段在 tcount_tbl 表对应的 runoob_count 字段值

此时就出现了两个表同时读取,其中是按照 runoob_author 来连接两个表的

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;
+-------------+-----------------+----------------+
| 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.00 sec)

# 注意了,我们给连个 表起了别名,a 和 b。此时我们连接 a 和 b,以 ON 后面为准(两个表中的,runoob_author 相等)
# 显示出来的内容,以 SELECT 为准
# 现在就是,我们获取两个表中,有着相同内容 runoob_author,此时是相交连接,所以取出来的是,两者 共有的

6.4.2、LEFT JOIN(左连接)

image

读取的,会读取左边数据表的全部数据,即便右边表无对应数据。(LEFT,读取全部左表的数据,如果对应的数据在右边中无,那么就设为 NULL)

读取左边的数据表 runoob_tbl 的所有选取的字段数据,即便在右侧表 tcount_tbl中 没有对应的 runoob_author 字段值。

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)

# 此时,虽然还是以 runoob_author 为准,但是我们优先读 左边 runoob_tbl,发现了 FK 在 右边不存在,但是照样还是显示了。
# 而对应的 b.runoob_count 没有 FK 的数据,所以设为了 NULL

6.4.3、RIGHT JOIN(右连接)

类似 LEFT JOIN,只是反过来了而已。

image

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

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)

# 此时,对 tcount_tbl 的全部数据读取。
# 发现在 tcount_tbl 有一个 Google 在 runoob_tbl 没有,但是还是显示出来了,因为要全部 tcount_tbl 的数据
# 只是,没有的值,我们就用 NULL 显示。

6.5、MySQL函数

举例一些常用的,比较齐全的看:https://www.runoob.com/mysql/mysql-functions.html

对于函数,我们有时候使用,会比较方便,可以实现一些功能,方便。

字符函数:length  concat substr
instr trim upper lower
lpad rpad replace

数学函数: round ceil floor truncate mod

日期函数:now curdate curtime year month monthname 
day hour minute second str_to_date  date_format

其他函数:version database user

控制函数: if case

6.5.1、字符函数

#1. length 获取参数值的字节个数
SELECT LENGTH('john');#4
SELECT LENGTH('张三丰hahaha');#15,utf8一个汉字占3个字节


#2. concat 拼接字符串(用下划线拼接)
SELECT CONCAT(last_name,'_',first_name) FROM employees;


#3. upper,lower
SELECT UPPER('john');#变大写
SELECT LOWER('JOHN');#变小写
#示例:将姓变大写,名变小写,拼接 
SELECT CONCAT(UPPER(last_name),LOWER(first_name)) AS 姓名 FROM employees;


#4. substr,substring
#注意索引从1开始,下语句输出:和李四
#截取从指定索引处后面所有字符
SELECT SUBSTR('张三和李四',3) out_put;

#截取从指定索引处指定字符长度的字符
#下面语句输出:张三
SELECT SUBSTR('张三和李四',1,2) out_put;

#案例:姓名中首字符大写,其他字符小写,用_拼接,显示出来
SELECT CONCAT(UPPER(SUBSTR(last_name,1,1)),'_',LOWER(SUBSTR(last_name,2))) output
FROM employees;


#5. instr
#返回子串的起始索引,找不到返回0
SELECT INSTR('杨不悔爱上了殷六侠','殷六侠') AS out_put


#6、trim 去掉首尾的字符,默认是去除 空格。
#输出张翠山
SELECT LENGTH(TRIM('    张翠山      ')) AS out_put;
#输出张aaaa翠山
SELECT TRIM('a' FROM 'aaaa张aaaa翠山aaaaaaaa') AS out_put;


#7、 lpad  用指定的字符实现左填充指定长度
#输出*******殷素素
SELECT LPAD('殷素素',10,'*') AS out_put;
#输出:殷素
SELECT LPAD('殷素素',2,'*') AS out_put;


#8、 rpad  用指定的字符实现右填充指定长度
#输出:殷素素ababababa
SELECT RPAD('殷素素',12,'ab') AS out_put;


#9、replace 替换
SELECT REPLACE('张无忌爱上了周芷若','周芷若','赵敏') AS out_put;

6.5.2、数学函数

#1、round四舍五入
SELECT ROUND(1.65);#2
SELECT ROUND(-1.45);#-1
SELECT ROUND(1.567,2);#1.57,小数点后保留2位


#2、ceil向上取整(返回>=该参数的最小整数)
SELECT CEIL(-1.02);#-1
SELECT CEIL(1.00);#1


#3、floor 向下取整,返回<=该参数的最大整数
SELECT FLOOR(-9.99);#-10


#4、truncate 截断
SELECT TRUNCATE(1.65,1);#1.6;


#5、mod 取余(也可以直接用 % 运算符)
/*
mod(a,b) : a-a/b*b

mod(-10,-3) : -10-(-10)/(-3)*(-3)=-1;
*/
SELECT MOD(10,-3);#1

6.5.3、日期函数

#1、now:返回当前系统日期加时间
SELECT NOW();


#2、curdate 返回当前系统日期,不包含时间
SELECT CURDATE();


#3、curtime() 返回当前时间,不包含日期
SELECT CURTIME();

#4、可以获取指定的部分,年,月,日,小时,分,秒
SELECT YEAR(NOW()) AS;
SELECT YEAR('1998-1-1');

SELECT YEAR(hiredate)FROM employees;

SELECT MONTH(NOW());
SELECT MONTHNAME(NOW());#显示英文月份

#5、str_to_date 将日期格式的字符转换成指定格式的日期
# 将对应的字符串(要指明其形式),然后转化为 标准的 年月日的日期格式
/*
%Y 四位的年份
%y 2位的年份
%m 月份 (01,02,...12)
%c 月份(1,2,..., 12)
%d 日
%H 小时(24)%h(12)
%i 分钟  %s秒
*/
SELECT STR_TO_DATE('9-13-1999','%m-%d-%Y') 日期;#1999-09-13
SELECT STR_TO_DATE ('2020-4-17','%Y-%c-%d') AS output;#2020-4-17

#查询入职日期为1992-4-3的员工信息
SELECT * FROM employees WHERE hiredate='1992-4-3';
SELECT * FROM employees WHERE hiredate=STR_TO_DATE('4-3 1992','%c-%d %Y');


#6、date_format 将日期转换成字符
# 将 标准的日期格式,转化为 我们想要的 字符串格式,方便用于输出显示
SELECT DATE_FORMAT(NOW(),'%y年%m月%d日') AS output;#20年4月17日

#查询有奖金的员工名和入职日期(xx月/xx日 xx年)
SELECT last_name,DATE_FORMAT(hiredate,'%m月/%d日 %Y年') 入职日期
FROM employees
WHERE commission_pct IS NOT NULL;

6.5.4、其他函数

SELECT VERSION();
SELECT DATABASE();#查看当前库
SELECT USER();

6.5.5、流程控制函数

#1、IF 函数:if else 的效果

SELECT IF(10>5,'大','小');

SELECT last_name,commission_pct,IF(commission_pct IS NULL,'没奖金','有奖金') 备注
FROM employees;


#2.case函数的使用一: switch case的效果
/*
case 要判断的字段或表达式
when 常量1 then要显示的值1或语句1;
when 常量2 then要显示的值2或语句2;
...
else 要显示的值n或语句n
end
(搭配select当表达式,then加一个值,或者不搭配select当语句)
*/
/*案例:查询员工的工资:要求
部门号=30,显示的工资为1.1倍
部门号=40,显示的工资为1.2倍
部门号=50,显示的工资为1.3倍
其他部门显示原工资
*/

SELECT salary,department_id,
CASE department_id
WHEN 30 THEN salary*1.1
WHEN 40 THEN salary*1.2
WHEN 50 THEN salary*1.3
ELSE salary
END AS 新工资
FROM employees;


#3.case函数的使用二: 类似于多重if
/*
case  
when 条件1 then 要显示的值1或语句1
when 条件2 then 要显示的值2或语句2
...
else 要显示的值n或语句n
end
*与上一种情况的不同就是case后不加表达式
*/

#案例:查询员工的工资情况
/*
如果工资>20000,显示A级别
如果工资>15000,显示B级别
如果工资>10000,显示C级别
否则显示D级别
*/

SELECT salary,
CASE
WHEN salary>20000 THEN 'A'
WHEN salary>15000 THEN 'B'
WHEN salary>10000 THEN 'C'
ELSE 'D'
END AS 工资级别
FROM employees;

6.5.6、分组函数

#六、分组函数
/*
功能:用作统计使用,又称为聚合函数或统计函数或组函数
分类:sum 求和、avg平均值、max最大值、min最小值、count计算 非NULL 个数
特点
1、sum,avg用于处理数值型。max,min,count可以处于任何类型
2、以上分组函数都忽略null值
3、可以和distinct搭配实现去重
4、count函数的单独介绍
5、和分组函数一同查询的字段要求是group by后的字段
*/

#1.简单的使用
SELECT SUM(salary) FROM employees;
SELECT SUM(salary) ,ROUND(AVG(salary),2)  FROM employees;
SELECT MAX(salary) ,MIN(salary) FROM employees;
SELECT MIN(salary) FROM employees;
SELECT COUNT(salary) FROM employees;

#2.参数支持哪些类型
 SELECT SUM(last_name),AVG(last_name) FROM employees;
 SELECT SUM(hiredate),AVG(hiredate) FROM employees;
 #无意义,不这样用,SUM 和 AVG 只能算数值类型
 
 SELECT MAX(last_name),MIN(last_name) FROM employees;
 SELECT MAX(hiredate),MIN(hiredate) FROM employees;
 #支持
 
 SELECT COUNT(last_name) FROM employees; #计算非空的值 107
 SELECT COUNT(commission_pct) FROM employees;#35
 
 
 #3、是否忽略null
 SELECT SUM(commission_pct),AVG(commission_pct) FROM employees;
  
  
#4、和distinct搭配
SELECT SUM(DISTINCT salary), SUM(salary) FROM employees;
SELECT COUNT(DISTINCT salary), COUNT(salary) FROM employees;
  
  
#5、count函数的详细介绍
SELECT COUNT(salary) FROM employees;
SELECT COUNT(*) FROM employees;#统计每一列的数目,即所有行数
SELECT COUNT(1) FROM employees;#和上一语句效果一样
  
#6、和分组函数一同查询的字段有限制
SELECT AVG(salary),employee_id FROM employees;#这个员工id查出来没有意义  

6.6、分组查询

SELECT 
    column_1, column_2, ...
FROM
    table_1
[INNER | LEFT |RIGHT] JOIN table_2 ON conditions
WHERE
    conditions
GROUP BY column_1   # 这个就是 分组查询
HAVING group_conditions
ORDER BY column_1
LIMIT offset, length;   # 这个就是 分页查询

GROUP BY 语句根据一个或多个列(如果是多个,就直接接在后面 , 隔开)对结果集进行分组。

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

大概的 分组查询的 语法:

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

# 按照 column_name 分组,然后显示 column_name 和 其分组中记录对应的 分组函数
# 其中 function 指的是 分组函数,SUM,MAX 之类的
# 要求,我们SELECT 后操作的列,也要出现在 GROUP BY 后
# group by子句支持单个字段分组,多个字段分组(多个字段之间用逗号隔开无顺序要求)

举个实例

/*
+----+--------+---------------------+--------+
| 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 |
+----+--------+---------------------+--------+
*/
# 现在有以上的表格,我们现在,按照 名字进行分组,同时统计每个人有几条记录

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

# 按照 name 分组,一个人,对应很多记录,分组后,只有 name 是不重复,然后统计了对应的记录条数。
/* 显示结果如下:
+--------+----------+
| name   | COUNT(*) |
+--------+----------+
| 小丽 |        1 |
| 小明 |        3 |
| 小王 |        2 |
+--------+----------+
3 rows in set (0.01 sec)
*/

6.7、分页查询(指明读取数据的条数)

应用场景:当要显示的数据一页显示不全时,那就要分页显示

比如说网页显示成绩,一次可以显示 10 门成绩,总共有 25 门成绩。那么此时,一次性读 10 门课成绩,也显示不完。因此第一页的时候,我们就读取前 10 条数据来显示。当有人点击下一页的时候,再加载 后 10 条数据来显示。
所以,这个 分页查询 指明了我们一次读几条数据,读的是,哪几条数据

基本格式

SELECT 
    column_1, column_2, ...
FROM
    table_1
[INNER | LEFT |RIGHT] JOIN table_2 ON conditions
WHERE
    conditions
GROUP BY column_1
HAVING group_conditions
ORDER BY column_1
LIMIT offset, length;   # 这个就是 分页查询

分页查询,一般是放在最后面。有两个参数

  • offset:这次读取的数据,是从 offset 这个位置开始读取(然后往后读取 length 条)。这个下标是从 0 开始的。
    • 比如我们从 第 5 条数据开始读取,那就是 offset = 5 - 1 = 4
  • length:要读取的数据 条数,即我们这次要读取 length 条数据

如果我们要读取 第 a 到 第 b 条数据,其实要读取的,就是:LIMIT a - 1 b - a + 1

如果 LIMIT 后面只跟一个参数,表示 省略了 offset,此时省略 offset 就是 默认 offset = 0

例子

#案例1:查询前五条员工信息
SELECT * FROM employees LIMIT 0,5;
SELECT * FROM employees LIMIT 5;


#案例2:查询第11条——第25条
SELECT * FROM employees LIMIT 10,15;


#案例3:有奖金的员工信息,并且工资较高的前10名显示
SELECT * FROM employees 
WHERE commission_pct IS NOT NULL
ORDER BY salary DESC
LIMIT 10;

7、创建之后表的修改:ALTER TABLE

alter table 语句用于创建后对表的修改, 基础用法如下:

7.1、添加列(增加某个字段内容)

基本形式:

ALTER TABLE 表名 ADD 列名 列数据类型 [数据类型属性] [after 插入位置];

# 对表名这个表,增加一列(一个字段,并且指明了这个字段的数据类型),该字段在 某个插入位置(字段)后
# 如果没有 [] 这个参数,默认新增字段,放在 最后

例子

ALTER TABLE students 
ADD address char(60);
# 在表的最后,新增一个字段,为 address,其为 一个字符串


ALTER TABLE students 
ADD birthday date 
AFTER age;
# 在名为 age 的列(字段)后插入新的列 birthday(其数据类型为 date)

7.2、修改列(修改字段名)

基本形式:

ALTER TABLE 表名 
CHANGE 列名称 列新名称 新数据类型 [数据类型属性];

# 将原来的 字段,更改为 新的字段(其数据类型也要指明)

例子

ALTER TABLE students 
CHANGE tel telphone char(13) default '-';
# 将原来的 tel 列名 改为 telphone,其数据类型 和 属性 都指明了


ALTER TABLE students 
CHANGE name name char(16) not null;
# 将 name 列的数据类型改为 char(16)。这里虽然是用改列,但实际上不是为了改名,而是为了改 列的数据类型

7.3、删除列

基本形式:

ALTER TABLE 表名 DROP 列名称;
# 将这列删除(同时这一列对应下去的数据,也都删除了)

例子

# 删除 birthday 列:
ALTER TABLE students 
DROP birthday;

7.4、重命名表

基本形式:

ALTER TABLE 表名 rename 新表名;
# 将原来的表名,更改为 新表名

例子

ALTER TABLE students 
RENAME workmates;
# 重命名 students 表为 workmates:

8、MySQL 导入/导出 数据

8.1、MySQL 导入数据

8.1.1、mysql 命令导入(整个数据库导入)

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

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

例子

mysql -u root -p 123456 < runoob.sql

将 runoob 作为整个数据库导入。

8.1.2、source 命令导入(整个数据库导入)

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

mysql> create database abc;      # 创建数据库
mysql> use abc;                  # 使用已创建的数据库 
mysql> source /home/abc/abc.sql  
# 从abc.sql 导入整个数据库进来

8.1.3、LOAD DATA导入数据(数据插入到 表中)

和 8.2.1 的导出数据互为逆过程

以下实例中将从当前目录中读取文件 dump.txt ,将该文件中的数据插入到当前数据库的 mytbl 表中

mysql> LOAD DATA LOCAL INFILE 'dump.txt' INTO TABLE mytbl;

如果指定 LOCAL 关键词,则表明从客户主机上按路径读取文件。如果没有指定,则文件在服务器上按路径读取文件。

你能明确地在LOAD DATA语句中指出列值的分隔符和行尾标记(因为可能之前保存成 txt 的时候,不是按默认保存),但是默认标记是定位符和换行符。

两个命令的 FIELDS(注明列值分隔符) 和 LINES(行尾标记)。子句的语法是一样的。两个子句都是可选的,但是如果两个同时被指定,FIELDS 子句必须出现在 LINES 子句之前。

mysql> LOAD DATA LOCAL INFILE 'dump.txt' INTO TABLE mytbl
  -> FIELDS TERMINATED BY ':'
  -> LINES TERMINATED BY '\r\n';
# 此时列值分隔符是 :
# 行尾标志是 \r\n

LOAD DATA 默认情况下是按照数据文件中列的顺序插入数据的,如果数据文件中的列与插入表中的列不一致,则需要指定列的顺序。
如,在数据文件中的列顺序是 a,b,c,但在插入表的列顺序为b,c,a,则数据导入语法如下:

mysql> LOAD DATA LOCAL INFILE 'dump.txt' 
    -> INTO TABLE mytbl (b, c, a);

8.2、MySQL 导出数据

8.2.1、SELECT ... INTO OUTFILE 语句导出数据(表中数据导出)

和 8.1.3 的导入数据 互为逆过程

先要登陆到 MySQL 数据库中。

其实就是,我们将 数据表 的数据,导出到文件中(比如 .txt 文件)

SELECT 列名 
FROM 表名 
INTO OUTFILE 导出文件的完整路径;

其实就是,我们将从 表中读数据,先读取想要的数据(列名,可以是部分,也可以是全部),将其保存在 对应的 文件中即可

举个例子

SELECT * 
FROM runoob_tbl 
INTO OUTFILE '/tmp/runoob.txt';
# 将 runoob_tbl 的所有内容(*) 导出,保存在 runoob.txt 文件中

保存的时候,因为原本在表中,数据是一行一行的,那么在保存的时候,默认列的隔开符和行尾符为:定位符和换行符。(这里和8.1.3 的导入数据对应上的

那么如果我们想保存的时候,设置 列的隔开符 和 行尾符,可以用下面的语句来:

SELECT a,b,a+b 
FROM test_table;
INTO OUTFILE '/tmp/result.text'
FIELDS TERMINATED BY ',' [OPTIONALLY] ENCLOSED BY '"'
LINES TERMINATED BY '\n'

# SELECT 可以选择,导出的数据是 部分字段,还是所有字段
# FIELDS 设置的是,列的隔开符
# LINES 是行尾符
# ENCLOSED 表示,文件中字符值放在 “” 之中
# 如果是 OPTIONALLY ENCLOSED,表示所有的值,都是用 “” 包起
# FIELDS 指定每一列的数据应该怎么处理
# LINES 每一行之间怎么处理
# 可以只出现其中几个,也可全部一起;如果两个同时被指定,FIELDS 子句必须出现在 LINES 子句之前。

注意的点

  • LOAD DATA INFILESELECT ... INTO OUTFILE的逆操作。为了将一个数据库的数据写入一个文件,使用SELECT ... INTO OUTFILE,为了将文件读回数据库,使用LOAD DATA INFILE。(和8.1.3 的导入数据对应上的
  • 该文件被创建到服务器主机上,因此您必须拥有FILE权限,才能使用此语法。
  • 输出不能是一个已存在的文件。防止文件数据被篡改。
  • 你需要有一个登陆服务器的账号来检索文件。否则 SELECT … INTO OUTFILE 不会起任何作用(其实也就是要登陆到 数据库中)
  • 在UNIX中,该文件被创建后是可读的,权限由MySQL服务器所拥有。这意味着,虽然你就可以读取该文件,但可能无法将其删除。

8.2.2、mysqldump导出 SQL 格式的数据(可以导出单个表,也可以导出整个库)

这些不用登陆到 MySQL 中

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

$ mysqldump -u root -p 库名 库中的表名 > dump.txt
password ******

如果你需要导出整个数据库的数据,可以使用以下命令:

$ mysqldump -u root -p 库名 > database_dump.txt
password ******

如果需要备份所有数据库,可以使用以下命令:

$ mysqldump -u root -p --all-databases > database_dump.txt
password ******

8.2.3、将数据表及数据库拷贝至其他主机

第一种方法

在本机导出之后,将文件发送给其他主机,然后在其他主机上,加载到其他主机的数据库即可(先导出,再导入)

第二种方法:直接可以远程导入,不需要先导出再导入,直接一次性处理完

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

$ mysqldump -u root -p 要导出的库名 [表名] \
       | mysql -h 主机名 要导入的库名
# 上面是 本机,发送给 另一台主机
# 所以本机,就不用 -h,但是其他主机需要

利用了,管道


9、MySQL 脚本

脚本就是,将我们上面那些分散的那些指令,整个成一个文件 xxx.sql,然后运行这个 sql 脚本文件,就可以将指令执行。(类似于 shell 脚本,CPP 之类)

那么如果执行 sql 文件(脚本)呢?

方法一:直接执行 sql 文件

mysql -h localhost -u root -p123456 < E:\mysql\test.sql

# 也就是,在登陆 MySQL 的时候,重定向输入 这个 脚本文件,就可以运行了

方法二:先登录 MySQL,再执行 sql 脚本文件(source)

mysql -h localhost -u root -p123456
# 先登录进 MySQL 数据库中

source E:\mysql\test.sql
# 接着,加载(执行) sql 脚本文件
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值