MySql必知必会整理的读书笔记

  • 数据库就是以一个以某种有组织的方式存储的数据集合

MySql主键规则

  • 不更新主键的值
  • 不重用主键列的值
  • 不在主键列中使用可能会更改的值

  • SHOW TABLES; 获得一个数据库内的表的列表
  • 如果使用 DISTINCT 关键字,它必须直接放在列名的前面

  • LIMIT 5 表示MySql返回不多于5行

  • LIMIT 5,5 指示MySql返回从行5开始的5行
    第一个数为开始位置,第二个数为要检索的行数

  • 为了按多个列排序,只要指定列名,列名之间用逗号分开即可。

  • 在多个列上进行降序 如果想在多个列上进行降序,必须对每个列指定DESC关键字

  • OR 操作符指示MySql 检索匹配任一条件的行

  • SQL像多数语言一样在处理OR操作符前,优先处理AND操作符

  • 在where子句中使用圆括号任何时候使用具有AND和OR操作符的WHERE子句,都应该使用圆括号明确的分组操作符。不要过分依赖默认计算次序,即使它确实是你想要的东西也是如此。

  • in的操作符一般比OR操作符更快

  • in 的最大优点是可以包含其他的SELECT语句,使得能够更动态的建立WHERE字句

  • IN WHERE 字句用来指定要匹配值的清单的关键字,功能与OR相当

  • 模糊查询 %anvil%表示匹配任何位置包含文本anvil的值,而不论它之前或之后出现什么字符。

  • _ 下划线只匹配单个字符而不是多个字符

  • 通配符搜索的处理一般要比前面讨论的其他搜索所花的时间更长

  • 在确实需要使用通配符时,除非绝对有必要,否则不要把它们用在搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起来最慢

  • REGEXP 正则表达式
    SELECT from products WHERE prod_name REGEXP '.000' ORDER BY prod_name
    匹配任意一个含义000的字符

  • LIKE 与 REGEXP区别
    LIKE匹配整个列.如果被匹配的文本在列值中出现,LIKE将不会找到它,相应的行也不会被返回(除非使用通配符)。而REGEXP在列值内进行匹配,如果被匹配的文本在列值中出现,REGEXP将会找到它,相应的行将被返回

  • MySql正则表达式不区分大小写(3.23.4),为了区分大小写可使用BINARY关键字

  • 正则表达式进行 OR匹配
    select prod_name from where prod_name REGEXP '1000|2000' ORDER BY prod_name
    表示匹配其中之一,因此1000和2000都匹配返回

  • [123] 表示匹配 1或者2或者3,这是or的升级版
    [^123]匹配除含有 1或者2或者3的

-拼接: 将值联接到一起构成单个值
select repairshop_name, CONCAT(repairshop_name,repairshop_code), repairshop_code from t_ops_insuredorder;
将两个字段的值连接在一起

  • select也可以用来进行计算
    SELECT 3*2 将返回6

关于MySql中的函数

如果你决定使用函数,应该保证做好代码注释,以便以后你(或其他人)能确切地知道编写SQL代码的含义
MySql中实现支持一下函数

    1. 使用处理文本串(如删除或填充值,转换值为大写或者小写)的文本函数
    1. 用于在数值数据上进行算术操作(如返回绝对值,进行代数)的数值函数
    1. 用于处理日期和时间值并从这些值中提取特定成分(例如,返回两个日期之差,检查日期有效性)的日期时间函数
      DATE_FORMAt(date,format)时间按格式转化函数

SELECT created_at,repairshop_name from t_ops_insuredorder where DATE(created_at) = '2016-12-19'
针对日期处理查询条件函数

    1. 返回DBMS正使用的特殊信息(如返回用户登录信息,检查版本细节)的系统函数

Mysql中的聚集函数

运行在组上,计算和返回单个值的函数
AVG() 返回某列的平均值
COUNT() 返回某列的行数

  • 使用 count(*)对表中行的数目进行计数,不管表中包含的是空值(null)还是非空值
  • 使用COUNT(column)对特定列中具有值的行进行计算,忽略NULL值

MAX() 返回某列的最大值
MIN() 返回某列的最小值
SUM() 返回某列值之和


MySql中的分组函数

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

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

  • gruop by子句中列出的每个列必须是检索列或有效的表达式(但是不能是聚集函数),如果在SELECT中使用表达式,则必须在GROUP BY子句中给出

  • 如果分组中有NULL值,则 NULL将作为一个分组返回。如果列中有多行NULL值,则将他们分为一组
  • gruop by 必须出现在 where子句后,order by子句之前

过滤分组

对分组进行过滤使用 HAVING

  • HAVING支持所有的WHERE操作符

group by不能给分组的数据进行排序,所以必须是用 order by

