mysql 子查询多个字段_036、MySQL子查询和索引

1.子查询

可以将子查询放在许多的 SQL 子句中,包括:

• WHERE 子句

• HAVING 子句

• FROM 子句

使用子查询的原则

• 子查询放在圆括号中。

• 将子查询放在比较条件的右边。

• 在单行子查询中用单行运算符,在多行子查询中用多行运算符。

示例 :谁的薪水比 Oldlu 高

select 

单行子查询

11fd75770b540d9de2c0dc25572a29cb.png

示例 :查询 Oldlu 的同事,但是不包含他自己。

select 

多行子查询

978713de18470ea40563c3c296b074c3.png

示例:查找各部门收入为部门最低的那些雇员。显示他们的名字,薪水以及部门 ID。

select 

2.MySQL 中的正则表达式

正则表达式

• MySQL 中允许使用正则表达式定义字符串的搜索条件,性能要高于 like。

• MySQL 中的正则表达式可以对整数类型或者字符类型检索。

• 使用 REGEXP 关键字表示正则匹配。

• 默认忽略大小写,如果要区分大小写,使用 BINARY 关键字

正则表达式的模式及其含义

41956706b5430c0751b37ea44e6a9efc.png

“^”符号

^在正则表达式中表示开始

语法

查询以 x 开头的数据(忽略大小写)

SELECT 列名 FROM 表名 WHERE 列名 REGEXP '^x';

示例 :查询雇员表中名字是以 k 开头的雇员名字与薪水。

select 

“$”符号

语法

查询以 x 结尾的数据(忽略大小写)

SELECT 列名 FROM 表名 WHERE 列名 REGEXP 'x$';

示例 :查询雇员表中名字是以 n 结尾的雇员名字与薪水。

select 

“.”符号

语法

英文的点,它匹配任何一个字符,包括回车、换行等。

SELECT 列名 FROM 表名 WHERE 列名 REGEXP 'x.';

示例 :查询雇员表中名字含有 o 的雇员的姓名与薪水。

select 

“*”符号

语法

“*”:星号匹配 0 个或多个字符,在它之前必须有内容。

“+”符号

语法

"+":加号匹配 1 个或多个字符,在它之前也必须有内容。

SELECT 列名 FROM 表名 WHERE 列名 REGEXP 'x+';-匹配大于 1 个的任意字符

“?”符号

语法

“?”:问号匹配 0 次或 1 次。

SELECT 列名 FROM 表名 WHERE 列名 REGEXP 'x?';-匹配 0 个或 1 个字符

“|”符号

语法

“|”:表示或者含义

SELECT 列名 FROM 表名 WHERE 列名 REGEXP 'abc|bcd';-匹配包含 abc 或 bcd

示例 :查询雇员表中名字含有 ke 或者 lu 的雇员的名字与薪水。

select 

“[a-z]”

语法

“[a-z]”:字符范围

“^[....]”:以什么字符开头的

“[^....]”:匹配不包含在[]的字符

SELECT 列名 FROM 表名 WHERE 列名 REGEXP '[a-z]';-匹配内容包含 a-z 范围的数据

示例一 :查询雇员表中名字包含 x、y、z 字符的雇员的名字和薪水。

select 

示例二:查询雇员名字是 t、f 开头的雇员名字与薪水。

select 

示例三 :查询雇员的名字与薪水,不包含 oldlu。

select 

“{n}” 语法

“{n}”:固定次数。

select * from student where name REGEXP 's{2}';--匹配以 s 连续出现 2 次的所有数据

示例一 :查询雇员名字含有连续两个 e 的雇员的姓名与薪水

select 

示例二 :查询名字中含有两个 o 的雇员的名字与薪水。

select 

“{n,m}” 语法

“{n,m}”:范围次数。

select * from student where name REGEXP '^s{2,5}';--匹配以 s 开头且重复 2 到 5 次的所有数据

示例 :查询雇员名字中包含 1 个或者两个 o 的雇员姓名与薪水。

select 

3.MySQL 中的其他对象:索引

MySQL 索引的建立对于 MySQL 的高效运行是很重要的,索引可以大大提高 MySQL的检索速度。

MySQL 中的索引类型

• 普通索引

• 唯一索引

• 主键索引

• 组合索引

• 全文索引

--普通索引

是最基本的索引,它没有任何限制。

