数据库笔记。
数据库原理 数据库设计的三大范式 
第一范式:确保每列保持原子性。比如存储地址时,如果省市区都放到一列里,如果需要读取省份时,就比较麻烦了,这样就不符合原子性了。所以应当把省份、市、区、详细地址分别放到不同的列中。 
第二范式:确保每列数据完全依赖于主键,而不是依赖主关键字的一部分。如果有两个联合主键a和b,又有数据列c依赖a,d依赖b,就应该把他们分成两个表。 
第三范式:除主键外的其他列之间不应该有依赖关系。 
每个范式都建立在前一范式的基础上。在实际应用中不一定要完全遵守三大范式,虽然可能会有数据冗余,但是能提高查询效率。 
 
不遵守三大范式会带来哪些问题 
学号 
姓名 
班级 
班主任 
课程 
分数 
 
 
001 
萧炎 
一班 
药老 
青莲地心火 
100 
 
001 
萧炎 
一班 
药老 
净莲妖火 
100 
 
002 
林动 
二班 
天蚕土豆 
通背拳 
100 
 
002 
林动 
二班 
天蚕土豆 
大荒囚天指 
100 
 
003 
谢文东 
三班 
六道 
坏蛋是怎样炼成的 
100 
 
 
如上表格:
冗余数据。班级、班主任都因为课程出现数据冗余。 
插入异常。如果增加一个未选课的学生,就无法插入数据。 
删除异常。如果撤销一个班主任,会丢失学生的信息。 
修改异常。修改一个学生的班主任时,会有另一条记录未被修改。 
 
如何理解数据库索引 
数据库事务以及四大特性 1.事务
2.事务四大特性
原子性(atomicity):一个事务必须视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性。 
一致性(consistency):数据库总数从一个一致性的状态转换到另一个一致性的状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。(所谓一致性可以说是一种正确地状态,所谓正确,就是满足一定的约束条件) 
隔离性(isolation):一个事务所做的修改在最终提交以前,对其他事务是不可见的。 
持久性(durability):一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。 
 
3.四个特性的关系
在无并发的情况下,保证原子性就能实现一致性。 
有并发时保证原子性和隔离性才能实现一致性。 
实现一致性才能保证结果的正确。 
持久性保证数据库崩溃后数据不会丢失。 
 
并发一致性问题 1.1第一类丢失更新(回滚导致丢失)。T1回滚导致T2提交的修改丢失了。
 
1.2第二类丢失更新(覆盖导致丢失)。T1对var的修改被T2提交的修改覆盖了,这是不可重复读的一种特殊情况。
1 2 3 4 T1        T2 修改var               修改var 读取var 
 
2.脏读,又称无效数据读出。一个事务读取另外一个事务还没有提交的数据叫脏读。
 
3.不可重复读,一个事务读取了另一个事务提交的数据。1 2 3 4 T1        T2 读取var               修改var 读取var 
4.幻读,读取到了不存在的数据。
1 2 3 4 T1            T2 范围读取数据                   插入一条数据 范围读取数据 
 
不可重复读跟幻读有点像,区别在于不可重复读是读取到了另一个事务的update操作,幻读是读取到了另一个事务的insert操作。 
 
事务的四种隔离级别 数据库事务的隔离级别有4个,依次递增:
Read uncommitted,未提交读表示在一个事务中可以读取另一个事务未提交的数据,存在脏读、不可重复读、幻读的问题。 
Read committed,提交读表示一个事务中可以读取另一事务已提交的数据,存在不可重复读、幻读的问题。 
Repeatable read,可重复读保证一个事务中多次读取的结果是相同的,还存在幻读的问题。 
Serializable,强制事务串行化,一般不用这个隔离级别。 
 
隔离级别 
脏读 
不可重复读 
幻影读 
丢失更新 
第二类丢失更新 
 
 
未提交读 
√ 
√ 
√ 
x 
x 
 
提交读 
× 
√ 
√ 
x 
x 
 
