MySQL


SELECT子句的顺序

  子句    说明           是否必须使用
SELECT    要返回的列或表达式      是
FROM    从中检索数据的表      仅在从表中选择数据时使用
WHERE   行级过滤            否
GROUP BY   分组说明        仅在按组计算聚集时使用
HAVING    组级过滤           否
ORDER BY   输出排序顺序         否
LIMIT     要检索的行数          否

查询表的关键字顺序

select、from、order by、limit

limit

(limit x)表示返回的结果不多于x行 (limit 5,5;) 表示表示返回从第5行开始的5行,行号从0开始

order by

(order by 列名1,列名2) 表示按列排序,默认为asc升序,可以指定为desc降序

where

(列名 BETWEEN a AND b)  (列名 is NULL)  操作符(AND,OR,IN)其中AND操作符的优先级更高,OR=IN

LIke匹配整列

在使用"_"通配符时,尾空格可能导致匹配错误,"%"没办法匹配NULL值,

如果使用其他操作符能达到相同目的,就不要使用通配符,因为花费的时间更长

尽量不要用在搜索模式的开始处,这样是最慢的

REGEXP正则表达式在列值中匹配,不区分大小写,如果需要,(REGEXP BINARY)

(列名 REGEXP '.000')  "."为特殊字符,可以匹配任意字符

(列名 REGEXP '1000 | 2000')  "|"为"or"的意思  

([123] ton)  为"1 ton"or"2 ton"or"3 ton"  

([^12] ton)  其中[^12]将匹配除"1","2"以外的字符串

[0-9]  将匹配0到9的全部字符

匹配特殊字符需要转义如"\\.","\\-"这些

预定义的字符集:[:alnum:] 任意字母和数字  [:alpha:] 任意字母  [:blank:] 空格和制表  等等

重复字符元:* 无限制个数  + 至少一个  ? 0个或者1个  {n} 指定数目匹配  {n,} 不少于指定数目的匹配  {n,m} 匹配数目的范围,m不大于255

定位元字符:^ 文本的开始  $ 文本的结尾  [[:<:]] 词的开始  [[:>:]] 词的结尾

 创建计算字段以及别名

SELECT Concat(列名,'(',列名,')')  考虑到右侧空格,一般会用RTrim()函数来包裹列名,类似的还有LTrim(),Trim()

通常别名用"AS"关键字连接跟在列名后面,客户机可以按照别名引用列

SELECT 语句可以进行算术计算,SELECT Now(); 可以返回当前时间

使用数据处理函数

文本处理函数

UPPER(s)   将字符串转换为大写
LOWER(s)    将字符串 s 的所有字母变成小写字母
TRIM(s)    去掉字符串 s 开始和结尾处的空格
SUBSTRING_INDEX(s, delimiter, number)   返回从字符串 s 的第 number 个出现的分隔符 delimiter 之后的子串。如果 number 是正数,返回第 number 个字符左边的字符串。如果 number 是负数,返回第(number 的绝对值(从右边数))个字符右边的字符串。

SUBSTRING(s, start, length)   从字符串 s 的 start 位置截取长度为 length 的子字符串
LENGTH(s)    返回字符串s的字符数

mysql> SELECT platformName,Upper(platformName) AS new_data FROM roleinfo ORDER BY platformName;
+---------------+---------------+
| platformName  | new_data      |
+---------------+---------------+
| ainjigame_app | AINJIGAME_APP |
| cinjigame     | CINJIGAME     |
| xinjigame_app | XINJIGAME_APP |
+---------------+---------------+
 
mysql> SELECT SUBSTRING_INDEX('a*b','*',1) AS new_data;
+----------+
| new_data |
+----------+
| a        |
+----------+
1 row in set (0.00 sec)
 
mysql> SELECT SUBSTRING_INDEX('a*b','*',-1)AS new_data;
+----------+
| new_data |
+----------+
| b        |
 
mysql> SELECT SUBSTRING("RUNOOB", 2, 3) AS ExtractString;
+---------------+
| ExtractString |
+---------------+
| UNO           |
+---------------+
 
mysql> SELECT platformName,LENGTH(platformName) AS new_data FROM roleinfo WHERE sex =0;
+--------------+----------+
| platformName | new_data |
+--------------+----------+
| cinjigame    |        9 |
+--------------+----------+

日期和时间函数