在创建索引时,可以指定索引长度。length 为可选参数,表示索引的长度,只有字符串类型的字段才能指定索引长度,如果是 BLOB 和 TEXT 类型,必须指定 length。

创建索引时需要注意:

如果指定单列索引长度,length 必须小于这个字段所允许的最大字符个数。

---查询索引:

SHOW 

--直接创建索引

语法结构:CREATE INDEX index_name ON table(column(length))

示例 :为 emp3 表中的 name 创建一个索引,索引名为 emp3_name_index

create 

---修改表添加索引

语法结构:ALTER TABLE table_name ADD INDEX index_name (column(length))

示例 :修改 emp3 表,为 addrees 列添加索引,索引名为 emp3_address_index

alter 

--创建表时指定索引列

语法结构:

CREATE TABLE `table`

(

COLUMN TYPE ,

PRIMARY KEY (`id`),

INDEX index_name (column(length))

)

示例

创建 emp4 表,包含 emp_id,name,address 列,同时为 name 列创建索引。索引名为emp4_name_index

create 

--删除索引

语法结构:DROP INDEX index_name ON table

示例 :删除 mep3 表中索引名为 emp3_address_index 的索引

drop 

--唯一索引

唯一索引与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。它有以下几种创建方式:

---创建唯一索引

语法结构:CREATE UNIQUE INDEX indexName ON table(column(length))

示例 :为 emp 表中的 name 创建一个唯一索引,索引名为 emp_name_index

create 

修改表添加唯一索引

语法结构:ALTER TABLE table_name ADD UNIQUE indexName (column(length))

示例 :修改 emp 表,为 salary 列添加唯一索引,索引名为 emp_salary_index

alter 

--创建表时指定唯一索引

CREATE TABLE `table` (

COLUMN TYPE ,

PRIMARY KEY (`id`),

UNIQUE index_name (column(length))

)

示例

创建 emp5 表,包含 emp_id,name,address 列,同时为 name 列创建唯一索引。索引名为emp5_name_index

create 

--主键索引

主键索引是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般是在建表的时候同时创建主键索引。

---修改表添加主键索引

语法结构:ALTER TABLE 表名 ADD PRIMARY KEY(列名)

示例 :修改 emp 表为 employee_id 添加主键索引

alter 

--创建表时指定主键索引

CREATE TABLE `table` (

COLUMN TYPE ,

PRIMARY KEY(column)

)

示例 :创建 emp6 表,包含 emp_id,name,address 列,同时为 emp_id 列创建主键索引

create 

--组合索引

组合索引是指使用多个字段创建的索引,只有在查询条件中使用了创建索引时的第一个

字段,索引才会被使用(最左前缀原则)。

---最左前缀原则

就是最左优先。

如:我们使用表中的 name,address,salary 创建组合索引,那么想要组合索引生效,

我们只能使用如下组合:

name/address/salary

name/address

name/

如果使用 addrees/salary 或者是 salary 则索引不会生效。

--修改添加组合索引

语法结构:ALTER TABLE table_name ADD INDEX index_name (column(length),column(length))

示例 :修改 emp6 表,为 name,address 列创建组合索引

alter 

--创建表时创建组合索引

CREATE TABLE `table` (

COLUMN TYPE ,

INDEX index_name (column(length),column(length))

)

示例 :创建 emp7 表,包含 emp_id,name,address 列,同时为 name,address 列创建组合索引。

create 

--全文索引

全文索引(FULLTEXT INDEX)主要用来查找文本中的关键字,而不是直接与索引中的值相比较。FULLTEXT 索引跟其它索引大不相同,它更像是一个搜索引擎,而不是简单的 where语句的参数匹配。FULLTEXT 索引配合 match against 操作使用,而不是一般的 where 语句

加 like。

全文索引可以从 CHAR、VARCHAR 或 TEXT 列中作为 CREATE TABLE 语句的一部分被创建,或是随后使用 ALTER TABLE 添加。不过切记对于大容量的数据表,生成全文索引是一个非常消耗时间非常消耗硬盘空间的做法。

--修改添加全文索引

ALTER TABLE table_name ADD FULLTEXT index_content(content)

示例一 :修改 emp7 表添加 content 列类型为 TEXT

alter 

示例二 :修改 emp7 表,为 content 列创建全文索引

alter 

--创建表时创建全文索引

CREATE TABLE `table` (

COLUMN TYPE ,

FULLTEXT index_name (column)

)

示例