可重复读 
× 
× 
√ 
x 
x 
 
可串行化 
× 
× 
× 
x 
x 
 
 
参考:三级封锁协议两段锁以及隔离级别 
PS:我的理解是未提交读采用一级封锁协议就已经解决了丢失更新问题,但是网上很多人的总结”提交读”级别还存在第二类丢失更新问题?
两种封锁类型:读写锁和意向锁 Mysql提供两种封锁粒度,分别是行级锁和表级锁。
当访问数据的时候,尽量加锁小的范围可以减少性能的损耗,所以加锁的时候需要在锁开销和并发程度之间做一个平衡。
读写锁 
读锁又叫共享锁(Shared Lock,简称S锁),可以加在表上,也可以加在行上。 
写锁又叫排它锁(Exclusive Lock,简称X锁),可以加在表上,也可以加在行上。 
 
如果事务T1对数据A加了共享锁,T2可以对数据A再加共享锁,但是不能再加排他锁。
如果事务T2对数据A加了排它锁,T2不可以再加共享锁或排它锁。
两者的兼容关系如下:
意向锁 1.如果事务T1对表的第5行加了排它锁,T2又想对表加排它锁/共享锁,T2需要检查两件事:
表上是否有表级的排它锁。 
表中某一行是否加了排它锁。 
 
在判断第二点的时候,需要遍历表中的每一行才能判断,这样的开销太大了。如果能给表加一个标志 ,用来标志表内某一行是否有排它锁。这样就产生了意向锁。
2.意向锁分为以下两种:
意向共享锁(Intention Shared Lock,简称IS),只能是表锁。 
意向排他锁(Intention Exclusive Lock,简称IX),只能是表锁。 
 
事务T在获取某行 的S锁之前,需要先获取该表 的IS锁或者IX锁。
事务T在获取某行 的X锁之前,需要先获取该表 的IX锁。
PS:S和X是我们要手动去加的,IS和IX是数据库根据我们的操作自动去加的。
3.意向锁只是一个标志,表示表上已经加了或即将要加共享锁/排它锁,所以意向锁之间相互兼容 :
4.意向锁和表级的 共享锁排它锁之间的兼容关系如下:
参考 
隐式锁定&显示锁定 InnoDB会根据隔离级别在合适的时候进行加锁和解锁,这是隐式锁定。我们也可以通过Sql语句显示加锁。
1 2 SELECT ... LOCK IN SHARE MODE;  #添加共享锁 SELECT ... FOR UPDATE;	#添加排它锁 
 
封锁协议 了解读写锁和意向锁的概念后,何时加锁何时解锁还是个问题。有三级封锁协议,分别对应几种隔离级别。
一级封锁协议 
事务T修改数据时要加X锁,直到事务T结束 才释放锁。 
 
一级封锁协议要求修改数据时必须要加锁,能够避免丢失修改问题,对应”未提交读”隔离级别。
T1 
T2 
 
 
lockX(var) 
 
 
修改var 
lockX(var) 
 
提交 
阻塞 
 
unlockX(var) 
… 
 
 
获得锁 
 
 
修改var 
 
 
提交 
 
 
unlockX(var) 
 
 
二级封锁协议 二级封锁协议要求在一级封锁协议基础上再加一条:
这样事务T1在写数据时已经加了X锁,事务T2想要读取数据在加S锁时会阻塞,能够避免脏读问题。这对应了“提交读”的隔离级别。
T1 
T2 
 
 
lockX(var) 
 
 
修改var 
lockS(var) 
 
回滚 
阻塞 
 