AddDate()   增加一个日期(天、周等)
AddTime()    增加一个时间(时、分等)
CurDate()    返回当前日期
CurTime()    返回当前时间
Date()    返回日期时间的日期部分
DateDiff()   计算两个日期之差
DATE_FORMAT(d,f)    按表达式f的要求显示日期d:返回一个格式化的日期或时间串
DAY(d)    返回日期值d的天数部分
DAYOFWEEK(d)    日期 d 今天是星期几:对于一个日期,返回对应的星期几
DAYOFYEAR(d)    计算日期 d 是本年的第几天
HOUR(t)    返回 t 中的小时部分
LOCALTIME()    返回当前日期和时间
NOW()    返回当前日期和时间
MINUTE(t)    返回 t 中的分钟值
MONTHNAME(d)   返回日期当中的月份名称,如 Janyary
MONTH(d)    返回日期d中的月份值,1 到 12
SECOND(t)   返回 t 中的秒钟值
TIMEDIFF(time1, time2)    计算时间差值
WEEK(d)    计算日期 d 是本年的第几个星期,范围是 0 到 53
YEAR(d)    返回一个日期的年份部分
TIME(d)   返回一个日期时间的时间部分

数据经常需要用日期进行过滤。用日期进行过滤时需要注意一些别的问题和使用特殊函的MYSQL函数:

首先需要注意的是MYSQL使用的日期格式。无论你什么时候指定一个日期,不管是插入或更新表值还是使用WHERE子句进行过滤,日期格式必须为yyyy-mm-dd。虽然其他格式也行,但是这是首选格式,因为他排除了多义性。

mysql> SELECT sex,createTime FROM roleinfo WHERE createTime = 1528216525;
+-----+------------+
| sex | createTime |
+-----+------------+
|   1 | 1528216525 |
+-----+------------+

mysql> SELECT sex,createTime FROM roleinfo WHERE createTime = 1528216525;
+-----+------------+
| sex | createTime |
+-----+------------+
| 1 | 1528216525 |
+-----+------------+

mysql> SELECT sex,logintime FROM roleinfo WHERE logintime = "2019-01-25";
+-----+------------+
| sex | logintime |
+-----+------------+
| 1 | 2019-01-25 |
+-----+------------+

mysql> SELECT sex,changetime FROM roleinfo WHERE Date(changetime) = "2019-01-15";
+-----+---------------------+
| sex | changetime |
+-----+---------------------+
| 1 | 2019-01-15 22:40:22 |
+-----+---------------------+

注:
例4中使用了Date()函数:指示MYSQL仅将给出的日期与列中值得日期部分进行比较,而不是将给出的日期与整个列值进行比较。当然也存在一个Time()函数用于值比较日期时间值中的时间部分

MySQL数据库中的Date,DateTime,TimeStamp和Time类型
DATETIME类型用在你需要同时包含日期和时间信息的值时。MySQL检索并且以'YYYY-MM-DD HH:MM:SS'格式显示DATETIME值,支持的范围是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。(“支持”意味着尽管更早的值可能工作,但不能保证他们可以。)

DATE类型用在你仅需要日期值时,没有时间部分。MySQL检索并且以'YYYY-MM-DD'格式显示DATE值,支持的范围是'1000-01-01'到'9999-12-31'。

TIMESTAMP列类型提供一种类型,你可以使用它自动地用当前的日期和时间标记INSERT或UPDATE的操作。

TIME数据类型表示一天中的时间。MySQL检索并且以"HH:MM:SS"格式显示TIME值。支持的范围是'00:00:00'到'23:59:59'。

汇总数据(自动忽略NULL值)

AVG()   返回某列的平均值,AVG( DISTINCT level),可以指定为计算不同值的行,也可以不指定(ALL)
COUNT() 返回某列的行数
MAX()  返回某列的最大值
MIN()   返回某列的最小值
SUM()    返回某列值之和

分组数据

依据(GROUP BY 列名)  使用了GROUP BY,就不必指定要计算和估值的每个组了,系统会自动完成。GROUP BY子句指示指示MySQL分组数据,然后都每个组而不是整个结果集进行聚集

关于GROUP BY使用,请注意以下规则:

1、GROUP BY子句可以包含任意数目的列,这使得可以对分组进行嵌套,为数据分组提供更细致的控制

2、如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上进行汇总。即:在建立分组时,指定的所有列都一起计算(所以不能从个别列取回数据)

3、GROUP BY子句中列出的每个列都必须是检索列或有效的表达式(但不能是聚集函数),如果在select中使用表达式,则必须在GROUP BY子句中指定相同的表达式(不能使用别名)

4、除了聚集计算语句外,select语句中的每个列都必须在GROUP BY子句中给出

5、如果分组列中具有null值,则null将作为一个分组返回(如果列中有多行null值,他们将分为一组)

