1. 数据准备:
incorrect string value 错误时:
建表前写 SET NAMES utf8;
建表后写 ALTER TABLES tdb_goods CHARACTER SET utf8;
录入数据前重启MySQL一次
SELECT显示数据时如果是乱码: SET NAMES gbk; 在客户端以gbk的编码显示数据,只影响客户端显示,并不影响真实的数据表中的数据
2. 子查询(SubQuery):是指出现在其他SQL语句内的SELECT子句
e.g. SELECT * FROM t1 WHERE col1= (SELECT col2 FROM t2);
其中 SELECT * FROM t1: 称为 Outer Query / Outer Statement;
SELECT col2 FROM t2: 称为 SubQuery。
!!!注意:
子查询指嵌套在查询内部,且必须始终出现在圆括号内;
子查询可以包含多个关键字或条件,如 DISTINCT, GROUP BY, ORDER BY, LIMIT,函数等;
子查询的外层查询(外层查询:我们所知道的所有SQL(结构化查询语言)命令的统称)可以是 SELECT, INSERT, UPDATE, DELETE, SET 或 DO。
子查询可以返回标量、一行、一列或子查询。
子查询的结果可以在其他的SQL语句,如INSERT, UPDATE 以及SELECT等语句中使用。
(1) 使用比较运算符(= < > <= >= <> != <=>)的子查询:
语法结构: operand comparison_operator (subquery)
e.g.查找商品的平均价格:
对数字做四舍五入,并保留到小数点后两位:
看看哪些商品的价格大于等于5636.36
查找超级本类型的商品的价格:
子查询返回多个结果时: 用ANY, SOME 或 ALL 修饰的比较运算符:(ANY, SOME等价,符合其中一个就行;ALL 符合全部)
operand comparison_operator ANY (subquery)
operand comparison_operator SOME (subquery)
operand comparison_operator ALL (subquery)
原则:
ANY | SOME | ALL | |
>, >= | 最小值 | 最小值 | 最大值 |
<, <= | 最大值 | 最大值 | 最小值 |
= | 任意值 | 任意值 | |
<>, != | 任意值 |
e.g.查询哪些商品的价格大于超级本的价格:
(2)由[NOT] IN/EXISTS引发的子查询:
(a) IN 或 NOT IN,语法结构: operand comparison_operator [NOT] IN (subquery)
= ANY 运算符与IN等效
!= ALL 或<> ALL运算符与NOT IN 等效
(b) EXISTS 或 NOT EXISTS: 如果子查询返回任何行,EXISTS 将返回TRUE, 否则为FALSE。
(3) INSERT... SET... 与INSERT... VALUES...的区别在于 INSERT ... SET...可以使用子查询:
e.g. SET a字段=(Subquery)
INSERT ... SELECT: 将查询结果写入数据表:
INSERT [INTO] tbl_name [ (col_name,...) ] SELECT...
参照分类表(tdb_goods_cates) 更新商品表(tdb_goods),这就需要多表的更新:
3. 多表更新(参照另外的表来更新本表内的记录):
方法一: 建立一个新的表,INSERT... SELECT 插入记录,UPDATE... join
UPDATE table_references
SET col_name1= {expr | DEFAULT}
[ , col_name2={expr|DEFAULT]...
[WHERE where_condition]
方法二: 多表更新的一步到位: CREATE... SELECT ,即将方法一种创建数据表和查询写入记录的步骤两者合为一个命令,更为便捷。
创建数据表的同时将查询结果写入到数据表:
CREATE TABLE [IF NOT EXISTS] tbl_name
[ (create_definition,...)]
select_statement
参照品牌表更新商品表:
注意,即使我们UPDATE之后,tdb_goods表中goods_cate 和 brand_name的类型仍然是VARCHAR(40)
尽量去修改表的结构
既要改字段的名字又要改数据类型 --> 利用CHANGE
至此,我们才给数据表做了减肥的操作。(即使后续有重复的,数字所占的字节数要远小于字符所占的字节数)
在创建外键时不一定非要加FOREIGN KEY(物理外键);我们也可以使用上述形式的外键(事实的外键),且这种形式较为常用。
由于没有物理外键,上图中即使tdb_goods_cates中没有cate_id=12,我们仍然可以在tdb_goods中插入一条cate_id为12的记录
当我们想要把记录的详细信息展示给客户看时,应该显示明确的商品的品牌、商品的分类,此时就需要这几张表的协作,这就需要连接来实现,操作解释如下:
4. 连接 (join)
MySQL在SELECT语句、多表更新、多表删除语句中都支持JOIN操作
(1) 连接的语法结构:
table_reference (a表)
{ [INNER | CROSS] JOIN | {LEFT|RIGHT} [OUTER] JOIN}
table_reference (b表)
ON conditional_expr (连接条件)
(2)连接类型:
(a) INNER JOIN, 内连接: 在MySQL中, JOIN, CROSS JOIN 和 INNER JOIN 是等价的, 一般习惯使用INNER JOIN
内连接:显示左表和右表中交集的部分、公共的部分,即仅显示符合连接条件的记录
(b) LEFT [OUTER] JOIN, 左外连接
显示左表的全部记录及右表符合连接条件的记录
右表中没有符合条件的记录则显示为NULL
(c) RIGHT [OUTER] JOIN, 右外连接
显示右表的全部记录以及左表符合连接条件的记录,左表中不符合连接条件的显示为NULL
(3) 数据表参照:
table_reference
tbl_name [ [AS] alias ] | table_subquery [AS] alias
数据表可以使用tbl_name AS alias_name 或 tbl_name alias_name赋予别名 (两张不同的表中可能存在相同的字段,为了区分)
table_subquery可以作为子查询使用在FROM子句中,这样的子查询必须为其赋予别名
(4) 连接条件: 使用ON关键字来设定连接条件,也可以使用WHERE来代替
通常使用ON关键字来设定连接条件,使用WHERE关键字进行结果集记录的过滤。
(5) 多表连接:
【表的连接其实可以说是外键的逆向操作,外键把数据分开存储,连接又将多张表联系在一起】
(6) 关于连接的几点说明:
(a)
A LEFT JOIN B join_condition (左外连接,右外连接同理)
数据表B的结果集依赖数据表A ;(数据表A中有的记录在B表中才显示出来,否则B表中记录不能显示)
数据表A的结果集根据左连接条件依赖所有数据表(B表除外);
左外连接条件决定如何检索数据表B(在没有指定WHERE条件的情况下);(A表决定B表)
如果数据表A的某条记录符合WHERE条件,但是在数据表B不存在符合连接条件的记录,将生成一个所有列为空(NULL)的额外的B行。
(b) 如果使用内连接查找的记录在连接数据表中不存在,并且在WHERE子句中尝试以下操作: col_name IS NULL时, 如果col_name被定义为NOT NULL, MySQL将在找到符合连接条件的记录后停止搜索更多的行
[参考链接] https://www.imooc.com/learn/122