SELECT order_num,SUM(quantity*item_price)
AS ordertotal
FROM orderitems
GROUP BY order_num
HAVING SUM(quantity*item_price) >= 50

SELECT子句顺序

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

子查询

SELECT
    *
FROM
    vg_user_detail
WHERE
    user_id IN (
        SELECT
            COUNT(user_id) user_id
        FROM
            vg_user_info
        GROUP BY
            tenant_id
        ORDER BY
            user_id
    )

使用子查询时候必须保证SELECT语句具有与WHERE子句中相同数目的列

作为计算字段使用子查询

SELECT department_id,
(SELECT COUNT(user_id) 
FROM vg_user_info
WHERE vg_user_detail.user_id = vg_user_info.user_id
) userId 
from vg_user_detail
GROUP BY department_id
HAVING department_id > 0

注意 在子查询中from使用了完全限定列名避免歧义


联结表

两种写法: 关于等值联结

  • 1 .
SELECT vi.user_id,vi.user_name,vd.staff_name
from vg_user_info vi,vg_user_detail vd
where vi.user_id = vd.user_id
  • 2 .
SELECT vf.user_id,vf.user_name,vd.staff_name
from vg_user_info vf JOIN vg_user_detail vd
ON vf.user_id = vd.user_id
内联结
SELECT vf.user_id,vf.user_name,vd.staff_name
from vg_user_info vf INNER JOIN vg_user_detail vd
on vf.user_id = vd.user_id 
外部联结

左联结

SELECT column_name(s)
FROM table_name1
LEFT JOIN table_name2 
ON table_name1.column_name=table_name2.column_name

LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行。
显示左边所有的行,右边没有的显示null

有联结

RIGHT JOIN
显示右边所有的行,左边没有的显示null


组合查询

适用场景

  • 在单个查询中从不同的表返回类似的结构
  • 对单个表执行多个查询,按单个查询返回数据
SELECT position_name,user_id
from vg_user_info vf where tenant_id = -1
UNION 
SELECT position_name,user_id
from vg_user_info where position_name = '人力资源经理'

注意事项:

  • union中的每个查询必须包含相同的列、表达式或聚合函数(每个列不需要以相同的次序出现)

  • 列数据类型必须完全兼容

union查询结果集中自动去掉重复的行
如果想取得所有的行则用 UNION ALL


**全文本索引只在 MyISAM数据引擎中使用

SELECT *
from vg_user_info vf 
WHERE MATCH(user_id) AGAINST ("abc")

match匹配列, AGSINST搜索含有abc的列


视图

  • 创建视图 view
    CREATE VIEW 视图名 AS 子查询虚表

**视图为虚拟的表. 它们包含的不是数据而是根据需要检索数据的查询。视图提供了一种MySql的SELECT 语句层次的封装,可用来简化数据的处理以及重新格式化数据或保护基础数据


存储过程

就是为了以后的使用而保存的一条或多条MySql语句的集合。可将其视为批文件,虽然他们的作用不仅限于批处理

  • 执行存储过程
    MySql 执行存储过程称为调用,使用 CALL命令

CALL productpricing(@pricelow,@pricehigh,@priceaverage);

  • 创建存储过程
    CREATE PROCEDURE productpricing() BEGIN SELECT Avg(prod_price) AS price average FROM products; END;

  • 删除存储过程
    DROP PROCEDURE productpricing;

  • 变量
    内存中一个特定的位置,用来存储临时数据。
  CREATE PROCEDURE productpricing(
     OUT p1 DECIMAL(8,2),
     OUT ph DECIMAL(8,2),
     OUT pa DECIMAL(8,2)
 
  )
 BEGIN 
  SELECT Min(prod_price)
  INTO p1
  from products
  SELECT Mac(prod_price)
  from products
  SELECT Avg(prod_price)
  INTO pa
  from products;
 END

关键字 OUT 指出相应的参数用来从存储过程传出一个值(返回给调用者).
MySql支持 IN(传递给存储过程)、OUT(对存储过程传入和传出)类型的参数

为调用此存储过程必须使用3个变量

CALL producttpricing(
                    @pricelow,
                    @pricehigh
                    @priceaverage
 );

为了显示值

 select @priceaverage;

下面这个例子使用 INOUT参数。
ordertotal接受订单号并返回该订单的合计

 CREATE PROCEDURE ordertotal(
     IN onnumber INT,
     OUT otatal DECIMAL(8,2)
                            )
 BEGIN
     SELECT Sum(item_price*quantity)
     FROM orderitems
     WHERE order_num = onnumber
     INTO ototal;
     END;

分析:
onnumber定义为IN,因为订单号被传入存储过程。otatal定位为OUT,因为要从存储过程返回合计。SELECT 语句使用这两个参数,WHERE子句使用onumber选择正确的行,INTO使用ototal存储计算出来的合计

