![]() |
奋斗的木瓜 · Create DBRefs in MongoDB· 2 周前 · |
![]() |
留胡子的电影票 · MySQL时间戳转换时间10位 ...· 1 周前 · |
![]() |
傻傻的大熊猫 · MySQL时间转换(timestamp与da ...· 1 周前 · |
![]() |
开朗的大白菜 · python / shell / ...· 1 周前 · |
![]() |
爱跑步的松鼠 · python ...· 5 月前 · |
![]() |
英勇无比的火腿肠 · 其实我一直都认为罗永浩是草根逆袭,把他当做典 ...· 5 月前 · |
![]() |
火星上的楼梯 · 【雅昌快讯】1.22亿!藏在法国阁楼的乾隆御 ...· 6 月前 · |
![]() |
微醺的凉茶 · Q-Flow和Q-Studio ...· 6 月前 · |
![]() |
豪爽的西装 · 爱上ASMR官网(asasmr.com)-网 ...· 9 月前 · |
事务隔离级别 table mysql update语句 mysql |
https://fynn90.github.io/2018/01/07/MySQL%E5%9F%BA%E7%A1%80%E6%93%8D%E4%BD%9C%E6%89%8B%E5%86%8C/ |
![]() |
谈吐大方的镜子
6 月前 |
计算机存储信息的最小单位是
位(bit)
。二进制一个’0’或一个’1’叫一位。
计算机存储容量最基本的单位是 __字节(Byte)__。8个二进制位(bit)组成一个字节。一个标准的英文字母占一个字节位置,一个标准的汉字占二个字节位置。(不同编码可能占用字节不一样!)
UTF-8编码中,一个英文字母字符存储需一个字节,一个汉字字符存储需要3~4个字节。
MySQL数据类型 tinyint(m) [UNSIGNED] 1个字节 范围(-128~127) smallint(m) [UNSIGNED] 2个字节 范围 (-32768~32767) mediumint(m)[UNSIGNED] 3个字节 范围 (-8388608~8388607) int(m) [UNSIGNED] 4个字节 范围(-2147483648~2147483647) bigint(m) [UNSIGNED] 8个字节 范围(+-9.22*10的18次方)取值范围如果加了 unsigned ,则最大值翻倍。例如 tinyint unsigned 的取值范围为(0~256)。
MySQL数据类型 float(m, d) 单精度浮点型 8位精度(4字节) m总个数, d小数位 double(m, d) 双精度浮点型 16位精度 (8字节) m总个数, d小数位设一个字段定义为float(5,3),如果插入一个数123.45678,实际数据库里存的是123.456,总个数以实际为准。
浮点数在数据库中存放的是近似值,而定点类型在数据库中存放的是精确值。
decimal(m, d) 参数 m<65是总个数,d<30且d<m是小数位。
char(n)
中的n设定字符串存储时的长度,如果长度不足n,则空格补于其后,查询时在将空格去掉。
varchar(n)
中的N设定字符串存储时的长度,如果长度不足n,不会再后面填充空格,但varchar实际长度是存储时长度+1。因为varchar字段会用一个字节保存字符串长度。
char类型的字符串检索速度要比varchar类型快。但占的存储空间可能比varchar大。
MySQL数据类型 最大长度 65535个字节 MediumBlob 最大长度 16777215个字节 LongBlob 最大长度 4294967295个字节Blob (Binary large objects)储存二进位资料,且有分大小写
MySQL数据类型 日期 ‘2008-12-2’ 时间 ‘12:25:36’ datetime 日期时间 ‘2008-12-2 22:06:44’ timestamp 自动存储记录修改时间 (系统当前时间) 年份yyyyMySQL关键字 | 数据列可包含NULL值 | NOT NULL | 数据列不允许包含NULL值 | DEFAULT | PRIMARY KEY | AUTO_INCREMENT | 自动递增,适用于整数类型 | UNSIGNED | CHARACTER SET name | 指定一个字符集 |
---|
1 |
CREATE DATABASE database_name; |
创建数据库表:
1 |
CREATE TABLE tablename ( |
查看表结构:
DESC table_name \G;
。
查看创建表的表达式:
show create table table_name \G;
1 |
CREATE TABLE persons ( |
创建MySQL账户,语法:
1 |
CREATE USER 'user_name'@'[localhost|%]' IDENTIFIED BY 'password'; |
localhost 表示只能是本地登录, % 表示可以远程登录。
删除数据库:
1 |
DROP DATABASE database_name; |
删除数据库表:
1 |
DROP TABLE table_name; |
删除表索引:
1 |
ALTER TABLE table_name DROP INDEX index_name; |
对于已经创建好的表,如果需要做一些结构上的改变可以使用
alter table
语句。
1 |
ALTER TABLE tbale_name MODIFY [COLUMN] column_definition [FIRST | AFTER col_name]; |
1 |
ALTER TABLE emp MODIFY ename varchar(20); |
1 |
ALTER TABLE table_name ADD [COLUMN] column_definition [FIRST | AFTER col_name]; |
1 |
ALTER TABLE emp add column age int(3) |
1 |
ALTER TABLE table_name DROP COLUMN column_name |
1 |
ALTER TABLE emp DROP COLUMN age; |
1 |
ALTER TABLE table_name ALTER column_name SET DEFAULT value; |
1 |
ALTER TABLE table_name ALTER column_name DROP DEFAULT; |
1 |
ALTER TABLE table_name CHANGE [COLUMN] old_column_name column_definition [FIRST | AFTER column_name] |
1 |
ALTER TABLE emp CHANGE age age1 int(4); |
例子,新增的字段birth date 加在ename之后:
1 |
ALTER TABLE emp ADD birth date after ename; |
1 |
ALTER TABLE old_table_name RENAME TO new_table_name; |
1 |
INSERT INTO table_name (field1,field2,field3) VALUES (value1,vaule2,vaule3),(value1.1,value1.2,value1.3); |
1 |
INSERT INTO persons (LastName,FirstName,Address,City) VALUES ('Gates','Bill','xuanwumen 10','Bei jing'); |
表中允许为空值的字段可以在插入时不插入数据,但如果表中字段为非空并且没有默认值则每次插入都需要插入数据。
可空字段,非空但含有默认值的字段,自增长字段可以不用在insert后的字段列表里面出现。
数值顺序如果是表结构字段顺序则可以省略字段声明部分。例如:
1 |
INSERT INTO dept VALUES (5,'dept5); |
1 |
UPDATE tablename SET field1=value1,field2=value2,fieldn=valuen [WHERE CONDITION] |
1 |
UPDATE persons SET FirstName='Fred' WHERE LastName = 'Wilson'; |
1 |
DELETE FROM table_name [WHERE CONDITION]; |
1 |
DELETE FROM Person WHERE LastName = 'Wilson' |
在MySQL中可以一次删除多个表的数据,语法:
1 |
DELETE t1,t2,...,tn FROM t1,t2,...tn [WHERE CONDITION]; |
1 |
delete a,b from emp a,dept b where a.deptno=b.deptno and a.deptno=3; |
数据插入到数据库中后,可以用SELECT命令进行各种各样的查询。最基本的语法如下:
1 |
SELECT * FROM table_name [WHERE CONDITION] |
* 表示将所有记录都选出来,等同于用逗号分割所有字段。
有时需要将表中的记录去掉重复后显示出来,可以使用关键字 distinct。
1 |
SELECT DISTINCT field1,field2 FROM table_name; |
被 distinct 字段必须在首位,且一条查询语句只能有一个 distinct 。
很多情况,我们不需要将所有数据查询出来,而只是根据限定条件查询一部分数据,用where关键字可以实现这样操作。
1 |
select * from persons where City='Bei jing'; |
where关键字后面条件除了 = 外,还可以使用 > <__ __>= <= != 等比较运算符。多个条件之间还可以使用 or and 等逻辑运算符进行条件联合查询。
1 |
select * from emp where deptno=1 and sal<3000; |
我们经常有这样的需求,取出按照某个字段进行排序后的记录结果集,这就需要用到数据库的排序操作。用关键字 ORDER BY来实现。语法如下:
1 |
SELECT * FROM table_name [WHERE CONDITION] [ORDER BY field1 [DESC|ASC], field2 [DESC|ASC],..., fieldn [DESC|ASC]] |
其中 DESC 和 ASC 是排序顺序关键字, DESC 表示按字段进行降序排列, ASC 则表示升序排列,如果不写关键字默认是升序排列。 ORDER BY后面可以跟多个不同的排序字段,并且每个排序字段可以有不同的排序顺序。
1 |
select * from emp order by deptno, sal desc; |
排序后希望只显示一部分而不是全部,就可以使用LIMIT关键字来实现。语法如下:
1 |
SELECT ... [LIMIT offset_start, row_count]; |
其中 offset_start 表示记录的起始偏移量, row_count 表示显示的行数。
1 |
select * from emp order by sal limit 3; |
limit经常和order by 一起配合使用来进行记录的分页。
1 |
GRANT operate1,operate2,...,operateN ON db.tableName to 'user'@'[%|localhost]'; |
假如数据库中有个
testdb
数据库和
developer
账户。
给
developer
账户授予 查询,插入,更新
testdb
数据库中所有表的权限,并且可以在远程登录。例子:
1 |
grant select,insert,update on testdb.* to 'developer'@'%'; |
授予所有权限语法:
1 |
grant all privileges on testdb.* to 'developer'@'%'; |
1 |
revoke operate1,operate2,...,operateN ON db.tableName FROM 'user'@'[%|localhost]'; |
表连接分为 内连接和外连接。它们之间的主要区别是,内连接仅选出两张表中互相匹配的记录,而外连接会选出其他不匹配的记录。
内连接,例子:
1 |
select ename,deptname from emp,dept where emp.deptno = dept.deptno; |
左连接,LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行。语法:
1 |
SELECT column_name(s) FROM table_name1 LEFT JOIN table_name2 ON table_name1.column_name = table_name2.column_name; |
右连接,RIGHT JOIN 关键字会右表 (table_name2) 那里返回所有的行,即使在左表 (table_name1) 中没有匹配的行。语法:
1 |
SELECT column_name(s) |
在表中存在至少一个匹配时,INNER JOIN 关键字返回行。语法:
1 |
SELECT column_name(s) |
UNION 操作符用于合并两个或多个SELECT语句的集合。语法:
1 |
SELECT column_name(s) FROM table_name1 |
请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。
UNION默认会选取不同的值,如果允许值重复使用UNION ALL。
和大多数数据库不同,MySQL中有存储引擎的概念,不同的存储引擎其应用方面不一样。常用到的MySQL存储引擎有:MyISAM、InnoDB、MEMORY、MERGE。
MyISAM存储引擎特别适合在一下几种情况下使用:
在一下场合下,使用InnoDB是最理想的选择:
1 |
CREATE TABLE log_YY ( |
上面SQL创建日志表。
1 |
CREATE TABLE log_merge( |
上面SQL将多张日志表合并为一张表。
TokuDB不是MySQL官方存储引擎( 安装教程 )。它是TokuTek公司(已被 Percona收购)研发的新引擎,支持事务/MVCC,有着出色的数据压缩功能,支持异步写入数据功能。
TokuDB索引结构采用fractal tree数据结构,是buffer tree的变种,写入性能优异,适合写多读少的场景。除此之外,TokuDB还支持在线加减字段,在线创建索引,锁表时间很短。
Percona Server和Mariadb支持TokuDB作为大数据场景下的引擎,目前官方MySQL还不支持TokuDB。ApsaraDB for MySQL从2015年4月开始支持TokuDB,在大数据或者高并发写入场景下推荐使用。
1 |
[CONSTRAINT symbol] FOREIGN KEY [id] (从表的字段1) |
1 |
mysql> CREATE TABLE `user` ( //创建用户表 |
外键只有InnoDB存储引擎才支持。对外键关联的表进行检索会影响效率。
索引是数据库中提高查询操作性能的最佳途径。但滥用索引会降低写操作的性能,因为在更新表时不仅要保存数据,还要保存一下索引文件。
1 |
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name [USING index_type] ON tbl_name (index_col_name1,index_col_name2,...,index_col_nameN) |
1 |
ALTER mytable ADD INDEX [indexName] ON (username(length)) |
1 |
CREATE TABLE mytable( |
1 |
DROP INDEX [indexName] ON mytable; |
从物理存储角度:
从逻辑角度:
MYSQL使用SPATIAL关键字进行扩展,使得能够用于创建正规索引类型的语法创建空间索引。创建空间索引的列,必须将其声明为NOT NULL,空间索引只能在存储引擎为MYISAM的表中创建
视图-事先定义好SQL操作规则的虚拟表。
对视图的使用就把它当作table,但它并没有定义字段。它的数据和字段来自真实的table。
视图相对普通表的优势主要包括一下:
1 |
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] |
1 |
mysql>CREATE OR REPLACE VIEW staff_list_view AS |
视图一旦创建完毕,就可以像普通表那样使用,视图主要用来查询:
1 |
mysql> select * from view_name |
1 |
SQL DROP VIEW Syntax DROP VIEW view_name; |
1 |
drop view staff_list; |
存储过程-数据库端可编程的函数,它在数据库中创建并保存。它可以有SQL语句和一些特殊的
控制结构
组成。
存储过程可以看做是对编程中面向对象方法的模拟。
存储过程优点:
存储过程缺点:
1 |
CREATE PROCEDURE sp_name ([proc_parameter]) |
例子 IN参数:
1 |
mysql> delimiter $$ |
delimiter
定义MySQL语句最后结束符。
存储过程的调用通过关键字
call
+ pro_name(params)。
例子OUT参数:
1 |
mysql> delimiter // |
1 |
DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name |
通过 DECLARE 可以定义一个局部变量,该变量的作用域只能在 BEGIN…END 块中。可以用于嵌套块中。
1 |
DECLARE var_name [,...] type [DEFAULT value] |
1 |
DECLARE last_month_start DATE; |
直接赋值通过 SET 例子:
1 |
SET var_name = expr [, var_name = expr] ... |
通过查询赋值,例子:
1 |
SELECT col_name[,...] INTO var_name[,...] table_expr |
条件的定义和处理可以用来定义在处理过程中遇到问题时对应的处理步骤。
条件的定义,语法:
1 |
DECLARE condition_name CONDITION FOR condition_value |
条件的处理,语法:
1 |
DECLARE handle_type HANDLER FOR condition_value[,...] sp_statement |
例子,向一张表批量插入数据。当数据主键有重复时插入会失败并报 23000 错误。可以通过定义错误处理忽略此错误。
1 |
mysql> delimiter $$ |
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
此句告诉数据库当出现 23000错误时继续执行下面的SQL语句。
上面的例子可以写成下面几种形式:
DECLARE CONTINUE HANDLER FOR 1062 SET @x2 = 1;
DECLARE DuplicateKey CONDITION FOR SQLSTATE '23000';
DECLARE CONTINUE HANDLER FOR DuplicateKey SET @x2 = 1;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @x2 = 1;
例子:对payment表按照行进行循环处理,按照staff_id值的不同累加 amount值。判断循环结束的条件是捕获NOT FOUND 的条件,当FETCH光标找不到下一条记录的时候,就会关闭光标然后退出过程。
1 |
mysql> delimiter $$ |
可以使用 IF、CASE、LOOP、LEAVE、ITERATE、REPEAT及WHILE语句进行流程的控制。
IF search_condition THEN statement_list [ELSEIF search_condition THEN statement_list] ... [ELSE statement_list] END IF
CASE case_value WHEN when_value THEN statement_list [WHEN when_value THEN statement_list] ... [ELSE statement_list] END CASE
[begin_label:] LOOP statement_list END LOOP [end_label]
如果不再 statement_list中增加退出循环的语句,那么LOOP语句可以用来实现简单的死循环。
[begin_lable:] REPEAT statement_list UNTIL search_condition END REPEAT [end_label]
[begin_label:] WHILE search_condition DO statement_list END WHILE [end_label]
WHILE循环和REPEAT循环的区别在于:WHILE是满足条件才执行循环,REPEAT是满足条件退出循环。WHILE最少执行0次,而REPEAT最少执行1次。
MySQL从5.0.2版本开始支持触发器的功能。触发器是当某张表发生触发器中定义触发事件时所做的反应。例如定义某张表发生插入或更新时进行某些SQL操作。
1 |
CREATE TRIGGER trigger_name trigger_time trigger_event on tbl_name FOR EACH ROW trigger_stmt |
注意:触发器只能创建在永久表上,不能对临时表创建触发器。
例子,为film表创建 AFTER INSERT的触发器,具体如下:
1 |
mysql> DELIMITER $$ |
上面定义一个film插入数据触发器。当film表有插入数据操作后,触发器会将插入的数据添加到表film_text中。
对于有重复的记录,需要进行UPDATE操作的INSERT,触发器触发的顺序是 BEFORE INSERT、BEFORE UPDATE、AFTER UPDATE、AFTER INSERT。对于没有重复记录的 INSERT,就是简单的执行 INSERT 操作,触发器触发的顺序是 BEFORE INSERT、AFTER INSERT。对于那些实际执行UPDATE操作的记录,仍然会执行BEFORE INSERT触发器的内容。
一次可以删除一个触发器,如果没指定shema_name,默认为当前数据库,具体语法:
1 |
DROP TRIGGER [schema_name.]trigger_name。 |
1 |
mysql> show triggers \G |
触发器执行的语句有以下两个限制:
如果不考虑隔离性可能出现的几种情况:脏读,不可重复读,幻读。
1 |
START TRANSACTION | BEGIN [WORK] |
1 |
mysql> start transaction; |
分布式事务-在不同的数据库中执行事务操作。所有行动都必须成功完成,或者一起回滚。
在MySQL中,使用分布式事务的应用涉及一个或多个资源管理器和一个事务管理器。
分布式事务分为两个阶段:
1 |
# 启动一个带xid值得XA事务 |
1 |
mysql> xa start 'test','db1'; |
1 |
show variables like 'character%'; --- 查看数据库编码; |
如果索引正在工作, Handler_read_key 的值将会很高,这个值代表一个行被索引读的次数,很低的值表名增加所以得到的性能改善不高,因为索引没经常使用。
Handler_read_rnd_next 的值高则意味着查询运行低效,并且应该添加索引补救。这个值含义是数据文件中读下一行的请求数。如果正进行大量的表扫描, Handler_read_rnd_next 的值会很高。则说明索引不正确或写入的查询没利用索引。
1 |
mysql> show status like 'Handler_read%'; |
在查询语句添加关键字 explain 可查看次查询语句具体查询数据。
1 |
mysql> explain select customer_id from customer order by store_id \G |
1 |
> mysql -h www.hostname.com -P 3306 -uroot -p |
在远程服务器打开防火墙,允许外部地址连接 3306端口。
打开防火墙后,要需要确保MySQL允许远程访问。
限定访问地址配置项是在 mysql数据库 user表 host字段。
host字段默认是’localhost’。只允许本地登陆。修改host字段为’%’允许所有地址登陆。然后重启mysql就可以了。
1 |
$ mysql -uroot -v --show-warnings -f test < a.sql |
由于服务器生成的二进制日志文件以二进制格式保存,所以如果要想检查这些文件的文本格式,就会用到 mysqlbinlog 日志管理工具。
1 |
shell> mysqlbinlog [options] log-files1 log-files2... |
option选项:
1 |
shell> mysqlcheck[options] db_name [tables] |
option常用项:
例子:
1 |
[root@localhost mysql]# mysqlcheck -uroot -c test |
mysqldump 客户端工具用来备份数据库或在不同数据库之间进行数据迁移。备份内容包含创建表或装载表的 SQL 语句。mysqldump 目前是 MySQL 中最常用的备份工具。它是和mysql一起被安装的,在mysql安装目录的bin目录下可以找到它。
常用命令:
1 |
mysqldump -u 用户名 -p 数据库名 > 导出的文件名 #导出一个数据库 |
mysqlshow 客户端对象查找工具,用来很快地查找存在哪些数据库、数据库中的表、表中的列或索引。
GROUP BY
语句结合合计函数,根据一个或多个列对结果集进行分组。
语法:
1 |
SELECT column_name, aggregate_function(column_name) FROM table_name WHERE column_name operate value GROUP BY column_name |
1 |
SELECT Customer,SUM(OrderPrice) FROM Orders |
默认情况下,MySQL对所有GROUP BY col1,col2….的字段进行排序。这与在查询中指定ORDER BY col1,col2…类似。因此,如果显示包括一个包含相同的列的 ORDER BY子句,则对MySQL的实际执行性能没什么影响。
如果查询包括GROUP BY但用户想要避免排序结果的消耗,则可以指定ORDER BY NULL。
当进行数据INSERT的时候,可以考虑采用一下几种优化方式。
insert into test values(1,2),(1,3),(1,4)…
。这种方式将大大缩减客户端与数据库之间的连接,关闭等消耗,使得效率比分开执行的单个INSERT语句块。
INSERT DELAYED
语句得到更高的速度。
DELAYED
的含义是让 INSERT语句马上执行,其实数据都被放在内存队列中,并没有真正写入磁盘,这比每条语句分别插入要快的多。
LOW_PRIORITY
刚好相反,在所有其他用户对表的读写完后才进行插入。
连接(JOIN)之所以更有效率一些,是因为 MySQL 不需要在内存中创建临时表来完成这个逻辑上的需要两个步骤的查询工作。
对于含有 OR 的查询子句,如果要利用索引,则 OR 之间的每个条件列都必须用到索引;如果没有索引,则应该考虑增加索引。
SQL 提示(SQL HINT)是优化数据库的一个重要手段,简单来说就是在 SQL 语句中加入一些人为的提示来达到优化操作的目的。
在查询语句中表名的后面,添加USE INDEX来提供系统MySQL去参考索引列表,可以让MySQL不再考虑其它可用索引。
1 |
mysql> explain select * from sales2 use index (ind_sales2_id) where id = 3\G; |
如果用户只是单纯地想让 MySQL 忽略一个或者多个索引,则可以使用 IGNORE INDEX 作为 HINT。
1 |
explain select * from sales2 ignore index (ind_sales2_id) where id = 3\G; |
1 |
mysql> explain select * from sales2 where id > 0 \G; |
但是,当使用 FORCE INDEX 进行提示时,即便使用索引的效率不是最高,MySQL 还是选择使用了索引,这是 MySQL 留给用户的一个自行选择执行计划的权力。加入 FORCE INDEX 提示后再次执行上面的 SQL:
1 |
mysql> explain select * from sales2 force index (ind_sales2_id) where id > 0 |
http://www.w3school.com.cn/sql/index.asp
http://www.runoob.com/mysql/mysql-tutorial.html
深入浅出Mysql
https://www.alibabacloud.com/help/zh/doc-detail/26133.htm
![]() |
奋斗的木瓜 · Create DBRefs in MongoDB 2 周前 |