unlockX(var) 
… 
 
 
获得锁 
 
 
读取var 
 
 
提交 
 
 
unlockS(var) 
 
 
三级封锁协议 三级封锁协议要求在一级封锁协议的基础上再加一条:
二级封锁协议在读取结束后就释放S锁,还会存在不可重复读问题:事务T2对数据加S锁,读取结束释放S锁。事务T1加X锁修改数据,T1结束释放X锁。事务T2又加S锁重复读取数据,这时T2在一个事务里就两次读到了不同的数据。
三级封锁协议要求在事务结束后释放S锁,就避免了读数据过程中其他事务来修改数据。解决了不可重复读的问题,对应”可重复读”隔离级别。
疑问:三级封锁协议并不能阻止幻读,修改的不能再被读取,但是新增(删除)的记录数可以统计。为什么三级封锁协议不能阻止幻读,insert和delete操作是如何加锁的?
T1 
T2 
 
 
 
lockS(var) 
 
 
读取var 
 
lockX(var) 
 
 
阻塞 
 
 
 
读取var 
 
 
提交 
 
 
unlockS(var) 
 
获得锁 
 
 
修改var 
 
 
提交 
 
 
unlockX(var) 
 
 
两阶段封锁协议 该协议要求一个事务分为加锁(生长阶段)和解锁(衰退阶段)两个阶段,也就是在一个事务里,任何一个加锁都在解锁前面。
事务满足两阶段封锁协议>>串行化调度,反之就不一定了。该协议可以满足”可串行化”隔离级别。
MVCC xxx
SQL语句 数据库相关操作 
判断mysql是否启动
 
 
启动mysql服务器
1 2 cd /usr/bin ./mysqld_safe & 
 
 
关闭mysql服务器
1 2 3 cd /usr/bin ./mysqladmin -u root -p shutdown Enter password: ****** 
 
 
启动mysql终端
 
 
退出mysql终端
 
 
 
1 2 3 4 #sql语句创建 CREATE  DATABASE  库名;#命令行直接创建 mysqladmin -u root -p create  库名 
 
1 2 3 DROP  DATABASE  库名;#命令行删除 mysqladmin -u root -p drop  库名; 
 
 
 
数据表相关操作 
1 2 SHOW  TABLE  STATUS  LIKE  '表名' ;ALTER  TABLE  表名 ENGINE =InnoDB ;
 
1 2 3 4 5 6 7 8 9 10 11 12 CREATE  TABLE  IF  NOT  EXISTS  `test_tbl` (   `test_id`  INT  UNSIGNED  AUTO_INCREMENT,    `test_title`  VARCHAR (100 ) NOT  NULL ,    `test_author`  VARCHAR (40 ) NOT  NULL ,    `submission_date`  DATE ,    PRIMARY KEY  ( `test_id`  ) )ENGINE =InnoDB  DEFAULT  CHARSET =utf8; ============================================================ 如果你不想字段为 **NULL** 可以设置字段的属性为 **NOT NULL**, 在操作数据库时如果输入该字段的数据为**NULL** ,就会报错。 AUTO_INCREMENT定义列为自增的属性,一般用于主键,数值会自动加1。 PRIMARY KEY关键字用于定义列为主键。 您可以使用多列来定义主键,列间以逗号分隔。 ENGINE 设置存储引擎,CHARSET 设置编码。 
 
 
 
插入数据 1 2 3 4 INSERT  INTO  test_tbl(test_title,test_author,submission_date) VALUES ("study sql" ,"YIFEI" ,NOW ()); 
 
查询数据 1 2 3 4 5 6 7 8 9 10 11 12 #SELECT语法 SELECT  column_name,column_nameFROM  table_name[WHERE  Clause] [LIMIT  N][ OFFSET  M] ============================================ 查询语句中你可以使用一个或者多个表,表之间使用逗号(,)分割,并使用WHERE 语句来设定查询条件。 SELECT  命令可以读取一条或者多条记录。你可以使用星号(*)来代替其他字段,SELECT 语句会返回表的所有字段数据 你可以使用 WHERE  语句来包含任何条件。 你可以使用 LIMIT  属性来设定返回的记录数。 你可以通过OFFSET 指定SELECT 语句开始查询的数据偏移量。默认情况下偏移量为0 。 
 
