本篇知识点
子查询、联结、全文本数据搜索、插入数据
使用子查询
- 案例1 订单存储在两个表中,orders表存储订单编号和客户ID,orderitems存储订单物品;客户信息存储在customers表中,现在需要列出订购商品TNT2的所有客户,步骤如下:
1.检索包含物品TNT2的所有订单编号
SELECT
2.检索前一步骤列出的订单编号的所有客户ID
SELECT
3.检索前一步骤返回的客户ID的客户信息
SELECT
- 用WHERE[1]子句和IN操作符将上述三句查询语句转换为子查询
SELECT
- 案例2 (此处省略表述直接看代码)
作为计算字段使用子查询
SELECT
相关子查询 涉及外部查询的子查询。上句中使用了完全限定列名,任何时候只要列名可能有多义性,就必须使用这种语法(表名列名由一个句点分隔)。
联结表
- 关系数据表通过某些常用的值互相关联
- 外键是某个表中的一列,它包含另一个表的主键值,定义两个表之间的关系
- 创建联结,规定要联结的所有表以及他们如何关联
SELECT
这里的FROM子句列出两个表,由WHERE子句联结,WHERE子句给出联结条件[2]。
SELECT
以上语句没有WHERE,得到的匹配结果不正确
- 内部联结也称等值联结,基于两个表之间的相等测试
SELECT
这里,两个表之间的关系是FROM子句的组成部分,以INNER JOIN指定。这种语法的联结条件用特定的ON子句而不是WHERE子句给出,实际效果相同。
- 联结多个表,SELECT语句中可以联结的表的数目没有限制
SELECT
创建高级联结
- 使用表别名(1.缩短SQL语句 2.单条SELECT语句中多次使用相同的表)
SELECT
这里FROM子句中3个表全都具有别名,并用于WHERE子句,还可用于SELECT的列表及语句的其他部分;表别名只在查询执行中使用,不返回到客户机。
- 案例 发现ID为DTNTR的物品存在问题,需要找到生产ID为DTNTR物品的供应商,然后找出这个供应商生产的其他物品是否也存在问题。
SELECT
- 使用自联结的相同查询
SELECT
products表在FROM子句中出现了两次,使用表别名来对products表引用两次;自联结通常作为外部语句用来替代从相同表中检索数据时使用的子查询语句。
- 自然联结选择那些唯一的列,一般通过对表使用通配符(SELECT*),对所有其他表的列使用明确的子集来完成。
SELECT
- 外部联结联结包含那些在相关表中没有关联行的行。
SELECT
在使用OUTTER JOIN语法时,必须使用RIGHT(从右边的表中选择所有行)或LEFT(从左边的表中选择所有行)关键字。
- 带聚集函数的联结
案例 检索所有客户及每个客户所下的订单数
SELECT
SELECT语句使用INNER JOIN将customers表和orders表相关联,GROUP BY子句按客户分组数据,函数调用COUNT对每个客户的订单计数。
组合查询
- 利用UNION操作符将多条SELECT语句组合成一个结果集
案例 需要价格小于等于5的所有物品的一个列表,且想包括供应商1001和1002生产的所有物品。
SELECT
UNION指示MySQL执行两条SELECT语句,并把输出组合成单个查询结果集;UNION中的每个查询必须包含相同的列、表达式或聚集函数。
- 使用UNION ALL返回所有匹配行,而UNION从结果集中自动去重:
SELECT
- 用ORDER BY子句对UNION组合查询结果排序(仅能使用一条ORDER BY子句)
SELECT
虽然ORDER BY子句似乎只是最后一条SELECT语句的组成部分,但实际上MySQL用它来排序所有SELECT语句返回的所有结果。
UNION和WHERE功能相似,但UNION ALL不能用WHERE替代。
全文本搜索
- MySQL支持几种基本的数据库引擎。两个最常使用的引擎为MyISAM和InnoDB,前者支持全文本搜索,后者不支持。
- 为什么要用全文本搜索?通配符和正则表达式存在:性能耗时、无法明确控制什么匹配什么不匹配、不能提供智能化的选择结果等问题
- 一般在创建表时启用全文本搜索。CREATE TABLE语句接受FULLTEXT子句,给出被索引列的一个逗号分隔的列表
CREATE
MySQL根据子句FULLTEXT(note_text)的指示对它进行索引,也可以指定索引多个列。在定义之后,MySQL自动维护、更新该索引。
不要在导入数据时使用FULLTEXT(费时),应导入数据后再修改表,定义FULLTEXT。
- 索引之后,使用两个函数Match( )和Against( )执行全文本搜索
SELECT
SELECT语句检索单个列note_text,Match(note_text)指示MySQL针对指定的列进行搜索,Against('rabbit')指定词rabbit作为搜索文本。
传递给Match( )的值必须与FULLTEXT( )定义中的相同。若指定多个列,则须列出它们(且次序正确);除非使用BINARY方式,否则不区分大小写。
上句也可用LIKE子句完成:
SELECT
得到结果的次序不同;较之使用LIKE, 使用全文搜索能够返回以文本匹配的良好程度排序的数据。
- 演示排序如何工作
SELECT
ERROR:我这里输出的结果报错;去掉 AS rank正常工作;rank改成其他单词可行。
![3545b1462ac12757698c030e577d7981.png](https://img-blog.csdnimg.cn/img_convert/3545b1462ac12757698c030e577d7981.png)
在SELECT而不是WHERE子句中使用Match( )和Against( ),使得所有行都被返回(因为没有WHERE子句)。Match( )和Against( )用来建立一个计算列,此列包含全文本搜所计算出的等级值(根据行中词的数目、唯一词的数目、整个索引中词的总数以及包含该词的行的数目计算出来)。不含词rabbit的行等级为0。
- 查询扩展(QUERY EXPANSION)用来设法放宽所返回的全文搜索结果的范围。
案例 找出所有提到anvils的注释,只有一个注释包含该词,但你还想找出可能与你搜索有关的其他行,即使它们不包含词anvils。
-
- 首先,进行一个基本的全文本搜索,找出与搜索条件匹配的所有行;
- 其次,MySQL检查这些匹配行并选择所有有用的词;
- 再其次,再次进行全文本搜索,这次不仅使用原来的条件,还使用所有有用的词。
SELECT
- 布尔方式(boolean mode)是MySQL支持全文本搜索到另一种形式,可以提供:
- 要匹配的词;
- 要排斥的词;
- 排列提示
- 表达式分组
- …
- 即使没有FULLTEXT索引也可以使用布尔方式
SELECT
这里虽使用了关键字IN BOOLEAN MODE,但未指定布尔操作符,结果与没有指定布尔方式相同。
SELECT
这一次仍匹配此heavy,但-rope*明确地指示MySQL排除包含rope*(任何以rope开始的词)的行。
![c947260fadd5f32b0dd05c559bb0b786.png](https://img-blog.csdnimg.cn/img_convert/c947260fadd5f32b0dd05c559bb0b786.png)
一些实例
SELECT
这个搜索匹配包含词rabbit和bait的行;
SELECT
没有指定操作符,这个搜索匹配包含rabbit和bait中的至少一个词的行。
SELECT
哲哥搜索匹配短语rabbit bait而不是匹配两个词rabbit和bait。
SELECT
匹配rabbit和caroot,增加前者的等级,降低后者的等级。
SELECT
这个搜索匹配词safe和combination,降低后者的等级。
- 关于全文搜索的重要说明:
- 索引全文本数据时,短词(3个或3个以下字符的词,这个数目可以改)被忽略并从索引中排除;
- MySQL带有一个内建的费用词(stop word)列表,这些词在索引全文数据时被忽略,若需要可覆盖这个列表;
- MySQL规定,如果一个词出现50%以上的行中,则将其作为一个费用此忽略(50%规则不用于IN BOOLEAN MODE);
- 忽略词中单引号
- 不具有词分隔符的语言(日语汉语)不能恰当返回全文本搜索结果
- 仅在MyISAM数据库引擎中支持全文本搜索
插入数据
- 使用INSERT来插入(或添加)行到数据库表,几种方式可使用:
- 插入完整的行
- 插入行的一部分
- 插入多行
- 插入某些查询到结果
- 插入完整的行,要求指定表名和被插入到新行中的值:
INSERT
INSERT语句一般不会产生输出
此例插入一个新客户到customers表,存储到每个表列中的数据在VALUES子句中给出,对每个列必须提供一个值次序填充,若无值,用NULL值。(自动增量列也使用NULL值,MySQL将会自动插入可用值)
更安全的方法:
INSERT
这个例子完成与前一个INSERT语句相同的工作,但在表名后的括号里明确给出列名。在插入行时,MySQL将用VALUES列表中的相应值填入列表中的对应项。这种方法下,即使表的结构改变,语句仍能正确工作,没有给出的列名无需给值。
在INSERT和INTO间添加关键词LOW_PRIORITY,使MySQL降低INSERT语句优先级
INSERT
- 使用多条INSERT语句插入多个行
INSERT
只要每条INSERT语句中的列名(和次序)相同,可用如下组合各语句:
INSERT
其中单条INSERT语句有多组值,每组值用一对圆括号括起来,用逗号分隔;性能更高。
- 插入检索出的数据,将一条SELECT语句的结果插入表中,即INSERT SELECT
INSERT
使用INSERT SELECT从custnew中将所有数据导入customers。SELECT语句从custnew检索出要插入的值,而不是列出它们。若custnew表为空,则没有行被插入,不会产生错误。不要求INSERT和SELECT语句列名匹配,只关心位置(SELECT中的第一列填充表列中指定的第一个列)。
参考
- ^在WHERE子句中使用子查询,应保证SELECT语句具有与WHERE子句中相同数目的列
- ^由没有联结条件的表关系返回的结果为笛卡儿积,检索出的行数是第一个表中的行数乘以第二个表中的行数