核心操作 第 14 - 21 章
子查询 subquery
1、处理顺序:从内向外
1 | SELECT cust-name, cust_contact |
2、格式化:分解多行 适当缩进
3、基本思想:将硬编码转换为子查询,减少代码量
-
列必须匹配:SELECT 子句和 WHERE 子句中的列数量相同
-
最常见:用于 WHERE 子句的 IN 操作符和填充计算列
4、相关子查询 correlated subquery
-
使用完全限定列名,指定调用 customers 表中该列名(否则默认自身比较,相当于自检);若非完全限定引用一个具有二义性的列名,将返回错误
1 | WHERE orders.cust_id = customers.cust.id; |
-
注意限制有歧义性的列名
联结表
1、关系
-
主键 primary key:唯一标识
-
外键 foreign key:某个表的一列,包含另一表主键值
2、可伸缩性 scale well:可适应不断增加的工作量并良好运作
3、创建联结(等值联结 equijoin)
1 | SELECT vend_name, prod_name, prod_price |
-
笛卡尔积:由没有联结条件的表关系返回的结果(def 离散)
- 因而需保证所有联结都有 WHERE 子句
- 交叉联结 cross join
4、* 内部联结
1 | SELECT vend_name, prod_name, prod_price |
-
联结条件:使用特定的 ON 子句给出
5、实例:相对子查询优化效率(具体问题具体分析)
1 | SELECT cust_name, cust_contact |
高级联结
1、使用表别名
1 | SELECT Concat(RTrim(vend_name), '(', RTrim(vend_country), ')') AS |
作用:
-
缩短语句
-
允许单条 SELECT 多次使用相同表,如:
1 | SELECT cust_name, cust_contact |
2、自联结
-
作为外部语句来替代从相同表中检索使用的子查询
1 | SELECT p1.prod_id, p1.prod_name |
注:实际问题,效率需具体分析,不一定优于子查询
1 | SELECT p1.prod_id, p1.prod_name |
3、自然联结
-
排除多次出现的列,仅使每个列返回一次(仅选择唯一列)
- 通常对表使用通配符 SELECT *
1 | SELECT c.*, o.order_num, o.order_date, |
4、外部联结 OUTER JOIN (较少使用)
-
联结包含了没有关联行的行
-
类型:左外部联结 右外部联结
- 使用时需要用 RIGHT / LEFT 关键字指定行范围(从右 / 左侧的表中选择所有行)
- mysql 不支持 *= 等一系列简化操作符!
- 可通过颠倒 FROM / WHERE 子句互换使用
- 使用时需要用 RIGHT / LEFT 关键字指定行范围(从右 / 左侧的表中选择所有行)
5、带聚集函数的联结
组合查询
1、并 union:执行多个查询,将结果作为单个查询结果集返回
-
使用情景:单个查询从多个表返回类似数据;对单个表多个查询,按单个返回
-
多个 WHERE 子句的单条查询可以达到相同的作用
-
使用于较为复杂过滤条件
2、UNION 规则
-
由两条及以上 SELECT 语句构成
-
每个查询包含相同表达式
-
列数据类型兼容
3、功能
-
自动去重(默认)
- 返回所有匹配行:UNION ALL
-
与 ORDER BY 排序:必须出现在最后一条 SELECT 语句后
1 | SELECT vend_id, prod_id, prod_price |
全文本搜索
1、支持的数据库引擎:MyISAM(InnoDB 不支持)
2、使用全文本搜索:随数据改变不断索引被搜索的列
-
FULLTEXT ():索引列
- 不要在导入数据使用,降低导入速率
-
Match ():指定被搜索的列
- 使用值必须与 FULLTEXT () 中定义相同
- 多个列索引,其次序与 FULLTEXT () 中保持一致
-
Against ():指定要使用的搜索表达式
- 文本中,靠前的行的给定词等级值高于后继
- 对多个搜索项,包含更多匹配词的行等级值更高
-
索引的搜索速度相当快
3、查询扩展
1 | SELECT note_text |
-
步骤
- 先进行全文本搜索
- 检查匹配行,判定有用词(与给定词相关词)
- 运用有用词和原给定词再次进行全文本搜索
-
文本行数越多,查询扩展结果越好
4、布尔文本搜索
1 | SELECT note_text |
匹配词 heavy,但排除任何包含以 rope 开始的词
-
布尔方式 boolean mode
- 提供:匹配词 排斥词 排列提示 表达式分组 etc.
- 没有定义 FULLTEXT 索引也可使用
-
全文本布尔操作符(P128)
- 如 + /- :包含 / 排除
- < >:包含,并减少 / 增加等级值
- -:取消一个
- *:词尾通配符
5、默认注意事项
-
短词(<=3 个字符的词)从索引中被排除
-
内建的非用词(stopword)被忽略
-
出现行数高于 50% 的词作为非用词忽略
-
少于三行的文本不返回结果
-
忽略词中的单引号
-
中文、日文等不具有词分隔符的语言无法正确返回结果
数据插入 INSERT
1、插入完整行
-
每组值用一对圆括号括起来,以逗号分隔
-
多使用 cust_id 明确插入,可在表结构改变后继续发挥作用
-
INSERT 一般无输出结果
-
必须给出 VALUES 的正确数目;不提供列名则必须对每列给出一个值
1 | INSERT INTO customers(cust_name, |
-
省略列:NULL
- 表的定义中给出默认值:不给定值时使用
-
提高整体性能:用 INSERT LOW_PRIORITY INTO 降低插入的优先级
2、插入多行
-
使用多条 INSERT 语句(可一次性提交)
3、插入检索所得数据
1 | INSERT INTO customers(cust_name, |
其中,列名不一定匹配,仅作顺序填充
-
可包含 WHERE 子句以过滤插入数据
更新和删除数据
1、更新:UPDATE 语句
-
不省略 WHERE 语句,避免更新表中所有行
-
语句组成:要更新的表名 列名及其新值 要更新行的条件
1 | UPDATE IGNORE customers |
-
更新多个列:逗号分隔(最后一行除外)
-
IGNORE 关键字:在发生错误时依旧更新
-
设为 NULL:删除某列值
2、删除:DELETE 语句
-
不省略 WHERE 语句
-
语句组成:要删除的表名 要删除行的条件
- 注:即便删除表中所有行,DELETE 不执行删除表操作
- 删除所有行使用 TRUNCATE TABLE
注:
-
两者使用前最好先用 SELECT 语句测试,保证过滤的记录正确
-
在使用强行引用完整数据库的更删时,仅可操作与其他表无关的数据行
创建和操纵表
1、创建:CREATE TABLE 语句
-
需给出信息:无冲突表名 列名及定义
-
NULL、NOT NULL:允许 / 阻止插入没有值的列
- 空串‘ ’视为一有效值
-
主键可在创建时或创建后定义
-
AUTO_INCREMENT:自动增量
- 每表仅一个列允许,以作为主键值
-
DEFAULT 数值:指定默认值
- 仅可为常量,mysql 不支持函数
-
ENGINE=InnoDB(MyISAM,etc.):指定所用引擎
- 外键不可跨引擎调取
2、更新表:ALTER TABLE
-
常用于定义外键
1 | ALTER TABLE orderitems |
-
更改表步骤
- 用新布局创建新表
- INSERT SELECT 复制数据
- 检验新表,重命名或删除旧表,命名新表
- 重新创建触发器、索引等
3、删除表:DROP TABLE
4、重命名表:RENAME TABLE
1 | RENAME TABLE table1 TO table2 |