1 2 3 SELECT  * FROM  表名;SELECT  column1,column2 FROM  表名;SELECT  DISTINCT  column1,coulumn2 FROM  表名;
 
WHERE子句 
单表
1 2 3 4 5 6 7 8 SELECT  test_author,test_id FROM  test_tblWHERE  BINARY  test_title='study php'  AND  	BINARY  test_author='YIFEI'  ======================================= 多个条件用AND 、OR 连接。 =检测是否相等,<>、!=检测不等,其他还有<=、>=。 BINARY 表示区分大小写。WHERE 也可以用于DELETE  或者 UPDATE 中。
 
 
多表
 
 
修改数据 1 2 3 UPDATE  test_tbl SET  test_title='study cpp' ,test_author='tws' WHERE  test_id=2 ;
 
删除数据 1 DELETE  FROM  test_tbl WHERE  test_id=3 ;
 
LIKE子句 
1 SELECT  * FROM  test_2 WHERE  submission_date LIKE  "%08-26" ;
 
UNION 
1 2 3 4 5 6 7 8 SELECT  submission_date FROM  test_2UNION  allSELECT  submission_date FROM  test_tblORDER  BY  submission_date;==================================== all是显示所有数据,默认为distinct 去重。 两个select 查询的列数应当相同。 ORDER  BY  submission_date是按照该列排序。
 
1 2 3 4 5 6 SELECT  country, name  FROM  WebsitesWHERE  country='CN' UNION  ALLSELECT  country, app_name FROM  appsWHERE  country='CN' ORDER  BY  country;
 
排序 
1 2 3 4 SELECT  * FROM  test_tbl ORDER  BY  name  DESC ,date  ASC ;=========================================================== ASC升序排列,DESC为降序排列。 如果排序列为汉字,想要按照拼音排序:ORDER BY CONVERT(title using gbk); 
 
分组 
1 2 3 4 SELECT  name ,COUNT (*) FROM  employee_tbl GROUP  BY  name ;====================================================== 按照名字分组。 count(*)统计每类的数量。 
 
使用WITH ROLLUP,在group by的结果之上再统计。 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 SELECT  coalesce (name , '总数' ), SUM (singin) as  singin_count FROM   employee_tbl GROUP  BY  name  WITH  ROLLUP ;+ | coalesce(name, '总数') | singin_count | + | 小丽                   |            2 | | 小明                   |            7 | | 小王                   |            7 | | 总数                   |           16 | + 4 rows in set  (0.01  sec) ================================================== coalesce (a,b,c)如果a!=null 就使用a作为该列名称,如上如果name 为空,就使用"总数" 作列名。ifnull (a,b)跟coalesce 一样的效果。WITH  ROLLUP 之后可以对分组结果再统计SUM (singin)。SUM 之外还有AVG 、COUNT 等。
 
连接 内连接 
1 2 3 SELECT  a.runoob_id,a.runoob_title,b.runoob_author FROM  runoob_2 AS  a INNER  JOIN  runoob_tbl AS  b ON  BINARY  a.runoob_author=b.runoob_author;
 
内连接是取两表的交集,上面语句等价于以下WHERE语句:
1 2 3 SELECT  a.runoob_id,a.runoob_title,b.runoob_author FROM  runoob_2 AS  a,runoob_tbl AS  b WHERE  BINARY  a.runoob_author=b.runoob_author;
 
左连接 
1 2 3 SELECT  a.runoob_id,a.runoob_title,b.runoob_author FROM  runoob_2 AS  a LEFT  JOIN  runoob_tbl AS  b ON  BINARY  a.runoob_author=b.runoob_author;
 
左连接会选取左表全部,输出右表满足要求的。
右连接 
1 2 3 SELECT  a.runoob_id,a.runoob_title,b.runoob_author FROM  runoob_2 AS  a RIGHT  JOIN  runoob_tbl AS  b ON  BINARY  a.runoob_author=b.runoob_author;
 