6、GROUP BY子句必须出现在WHERE子句之后,ORBER BY子句之前

PS:使用with rollup关键字,可以得到每个分组以及每个分组汇总级别(针对每个分组)的值。

过滤分组

1、除了使用GROUP BY分组数据外,MYSQL还允许过滤分组,规定包括哪些分组,排除哪些分组。为了得出这种数据,必须基于完整的分组而不是个别的行进行过滤

2、在进行分组过滤时不能使用WHERE关键字,因为WHERE过滤指定的是行而不是分组,事实上WHERE没有分组的概念。为此MYSQL提供了另外的子句,那就是HAVING子句。HAVING非常类似于WHERE,唯一的区别是WHERE过滤行,而HAVING过滤分组

注:一般使用group by子句时,也应该给出order by子句,这是保证数据正确排序的唯一方法(千万不要依赖group by排序数据)

分组数据
分组允许把数据分为多个逻辑组,以便能对每个组进行聚集计算


创建分组
在MySQL中,分组是在SELECT语句中的GROUP BY子句中建立的

例12:

mysql> SELECT total_price,count(*) AS new_price FROM price GROUP BY total_price;
+-------------+-----------+
| total_price | new_price |
+-------------+-----------+
|        1002 |         2 |
|        1003 |         4 |
|        1004 |         2 |
|        1005 |         2 |
+-------------+-----------+
注:
1、上面例子中指定了两个列,total_price为目标列(用于分组的列),new_price为计算字段(由count(*)函数建立)。GROUP BY子句指示MYSQL按total_price排序并分组数据,这导致对每个total_price计算而不是对整个表(列)计算

2、因为使用了GROUP BY,就不必指定要计算和估值的每个组了,系统会自动完成。GROUP BY子句指示指示MySQL分组数据,然后都每个组而不是整个结果集进行聚集


关于GROUP BY使用,请注意以下规则:
1、GROUP BY子句可以包含任意数目的列,这使得可以对分组进行嵌套,为数据分组提供更细致的控制

2、如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上进行汇总。即:在建立分组时,指定的所有列都一起计算(所以不能从个别列取回数据)

3、GROUP BY子句中列出的每个列都必须是检索列或有效的表达式(但不能是聚集函数),如果在select中使用表达式,则必须在GROUP BY子句中指定相同的表达式(不能使用别名)

4、除了聚集计算语句外,select语句中的每个列都必须在GROUP BY子句中给出

5、如果分组列中具有null值,则null将作为一个分组返回(如果列中有多行null值,他们将分为一组)

6、GROUP BY子句必须出现在WHERE子句之后,ORBER BY子句之前

PS:使用with rollup关键字,可以得到每个分组以及每个分组汇总级别(针对每个分组)的值。

 

过滤分组
1、除了使用GROUP BY分组数据外,MYSQL还允许过滤分组,规定包括哪些分组,排除哪些分组。为了得出这种数据,必须基于完整的分组而不是个别的行进行过滤

2、在进行分组过滤时不能使用WHERE关键字,因为WHERE过滤指定的是行而不是分组,事实上WHERE没有分组的概念。为此MYSQL提供了另外的子句,那就是HAVING子句。HAVING非常类似于WHERE,唯一的区别是WHERE过滤行,而HAVING过滤分组

例13:

mysql>  SELECT total_price,count(*) AS new_price FROM price GROUP BY total_price HAVING count(*)>= 3;
+-------------+-----------+
| total_price | new_price |
+-------------+-----------+
|        1003 |         4 |
+-------------+-----------+
注:
这条SQL语句中的having子句过滤出count(*)>=3(3个以上的分组)的那些分组


HAVING和WHERE的区别:
1、WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤;where排除的行不包括在分组中(这可能会改变计算值,从而影响having子句中基于这些值过滤掉的分组)

2、WHERE过滤行,而HAVING过滤分组


同时使用HAVING和WHERE
例14:

mysql> SELECT total_price,count(*) AS new_price FROM price WHERE current_price=8 GROUP BY total_price;
+-------------+-----------+
| total_price | new_price |
+-------------+-----------+
|        1003 |         4 |
|        1004 |         1 |
+-------------+-----------+
例14_1:

mysql> SELECT total_price,count(*) AS new_price FROM price WHERE current_price=8 GROUP BY total_price HAVING count(*)>= 2;
+-------------+-----------+
| total_price | new_price |
+-------------+-----------+
|        1003 |         4 |
+-------------+-----------+
注:
WHERE子句过滤出current_price=8的行,然后按照total_price分组数据,HAVING子句再过滤出计数大于等于2的分组