创 建 emp8 表 包 含 emp_id 列 , content 列 该 列 类 型 为 text , 并 为 该 列 添 加 名 为 emp8_content_fulltext 的全文索引

create 

--删除全文索引

语法结构:

DROP INDEX index_name ON table

ALTER TABLE table_name DROP INDEX index_name

示例 :删除 emp8 表中名为 emp8_content_full 的索引。

drop 

--使用全文索引

全 文 索 引 的 使 用 与 其 他 索 引 不 同 。 在 查 询 语 句 中 需 要 使 用 match(column) against(‘content’) 来检索数据。

---全文解析器

全文索引中基本单位是”词”。分词,全文索引是以词为基础的,MySQL 默认的分词是所有非字母和数字的特殊符号都是分词符。在检索数据时我们给定的检索条件也是词。MySQL 中默认的全文解析器不支持中文分词。如果数据含有中文需要更换全文解析器 NGRAM。

---使用全文索引

语法结构:SELECT 投影列 FROM 表名 WHERE MATCH(全文索引列名) AGAINST(‘搜索内容’)

示例一 :修改 emp8 表,为 content 列创建名为 emp8_content_full 的全文索引

alter 

示例二 :向 emp8 表中插入一条数据 content 的值为”hello,bjsxt”

insert 

示例三 :查询 emp8 表中内容包含 bjsxt 的数据。

select 

--更换全文解析器

在创建全文索引时可以指定 ngram 解析器

语法结构:

ALTER TABLE table_name ADD FULLTEXT index_content(content) WITH PARSER NGRAM

示例一 :删除 emp8 表中的 emp8_content_full 全文索引

drop 

示例二 :修改 emp8 表,为 content 列添加名称为 emp8_content_full 的全文索引,并指定 ngram 全文解析器。

alter 

4.MySQL 中的用户管理

MySQL 是一个多用户的数据库系统,按权限,用户可以分为两种:root 用户,超级管

理员,和由 root 用户创建的普通用户。

---MySQL 创建用户

CREATE USER username IDENTIFIED BY 'password';

---查看用户

SELECT USER,NOST FROM USER(该表位于 mysql 库中)

示例 :创建一个 u_sxt 的用户,并查看创建是否成功。

select 

--分配权限

新用户创建完后是无法登陆的,需要分配权限。

GRANT 权限 ON 数据库.表 TO 用户名@登录主机 IDENTIFIED BY "密码"

GRANT ALL PRIVILEGES ON *.* TO 'username'@'localhost' IDENTIFIED BY 'password'

登陆主机:

% 匹配所有主机

localhost localhost 不会被解析成 IP 地址,直接通过 UNIXsocket 连接

127.0.0.1 会通过 TCP/IP 协议连接,并且只能在本机访问;

::1 ::1 就是兼容支持 ipv6 的,表示同 ipv4 的 127.0.0.1

--权限列表

ALTER: 修改表和索引。

CREATE: 创建数据库和表。

DELETE: 删除表中已有的记录。

DROP: 删除数据库和表。

INDEX: 创建或删除索引。

INSERT: 向表中插入新行。

SELECT: 检索表中的记录。

UPDATE: 修改现存表记录。

FILE: 读或写服务器上的文件。

PROCESS: 查看服务器中执行的线程信息或杀死线程。

RELOAD: 重载授权表或清空日志、主机缓存或表缓存。

SHUTDOWN: 关闭服务器。

ALL: 所有权限,ALL PRIVILEGES 同义词。

USAGE: 特殊的 "无权限" 权限

示例 :为 u_sxt 用户分配只能查询 bjsxt 库中的 employees 表,并且只能在本机登陆的权限。

grant 

---刷新权限

每当调整权限后,通常需要执行以下语句刷新权限

FLUSH PRIVILEGES

---删除用户

DROP USER username@localhost

示例 :删除 u_sxt 用户

drop 

--通过 Navicat 工具管理用户

---创建用户

8ac60b699e6058353a76c496b2a6197d.png

1cb884cbde3f88c6ca7624cab75eb6f9.png

分配权限

9116d3b71caf41fb797e736eddbea056.png

a8fd5ad731a7bb8b0c08b08f732da4af.png

cb143ec80a92f83ee4298a57fe86186a.png

5.MySQL 分页查询

MySQL 分页查询原则

• 在 MySQL 数据库中使用 LIMIT 子句进行分页查询。