NULL值判断 在WHERE子句中判断某值为空时不能WHERE name=null ,应当使用如下方式:
1 2 3 4 5 SELECT  * FROM  test  WHERE  name  IS  NULL ;============================================= **IS NULL:** 当列的值是 NULL,此运算符返回 true。 **IS NOT NULL:** 当列的值不为 NULL, 运算符返回 true。 **<=>:** 比较操作符(不同于 = 运算符),当比较的的两个值相等或者都为 NULL 时返回 true。 
 
正则表达式 1 SELECT  * FROM  runoob_2 WHERE  runoob_author REGEXP '^y' ;
 
模式 
描述 
 
 
^ 
匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 ‘\n’ 或 ‘\r’ 之后的位置。 
 
$ 
匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 ‘\n’ 或 ‘\r’ 之前的位置。 
 
. 
匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用像 ‘[.\n]’ 的模式。 
 
[…] 
字符集合。匹配所包含的任意一个字符。例如, ‘[abc]’ 可以匹配 “plain” 中的 ‘a’。 
 
[^…] 
负值字符集合。匹配未包含的任意字符。例如, ‘[^abc]’ 可以匹配 “plain” 中的’p’。 
 
p1|p2|p3 
匹配 p1 或 p2 或 p3。例如,’z|food’ 能匹配 “z” 或 “food”。’(z|f)ood’ 则匹配 “zood” 或 “food”。 
 
* 
匹配前面的子表达式零次或多次。例如,zo 能匹配 “z” 以及 “zoo”。  等价于{0,}。 
 
+ 
匹配前面的子表达式一次或多次。例如,’zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。 
 
{n} 
n 是一个非负整数。匹配确定的 n 次。例如,’o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。 
 
{n,m} 
m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。 
 
 
事务 设置隔离级别 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 查看当前会话隔离级别: select  @@tx_isolation;查看系统的隔离级别: select  @@global.tx_isolation;设置会话的隔离级别,隔离级别由低到高设置依次为: set  session  transaction  isolation  level  read  uncommitted;set  session  transaction  isolation  level  read  committed;set  session  transaction  isolation  level  repeatable read ;set  session  transaction  isolation  level  serializable ;设置当前系统的隔离级别,隔离级别由低到高设置依次为: set  global  transaction  isolation  level  read  uncommitted;set  global  transaction  isolation  level  read  committed;set  global  transaction  isolation  level  repeatable read ;set  global  transaction  isolation  level  serializable ;
 
事务控制语句 
1 2 3 4 5 6 7 8 9 10 11 1、用 BEGIN , ROLLBACK , COMMIT 来实现 BEGIN  开始一个事务ROLLBACK  事务回滚COMMIT  事务确认2 、直接用 SET  来改变 MySQL 的自动提交模式:SET  AUTOCOMMIT=0  禁止自动提交SET  AUTOCOMMIT=1  开启自动提交3 、保存点SAVEPOINT  identifier,SAVEPOINT  允许在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT ;RELEASE  SAVEPOINT  identifier 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;ROLLBACK  TO  identifier 把事务回滚到标记点;
 
ALTER 命令 
1 SHOW  COLUMNS  FROM  testalter_tbl;
 
1 2 ALTER  TABLE  runoob_1 ADD  i INT  AFTER  runoob_id;
 
 可以将AFTER runoob_id改为FIRST,插入到第一列,默认是末尾。
1 2 ALTER  TABLE  testalter_tbl DROP  i;
 
1 2 3 4 5 ALTER  TABLE  testalter_tbl MODIFY  c CHAR (10 );#修改字段位置 ALTER  TABLE  test MODIFY  name1 type1 AFTER  name2;
 
1 2 ALTER  TABLE  testalter_tbl CHANGE  i j BIGINT ;
 
 CHANGE 关键字之后,紧跟着的是你要修改的字段名,然后指定新字段名及类型。
1 2 ALTER  TABLE  testalter_tbl ALTER  i SET  DEFAULT  1000 ;
 