为调用这个新存储过程,可以使用一下语句
CALL ordertotal (20005,@total)
必须给ordertotal传递两个参数:第一个参数为订单号,第二个参数为包含计算出来合计的变量名。
为了显示次合计
select @total

为了得到一个订单的合计显示,需要再次调用存储过程,然后重新显示变量。

CALL ordertotal(20009,@total)
SELECT @total

游标

应用场景:
有时需要在检索出来的行中前进或后退一行或多行。
游标主要用于交互式应用,其中用户需要滚动屏幕上的数据,并对数据进行浏览或作出更改
游标只能用于存储过程(和函数)

关于游标的注意事项:

  • 在使用游标前,必须先声明(定义)它。
    这个过程实际上没有检索数据,它只是定义要使用的SELECT 语句

  • 一旦声明后,必须打开游标以供使用。这个过程用前面定义的SELECT 语句把数据检索出来

  • 对于填有数据的游标,根据需要去除(检索)各行

  • 在结束游标使用时,必须关闭游标

创建游标
CREATE PROCEDURE processorders()
BEGIN 
   DECLARE ordernumbers CURSOR
   FOR 
   SELECT odernum FROM orders;
   END;

打开或关闭游标
游标使用 OPEN CURSOR语句来打开

  • 打开:
    OPEN ordernumbers;
  • 关闭
    CLOSE ordernumbers;

隐含关闭 如果不明确关闭游标,MySql将会在到达END语句时自动关闭它

例子:

CREATE procedure processorders()
BEGIN
   -- 定义一个游标
   DECLARE ordernumbers CURSOR
   FOR 
   SELECT irder_num FROM orders;
   
   --打开游标
   OPEN ordernumbers
   
   --检索游标
   FETCH ordernumbers INTO o;
   
   --关闭游标
   CLOSE ordernumbers;
   
   END;

触发器

应用场景: 如果你想要某条语句(或某些语句)在事件发生时自动执行
在每个表发生更改时自动处理

  • DELETE
  • UPDATE
  • INSERT
    操作可使用触发器

创建触发器需要提供的信息:

  • 唯一的触发器名;
  • 触发器关联的表
  • 触发器应该响应的活动(DELETE、INSERT或UPDATE);
  • 触发器何时执行

保持每个触发器的名称在每个表中的唯一

CREATE TRIGGER newproduct AFTER INSERT ON
products FOR EACH ROW SELECT 'Product added';

创建一个名为 newproduct的触发器 在INSERT语句成功执行后执行。这个触发器还指定 FOR EACH ROW 因此代码对每个差入行执行

触发器仅仅支持表 且每个表最多支持6个触发器

CREATE TRIGGER neworder AFTER INSERT ON
orders
FOR EACH ROW SELECT NEW.order_num;

生成一个neworder触发器,再插入一个新的订单并保存到order表时,MySql生成一个新的订单号并保存到order_num取得这个值并返回它


事务管理

  • 保留点: 指事务处理中设置的临时占位符

例子:

  SELECT * from ordertotals;
  START TRANSACTION;
  DELETE FROM ordertotals;
  ROLLBACK;
  SELECT * FROM ordertotals;

使用保留点
SAVEPOINT delete1;

更改默认的提交行为
SET commint 0;


管理用户

  • MySql中有一张 user表 用户管理所有的用户
CREATE USER ben IDENTIFIED BY 'p@$$wOrd';

重命名一个表

RENAME USER ben TO bforta;

删除一个表

DROP USER bforta

授予权限

GRANT SELECT ON crashcourse.* TO beforta;

表示: 用户bforta对crashcourse数据库中的所有数据具有只读访问权限

取消用户权限

REVOKE SELECT ON crashcourse.* FRO M beforta

两个命令在几个层次上的控制

  • 整个服务器,使用GRANT ALL和 REVOKE ALL;
  • 整个数据库,使用ON database;
  • 特定的表,使用ON database.table
  • 特定的列, 特定的存储过程。

备份数据


数据库维护

  • ANALYZE TABLE orders;
  • CHECK TABLE 快速发现和修复问题

查看日志文件

  • 错误日志: data目录下 hostname.err
  • 查询日志:hostname.log
  • 二进制日志:hostname-bin
  • 缓慢查询日志: hostname-slow.log

改善性能

  • 查看当前设置 SHOW VARIABLES
    SHOW STATUS

  • 查看当前所有线程ID和活动时间 SHOW PROCESS LIST

  • 你的SELECT语句中有一系列复杂的OR条件吗?通过使用多条SELECT 语句和连接它们的UNION语句

  • LIKE很慢,一般来说,最好使用FULLTEXT(全文索引)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,165评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,503评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,295评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,589评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,439评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,342评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,749评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,397评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,700评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,740评论 2 313
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,523评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,364评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,755评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,024评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,297评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,721评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,918评论 2 336

推荐阅读更多精彩内容