group by和order by的区别:
虽然GROUP BY和ORDER BY经常完成相同的 工作,但它们之间有很大的不同

ORDER BY                GROUP BY
排序产生的输出    分组行,但输出可能不是分组的顺序
任意列都可以使用,甚至非选择的列也可以使用    只可使用选择列或表达式列,而且必须使用每个选择列表达式
不一定需要      如果与聚集函数一起使用列(或表达式),则必须使用
注:一般使用group by子句时,也应该给出order by子句,这是保证数据正确排序的唯一方法(千万不要依赖group by排序数据)

例15:

mysql> SELECT total_price,SUM(current_price) AS new_price FROM price GROUP BY total_price;
+-------------+-----------+
| total_price | new_price |
+-------------+-----------+
|        1002 |        10 |
|        1003 |        39 |
|        1004 |        13 |
|        1005 |         6 |
+-------------+-----------+
例15_1:

mysql> SELECT total_price,SUM(current_price) AS new_price FROM price GROUP BY total_price HAVING SUM(current_price) >= 6 ORDER BY new_price;
+-------------+-----------+
| total_price | new_price |
+-------------+-----------+
|        1005 |         6 |
|        1002 |        10 |
|        1004 |        13 |
|        1003 |        39 |
+-------------+-----------+
 
————————————————
版权声明:本文为CSDN博主「不怕猫的耗子A」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_39314932/article/details/86563487

 使用子查询

使用子查询作为条件过滤

应当适当缩进一便于阅读,而且子查询的select应当与where语句的列匹配

作为计算字段使用子查询

此时的子查询对检索出来的数据执行一次

表联结

记得过滤语句,否则会出现笛卡尔积

联结表时首选 (from 表名 INNER JOIN 表名 on 过滤条件)  而不是 (from 表名,表名  where 过滤条件)

自联结

将同一个表取两个别名:(from 表名 AS pi,表名 AS p2  where 过滤条件)

外部联结[RIGHT|LEFT]必须选择一个

[RIGHT|LEFT] OUTER JOIN  right以及left决定返回右边或者左边的全部列,另一边没有与之匹配的列时用NULL代替

使用带聚集函数的联结

 可以将聚集函数放在select语句里面

组合查询

使用UNION将需要的select语句连接,需要有同样的列,一般来说,UNION的组合查询一般可以用(where or)语句代替。

有一种情况例外,当需要满足条件的语句都出现时,(where or)语句会自动删除一样的行,使用(UNION ALL)则不会

全文本搜索

最经常使用的引擎(ENGINE=MyISAM)支持,(ENGINE=InnoDB)不支持

如果需要开启全文本搜索,一般需要在create表的时候使用FULLTEXT(列名,列名)的方式,或者在稍后指定(这种情况下所有已有的数据必须立即索引),列名可不唯一,定义之后MySQL会自动维护该索引,在CRU时自动更新

使用方式(where Match(列名) Against('需要匹配的片段'))

此方式对比于like关键字的优势在于返回的数据会有理想的优先级,并且速度上快于like

使用查询扩展

(where Match(列名) Against('需要匹配的片段') WITH QUERY EXPANSION)此方式不仅会返回包含的关键字,还会返回包含关键字的语句的很可能相关的语句

布尔文本搜索

即使没有定义FULLTEXT索引,也可以使用,但这是一种很缓慢的操作,其性能将随着数据量的增加而降低

(where Match(列名) Against('需要匹配的片段') IN BOOLEAN MODE)

布尔操作符 说明
+ 包含,词必须存在
- 排除,词必须不存在
> 包含,并且增加等级值
< 包含,并且减小等级值
() 把词组成子表达式(允许这些子表达式作为一个组被包含、排除、排列等)
~ 取消一个词的排序值
* 词尾的通配符
“ ” 定义一个短语(与单个词的列表不一样,它匹配整个短语,以便包含或排除这个短语)

全文本搜索的注意事项

在索引全文本数据时,短语被忽略且从索引中排除。短语定义为具有3个或3个以下字符的词。可以修改。
MySQL带有一个内建的非用词(stopWord)列表,这些词在索引全文本数据时被忽略。可以覆盖这个列表。
许多词的出现频率很高,搜索它们会返回太多的结果,意义不大,因此,MySQL规定了一个50%规则:如果一个词出现在50%以上的行中,则将它作为一个非用词忽略。(50%规则不适用于布尔文本搜索)
如果表中的行数少于3行,则全文本搜索不返回任何结果,因为每个词都不出现或者出现在50%以上的行中。
忽略词中的单引号,如don’t的索引为dont。
不具有词分隔符的语言(如:汉语和日语),不能恰当的返回全文本搜索结果。
仅在MyISAM数据库引擎中支持全文本搜索。