• MySQL 分页中开始位置为 0。

• 分页子句在查询语句的最后侧。

--LIMIT 子句

语法格式

SELECT 投影列 FROM 表名 WHERE 条件 ORDER BY LIMIT 开始位置,查询数量。

示例 :查询雇员表中所有数据按 id 排序,实现分页查询,每次返回两条结果。

select 

--LIMIT OFFSET 子句

语法格式

SELECT 投影列 FROM 表名 WHERE 条件 ORDER BY LIMIT 查询数量 OFFSET 开始位置。

示例 :查询雇员表中所有数据按 id 排序,使用 LIMIT OFFSET 实现分页查询,每次返回两条结果。

select 

6.MySQL 中的执行计划

--MySQL 执行计划

在 MySQL 中可以通过 explain 关键字模拟优化器执行 SQL 语句,从而知道 MySQL 是如何处理 SQL 语句的。

--MySQL 整个查询执行过程

• 客户端向 MySQL 服务器发送一条查询请求

• 服务器首先检查查询缓存,如果命中缓存,则立刻返回存储在缓存中的结果。否则进

入下一阶段

• 服务器进行 SQL 解析、预处理、再由优化器生成对应的执行计划

• MySQL 根据执行计划,调用存储引擎的 API 来执行查询

• 将结果返回给客户端,同时缓存查询结果

--启动执行计划

EXPLAIN SELECT 投影列 FROM 表名 WHERE 条件

--EXPLAIN 列的解释

--ID

查询执行顺序:

id 值相同时表示从上向下执行

id 值相同被视为一组

如果是子查询,id 值会递增,id 值越高,优先级越高

--select_type

simple:表示查询中不包含子查询或者 union

primary:当查询中包含任何复杂的子部分,最外层的查询被标记成 primary

derived:在 from 的列表中包含的子查询被标记成 derived

subquery:在 select 或 where 列表中包含了子查询,则子查询被标记成 subquery

union:两个 select 查询时前一个标记为 PRIMARY,后一个标记为 UNION。union 出现

在 from 从句子查询中,外层 select 标记为 PIRMARY,union 中第一个查询为 DERIVED,第二个子查询标记为 UNION

unionresult:从 union 表获取结果的 select 被标记成 union result 。

--table

显示这一行的数据是关于哪张表的。

--type

这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为 system、const、 eq_reg、ref、range、index 和 ALL。

system:表中只有一行数据。属于 const 的特例。如果物理表中就一行数据为 ALL

const :查询结果最多有一个匹配行。因为只有一行,所以可以被视为常量。const 查询速度非常快,因为只读一次。一般情况下把主键或唯一索引作为唯一条件的查询都是 const

eq_ref:查询时查询外键表全部数据。且只能查询主键列或关联列。且外键表中外键列中数据不能有重复数据,且这些数据都必须在主键表中有对应数据(主键表中数据可以有没有用到的)

ref:相比 eq_ref,不对外键列有强制要求,里面的数据可以重复,只要出现重复的数据取值就是 ref。也可能是索引查询。

range:把这个列当作条件只检索其中一个范围。常见 where 从句中出现 between、<、in 等。

主要应用在具有索引的列中

index:这个连接类型对前面的表中的每一个记录联合进行完全扫描(比 ALL 更好,因为索引一般小于表数据)。

ALL:这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免。

--possible_keys

查询条件字段涉及到的索引,可能没有使用。

--Key

实际使用的索引。如果为 NULL,则没有使用索引。

--key_len

表示索引中使用的字节数,查询中使用的索引的长度(最大可能长度),并非实际使用长度,理论上长度越短越好。key_len 是根据表定义计算而得的,不是通过表内检索出的。

--ref

显示索引的哪一列被使用了,如果可能的话,是一个常量 const。

--rows

根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数。

--Fitered

显示了通过条件过滤出的行数的百分比估计值。

--extra

MYSQL 如何解析查询的额外信息。

Distinct:MySQL 发现第 1 个匹配行后,停止为当前的行组合搜索更多的行。

Not exists:MySQL 能够对查询进行 LEFT JOIN 优化,发现 1 个匹配 LEFT JOIN 标准的行后,不再为前面的的行组合在该表内检查更多的行。