1 2 ALTER  TABLE  testalter_tbl RENAME  TO  alter_tbl;
 
1 SHOW  TABLE  STATUS  LIKE  'testalter_tbl' 
 
1 2 ALTER  TABLE  testalter_tbl ENGINE  = MYISAM;
 
1 2 ALTER  TABLE  talbenameDROP  FOREIGN KEY  keyname;
 
索引 
1 SHOW  INDEX  FROM  table_name;
 
1 2 3 4 5 6 #添加普通索引,索引值可出现多次。 ALTER  TABLE  tbl_name ADD  INDEX  index_name (column_list);#添加唯一索引,创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)。 ALTER  TABLE  tbl_name ADD  UNIQUE  index_name (column_list);#添加全文索引 ALTER  TABLE  tbl_name ADD  FULLTEXT index_name (column_list);
 
1 ALTER  TABLE  tbl_name DROP  INDEX  index_name;
 
1 2 3 4 #添加主键,首先确保主键列不为空。 ALTER  TABLE  testalter_tbl MODIFY  i INT  NOT  NULL ;ALTER  TABLE  tbl_name ADD  PRIMARY KEY  (column_list);ALTER  TABLE  testalter_tbl DROP  PRIMARY KEY ;
 
1 CREATE  INDEX  indexName ON  table_name (column_name);
 
1 DROP  INDEX  [indexName] ON  table_name;
 
1 2 3 4 5 CREATE  TABLE  mytable(    ID  INT  NOT  NULL ,        username VARCHAR (16 ) NOT  NULL ,       INDEX  [indexName] (username(length ))   ); 
 
临时表 
临时表创建、插入、删除。(无法通过show tables查看) 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 CREATE  TEMPORARY  TABLE  SalesSummary (    product_name VARCHAR (50 ) NOT  NULL ,     total_sales DECIMAL (12 ,2 ) NOT  NULL  DEFAULT  0.00 ,     avg_unit_price DECIMAL (7 ,2 ) NOT  NULL  DEFAULT  0.00 ,     total_units_sold INT  UNSIGNED  NOT  NULL  DEFAULT  0  ); INSERT  INTO  SalesSummary(product_name, total_sales, avg_unit_price, total_units_sold) VALUES ('cucumber' , 100.25 , 90 , 2 ); SELECT  * FROM  SalesSummary;DROP  TABLE  SalesSummary;SELECT  * FROM  SalesSummary;
 
1 2 3 4 CREATE  TEMPORARY  TABLE  aaa AS (	SELECT  * FROM  runoob_1     LIMIT  1 ,10000   ); 
 
复制表 法一:执行sql创建新表、再插入数据 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #输出该表的创建语句 SHOW  CREATE  TABLE  runoob_tbl \G;#修改表名,然后执行sql语句 CREATE  TABLE  `clone_tbl`  (    `runoob_id`  int (11 ) NOT  NULL  auto_increment,     `runoob_title`  varchar (100 ) NOT  NULL  default  '' ,     `runoob_author`  varchar (40 ) NOT  NULL  default  '' ,     `submission_date`  date  default  NULL ,     PRIMARY KEY   (`runoob_id` ),     UNIQUE  KEY  `AUTHOR_INDEX`  (`runoob_author` ) ) ENGINE =InnoDB ; #将原表数据插入到新表 INSERT  INTO  clone_tbl (runoob_id,runoob_title,runoob_author,submission_date)SELECT  runoob_id,runoob_title,runoob_author,submission_date FROM  runoob_tbl;
 
法二:复制表结构、再插入数据 
1 2 CREATE  TABLE  targetTable LIKE  sourceTable;INSERT  INTO  targetTable SELECT  * FROM  sourceTable;
 
法三:复制表结构和数据 
1 CREATE  TABLE  new_name SELECT  * FROM  old_name;
 
创建新表并修改字段名 
1 2 3 CREATE  TABLE  newadmin(    SELECT  id , username AS  uname, password  AS  pass FROM  admin  ) 
 