表的CURD

插入数据

通常来说,插入数据是比较耗时的,如果需要,可以使用(INSERT LOW_PRIORITY INTO)来降低优先级,同时也适用于UPDATE和DELETE语句

插入语句还可以和select语句一起使用如:

INSERT INTO 表名(列名,.......)SELECT(列名,.......)FROM 表名;

同时select语句也可以包含where语句,需要注意的是,此时的列名的个数需要一样,且MySQL不关心列名的顺序

更新语句

一次更新多条语句时,如果一行出现错误,则会回滚到之前的状态。如果不想回滚,希望可以继续更新,可以使用IGNORE关键字,(UPDATE IGNORE 表名; )

删除语句

不带where语句的delete关键字会删除表的所有行,并不会删除表,如果确实想删除表的所有行,应该使用(TRUNCATE TABLE 表名;)速度会更快

DELETE 是 DML 类型的语句;TRUNCATE 是 DDL 类型的语句。它们都用来清空表中的数据。
DELETE 是逐行一条一条删除记录的;TRUNCATE 则是直接删除原来的表,再重新创建一个一模一样的新表,而不是逐行删除表中的数据,执行数据比 DELETE 快。因此需要删除表中全部的数据行时,尽量使用 TRUNCATE 语句, 可以缩短执行时间。
DELETE 删除数据后,配合事件回滚可以找回数据;TRUNCATE 不支持事务的回滚,数据删除后无法找回。
DELETE 删除数据后,系统不会重新设置自增字段的计数器;TRUNCATE 清空表记录后,系统会重新设置自增字段的计数器。
DELETE 的使用范围更广,因为它可以通过 WHERE 子句指定条件来删除部分数据;而 TRUNCATE 不支持 WHERE 子句,只能删除整体。
DELETE 会返回删除数据的行数,但是 TRUNCATE 只会返回 0,没有任何意义。
总结
当不需要该表时,用 DROP;当仍要保留该表,但要删除所有记录时,用 TRUNCATE;当要删除部分记录时,用 DELETE。

创建表

如果想在一个表不存在时创建它,应该在表名后给出IF NOT EXISTS

使用AUTO_INCREMENT, 
一个表只允许一个AUTO_INCREMENT的列,且必须被索引(比如通过它成为主键)
如果想覆盖AUTO_INCREMENT,只需要指定一个表中没有的值即可
通常你不知道AUTO_INCREMENT生成的值是多少,如果需要,可以使用(select last_insert_id();)此语句返回最后一个AUTO_INCREMENT值

表的约束

外键约束

事务

通常是默认开启事务的,所以不会回滚

事务保证了数据的一致性

  • 要么都成功
  • 要么都失败

对于没有开启自动提交的数据,是可以回滚的,一旦提交了之后,就不可以回滚,体现了MySQL的持久性

自动提交:@@autocommit=1;

手动提交:commit;

回滚:rollback;

开启事务的两种方式

  1. begin;
  2. start transaction;

事务的四大特征:

  • A 原子性:事务是最小的单位,不可以在分割。

  • C 一致性:事务要求,同一事务中的sql语句,必须保证同时成功或者同时失败。

  • I 隔离性:事务1和事务2之间是具有隔离性的。

  • D 持久性:事务一旦结束(commit,rollback),就不可以返回。事务开启:

修改默认提交

  • 1.set autocommit=0;
  • 2. begin;
  • 3. start transaction;
事务手动提交:commit;
事务手动回滚:rollback;

事务的隔离性

事务的隔离性越高,则性能越差,系统默认的隔离级别是REPEATABLE READ

查看系统隔离性

 select @@global.transaction_isolation;

查看会话隔离性

 select @@transaction_isolation;

修改系统隔离性

set global transaction isolation level read committed;

 1:read uncommitted

会出现脏读现象,即可以读到还未被提交的事务,如果未被提交的事务rollback,会发生不可预料的事情,应当避免发生脏读的发生

2:read committed

会出现不可重复读现象,即事务a对于事务b的insert语句提交之后,在事务a做操作的时候,读取不到事务b的insert数据

3:repeatable read

会出现幻读现象,已经被事务a提交的数据,事务b用select检索不出来,但又没办法insert

4:serializable

会出现超时的情况,当事务a开启并且还没有commit的时候,如果需要insert,这会造成等待,如果时间久,则可以失败

存储过程

很多公司禁止使用

参数类型

  • in  有参数默认
  • out  有返回
  • inout  两个的结合

 

索引