range checked for each record (index map: #):MySQL 没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用。

Using filesort:MySQL 需要额外的一次传递,以找出如何按排序顺序检索行。

Using index:从只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的列信息。

Using temporary:为了解决查询,MySQL 需要创建一个临时表来容纳结果。

Using where:WHERE 子句用于限制哪一个行匹配下一个表或发送到客户。

Using sort_union(...), Using union(...), Using intersect(...): 这 些 函 数 说 明 如 何 为

index_merge 联接类型合并索引扫描。

Using index for group-by:类似于访问表的 Using index 方式,Using index for group-by 表示

MySQL 发现了一个索引,可以用来查 询 GROUP BY 或 DISTINCT 查询的所有列,而不要额外搜索硬盘访问实际的表。

7.MySQL 数据库存储引擎介绍

查看 MySQL 数据库中的数据库存储引擎

4851aec388a13dd48d5cd120ce0f0a0e.png

ISAM(Indexed Sequential Access Method)

ISAM 是一个定义明确且历经时间考验的数据表格管理方法,它在设计之时就考虑到数据库被查询的次数要远大于更新的次数。

注意:使用 ISAM 时必须经常备份所有实时数据。

MyISAM

MyISAM 是 MySQL 的 ISAM 扩展格式和缺省的数据库引擎。除了提供 ISAM 里所没有的索引和字段管理的大量功能,MyISAM 还使用一种表格锁定的机制,来优化多个并发的读写操作,其代价是你需要经常运行 OPTIMIZE TABLE 命令,来恢复被更新机制所浪费的空间。

注意:MyISAM 引擎使用时必须经常使用 Optimize Table 命令清理空间;必须经常备份所有实时数据。工具有用来修复数据库文件的 MyISAMCHK 工具和用来恢复浪费空间的MyISAMPACK 工具。

如果使用该数据库引擎,会生成三个文件:

.frm:表结构信息

.MYD:数据文件

.MYI:表的索引信息

InnoDB

InnoDB 数据库引擎都是造就 MySQL 灵活性的技术的直接产品,这项技术就是 MYSQL++API。

innodb 与 myisam 区别

1. InnoDB 支持事务,MyISAM 不支持,对于 InnoDB 每一条 SQL 语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条 SQL 语言放在 begin 和 commit 之间,组成一个事务;

2. InnoDB 支持外键,而 MyISAM 不支持。对一个包含外键的 InnoDB 表转为 MYISAM会失败;

3. InnoDB 是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而 MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。

4. InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;

5. Innodb 不支持全文索引,而 MyISAM 支持全文索引,查询效率上 MyISAM 要高;(在MySQL5.7 版本中已经支持全文索引)

如何选择:

1. 是否要支持事务,如果要请选择 innodb,如果不需要可以考虑 MyISAM

2. 如果表中绝大多数都只是读查询,可以考虑 MyISAM,如果既有读写也挺频繁,请使用 InnoDB。

3. 系统奔溃后,MyISAM 恢复起来更困难,能否接受;

4. MySQL5.5 版本开始 Innodb 已经成为 Mysql 的默认引擎(之前是 MyISAM),说明其优势是有目共睹的,如果你不知道用什么,那就用 InnoDB,至少不会差。

修改数据库级引擎

修改 MySQL 的 my.ini 配置文件

C:ProgramDataMySQLMySQL Server 5.7

default-storage-engine=数据库引擎名称

重启 MySQL

458266d53e5e9ed0cbefc18f748800a4.png

修改表级存储引擎

ALTER TBALE tableName engine=InnoDB

查询表的存储引擎

show 

8.理解数据库设计的三大范式

数据库设计范式, 范式有什么作用?

数据库设计对数据的存储性能,还有开发人员对数据的操作都有莫大的关系。所以建立科学的,规范的的数据库是需要满足一些规范的来优化数据数据存储方式。在关系型数据库中这些规范就可以称为范式。

设计关系型数据库时,遵从不同的规范要求,设计出合理的关系型数据库。这些规范被称作范式。越高的范式数据库的 冗余度就越低。

数据库设计范式分类:

数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴德斯科范式(BCNF)、第四范式(4NF)和第五范式(5NF)。

第一范式

第一范式*(确保每列保持原子性)

第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库满足第一范式。

第一范式的合理遵循需要根据系统给的实际需求来确定。

第二范式

第二范式(确保表中的每列都和主键相关)
第二范式在第一范式的基础上更进一层,第二范式需要确保数据库表中每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。

第三范式

第三范式(确保每列都和主键列直接相关,而不是间接相关)

第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值