获取服务器原数据 
SELECT VERSION( ) 
服务器版本信息 
 
 
SELECT DATABASE( ) 
当前数据库名 (或者返回空) 
 
SELECT USER( ) 
当前用户名 
 
SHOW STATUS 
服务器状态 
 
SHOW VARIABLES 
服务器配置变量 
 
 
删除重复数据 1 2 3 4 5 6 7 CREATE  TABLE  tmpSELECT  last_name, first_name, sex FROM  person_tbl  GROUP  BY  (last_name, first_name, sex);DROP  TABLE  person_tbl;ALTER  TABLE  tmp RENAME  TO  person_tbl;
 
导入导出数据 导出数据 
1 show  variables  like  'datadir' ;
 
1 2 SELECT  * FROM  table_nameINTO  OUTFILE  'table.txt' ;
 
1 2 3 4 SELECT  a,b,a+b INTO  OUTFILE  '/tmp/result.text' FIELDS  TERMINATED  BY  ','  OPTIONALLY  ENCLOSED  BY  '"' LINES  TERMINATED  BY  '\n' FROM  test_table;
 
1 mysqldump -uroot -proot 数据库名 数据表名 > tmp.txt 
 
1 2 3 4 #导出数据库 mysqldump -uroot -proot 数据库名 > tmp.txt #导入数据库(库名要先手动创建) mysql -u root -p database_name < tmp.txt 
 
 
1 mysqldump -h other-host.com -P port -u root -p database_name > dump.txt 
 
导入数据 
1 2 #导入数据库(库名要先手动创建) mysql -u root -p database_name < tmp.txt 
 
1 2 3 4 CREATE  DATABASE  abc;USE  abc;SET  NAMES  utf8;SOURCE /tmp/tmp.txt 
 
1 LOAD  DATA  LOCAL  INFILE  'dump.txt'  INTO  TABLE  mytbl;
 
LeetCode题解 
1179. Reformat Department Table 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # Write your MySQL query statement below select  id , max (case  when  month ='Jan'  then  revenue end ) as  Jan_Revenue,max (case  when  month ='Feb'  then  revenue end ) as  Feb_Revenue,max (case  when  month ='Mar'  then  revenue end ) as  Mar_Revenue,max (case  when  month ='Apr'  then  revenue end ) as  Apr_Revenue,max (case  when  month ='May'  then  revenue end ) as  May_Revenue,max (case  when  month ='Jun'  then  revenue end ) as  Jun_Revenue,max (case  when  month ='Jul'  then  revenue end ) as  Jul_Revenue,max (case  when  month ='Aug'  then  revenue end ) as  Aug_Revenue,max (case  when  month ='Sep'  then  revenue end ) as  Sep_Revenue,max (case  when  month ='Oct'  then  revenue end ) as  Oct_Revenue,max (case  when  month ='Nov'  then  revenue end ) as  Nov_Revenue,max (case  when  month ='Dec'  then  revenue end ) as  Dec_Revenuefrom  departmentgroup  by  id 
 
 
 
Mysql b树与b+树对比 
b+树的非叶子结点存储数据,所有相对于b树的结点,b+树的非叶子结点可以存储更多的索引,这样b+树会更矮更宽。 
b+树每次操作都是o(logn)时间复杂度,是稳定的,b树的时间复杂度在o(1)~o(logn)之间。 
b+树的所有叶子结点被链表串起来,更适合范围查询。 
 
为什么数据库普遍不用红黑树作索引 
为什么数据库一般不用hash表作索引 
hash表在单词查询是时间复杂度是o(1),但是在范围查询时是o(n),数据库经常需要范围查询。 
 
STL为什么用红黑树实现map、set,不用平衡二叉树。 
平衡二叉树维护树完全平衡,但是这样就给每次操作带来了较大的常数时间,所以采用大体上平衡的红黑树反而效率更高。 
 
参考