DML（data manipulation language）是数据操纵语言：它们是SELECT、UPDATE、INSERT、DELETE，就象它的名字一样，这4条命令是用来对数据库里的数据进行操作的语言。DDL（data definition language）是数据定义语言：DDL比DML要多，主要的命令有CREATE、ALTER、DROP等，DDL主要是用在定义或改变表（TABLE）的结构，数据类型，表之间的链接和约束等初始化工作上，他们大多在建立表时使用。DCL（DataControlLanguage）是数据库控制语言：是用来设置或更改数据库用户或角色权限的语句，包括（grant,deny,revoke等）语句。DMLDML操作中，DELETE FROM 可以通过SET autocommit = FALSE;来使用ROLLBACK，在commit之前能够回滚数据SELECTsql92语法：SELECT (distinct)....,....,....(存在聚合函数) FROM ...,....,.... WHERE 多表的连接条件 AND 不包含聚合函数的过滤条件 GROUP BY ...,.... HAVING 包含聚合函数的过滤条件 ORDER BY ....,...(ASC / DESC ) LIMIT ...,....sql99语法：除了GROUP BY和LIMIT外，其他位置都可以申明子查询SELECT (distinct) ....,....,....(存在聚合函数) FROM ... (LEFT / RIGHT)JOIN ....ON 多表的连接条件 (LEFT / RIGHT)JOIN ... ON .... WHERE 不包含聚合函数的过滤条件 GROUP BY ...,.... HAVING 包含聚合函数的过滤条件 ORDER BY ....,...(ASC / DESC ) LIMIT ...,....SQL语句的执行过程：FROM ...,...-> (LEFT/RIGNT JOIN) ->ON -> WHERE -> GROUP BY -> HAVING -> SELECT -> DISTINCT -> ORDER BY -> LIMIT数据增删改# 添加数据 INSERT INTO emp1[(字段名)] [ VALUES (4,'Jim',5000), (5,'张俊杰',5500); ]; [ # 直接插入查询结果 SELECT employee_id,last_name,salary,hire_date # 查询的字段一定要与添加到的表的字段一一对应 FROM employees WHERE department_id IN (70,60); ] # 更新数据 UPDATE emp1 SET hire_date = CURDATE(),salary = 6000 WHERE id = 4; # 删除 DELETE [emp1] FROM emp1 WHERE id = 1; # 不指定某行就情况整个表 # MySQL8的新特性：计算列 CREATE TABLE test1( a INT, b INT, c INT GENERATED ALWAYS AS (a + b) VIRTUAL #字段c即为计算列 ); 约束# 使用添加约束的方法 ADD CONSTRAINT constraint_name [UNIQUE(字段列表)] [UNIQUE KEY(字段列表);] / ADD UNIQUE KEY(字段列表);重点：非空约束 唯一性约束，主键约束，默认值约束# 建表时 CREATE TABLE 表名称( 字段名 数据类型, 字段名 数据类型 NOT NULL, 字段名 数据类型 [unique][unique key], 字段名 数据类型 primary key(字段名) [auto_increment], 字段名 数据类型 default 默认值, [[constraint 约束名] unique key(字段名)], / [unique key(字段列表)], primary key(字段列表) [auto_increment]# 复合主键 ); # 建表后 alter table 表名称 modify 字段名 数据类型 not null; alter table 表名称 modify 字段名 字段类型 unique; / alter table 表名称 add unique key(字段列表); ALTER TABLE 表名称 MODIFY [COLUMN] 字段名 字段类型 PRIMARY KEY; / ALTER TABLE 表名称 ADD PRIMARY KEY(字段列表); alter table 表名称 modify 字段名 数据类型 default 默认值; # 复合 ALTER TABLE 表名称 MODIFY [COLUMN] constraint 约束名 ...规范：VALUES 中字符串用''SELECT 中用字符串""Mysql在win中 字符串也忽视大小写取模%时，答案的正负只和被模数相关字符串隐式转化不成功的话，会被转成数值0LIKE 中 %代表0或多，_代表未知占位ESCAPE指定转义符and优先级高于or别名只能在ORDER BY中使用Mysql不支持sql92中外连接的+，也不支持sql99的FULL OUTER JOINSELECT出现的非组函数的字段必须声明在GROUP BY中，反之可以不出现。(不一定)聚合函数不能嵌套多行子查询的 IN（）中，如果子表中有NULL值，则任何值与其判断都会被判定为真在DRAP TABLE中 5.7和8.0的不同：5.7 中如果 DRAP TABLE book1,book2 若是book2不存在导致执行失败，book1也会被删除8.0 中 DRAP TABLE book1,book2 即便是book2不存在导致执行失败，book1也不会删除DESC table 中，int(4) 其中的4是包括了符号的，而float(5,2)，中的5是不包括符号的由于二进制不能准确表示小数，所以float和double都是不精准的，而DECIMAL是用字符串形式存储的DATETIME 和 TIMESTAMP的区别TIMESTAMP占用内存更小，可存储的范围更小TIMESTAMP中包含时区信息char 不存空格，而VARCHAR类型的字段数据时，会保留数据尾部的空格。char(5)，VARCHAR(5) 中的5皆代表字符数（SQL8.0）类型类型特点空间上时间上适用场景CHAR(M)固定长度浪费存储空间效率高存储不大，速度要求高VARCHAR(M)可变长度节省存储空间效率低非CHAR的情况BLOB和TEXT类型容易造成空间空洞sql中的“？”称为占位符，JAVA中的泛型中的"?"称为通配符sql中有个日期的隐式转换，它会把字符串"1999-1-1"自动转成Date类DDL# 创建库、表 CREATE DATABASE [IF NOT EXISTS] 数据库名 [CHARACTER SET 'UTF8'] CREATE TABLE dept01 [ (id INT(7), `name` VARCHAR(25)); ] [ AS SELECT * FROM atguigudb.`departments`; ] # 修改 ALTER TABLE emp01 [# 修改列 MODIFY last_name VARCHAR(50); DESC emp01; ] [# 增加列 ADD test_column VARCHAR(20); ] [# 删除列 DROP COLUMN department_id ] [# 重命名并重定义内部属性列 CHANGE department_name dept_name varchar(15); ] #删除表、库 DROP TABLE [IF EXISTS] emp01; DROP DATABASE [IF EXISTS] 数据库名; # 表重命名 RENAME TABLE emp02 TO emp01; / ALTER TABLE emp02 RENAME TO emp01 # 清空表 # DELETE FROM 可以通过SET autocommit = FALSE;来使用ROLLBACK，在commit之前能够回滚数据 TRUNCATE TABLE emp2; / DELETE FROM emp2; 阿里开发规范： 【参考】TRUNCATE TABLE 比 DELETE 速度快，且使用的系统和事务日志资源少，但 TRUNCATE 无 事务且不触发 TRIGGER，有可能造成事故，故不建议在开发代码中使用此语句。 说明：TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同。补充ALTER TABLE MODIFY和ALTER TABLE CHANGE的区别1、改列的类型而不是名称， CHANGE语法仍然要求旧的和新的列名称，即使旧的和新的列名称是一样的。例如： ALTER TABLE t1 CHANGE b b BIGINT NOT NULL.2、使用MODIFY来改变列的类型，此时不需要重命名：例如： ALTER TABLE t1 MODIFY b BIGINT NOT NULL。高级Linuxdesc 表名 显示某表信息，用于sql操作界面查看sql版本 sqladmin --versionsql的root若是想能够远程访问需要把mysql数据库中的user表中root对应的host列改成%，然后使用sql语句flush privileges刷新InnoDB优点支持外键可以处理事务如果更新、删除操作多，应使用InnoDB，它是为处理大数据量设计的可以进行行锁数据和索引合一自适应 Hash索引MyISam索引和数据分离InnoDb的不足写的处理效率差一些对内存要求高MyISAM的优点对SELECT、INSERT为主的应用处理速度更快有额外的常数存储，故count(*)的查询效率高MyISAM的不足不支持事务只支持表级锁崩溃后无法安全恢复分清聚簇索引、二级索引（非聚簇索引、辅助索引）、联合索引（非聚簇索引）聚簇索引：B+树的 叶子节点 存储的是完整的用户记录。二级索引：在建立聚簇索引B+树的基础上，再以每个列和主键构建一个二级索引B+树联合索引：是同时为多个列建立索引，比如C2,C3InnoDB的B+树索引的注意事项根页面位置万年不动数据从根节点向下复制衍生，根节点的物理位置不会变内节点中目录项记录的唯一性对二级索引或者联合索引来说，当对比的字段都一致时，要在目录页面（非叶子节点）中加入主键来做对比一个页面最少存储2条记录索引CREATE TABLE table_name [col_name data_type] [UNIQUE | FULLTEXT | SPATIAL] [INDEX | KEY] [index_name] (col_name [length]) [ASC | DESC]UNIQUE 、 FULLTEXT 和 SPATIAL 为可选参数，分别表示唯一索引、全文索引和空间索引；INDEX 与 KEY 为同义词，两者的作用相同，用来指定创建索引；index_name 指定索引的名称，为可选参数，如果不指定，那么MySQL默认col_name为索引名；col_name 为需要创建索引的字段列，该列必须从数据表中定义的多个列中选择；length 为可选参数，表示索引的长度，只有字符串类型的字段才能指定索引长度；ASC 或 DESC 指定升序或者降序的索引值存储。聚簇索引和非聚簇索引聚簇索引：B+树结构，且只有主键主键索引非聚簇索引：可能是B+树结构，有主键和其他列（就算以一个列做索引也会自动带上主键的）普通索引二级索引：在建立聚簇索引B+树的基础上，再以每个列和主键构建一个二级索引B+树联合索引：是同时为多个列建立索引，比如C2,C3前缀索引：把很长字段的前面的公共部分作为一个索引，order by不支持前缀索引回表：指类似二级索引某列后，再通过主键去主键索引出其他列信息ps 全文索引只能用在char类pss MyISAM无论主键索引还是二级索引都是非聚簇索引，而InnoDB的主键索引是聚簇索引，二级索引是非聚簇索引。我们自己建的索引基本都是非聚簇索引查看MySQL语句有没有用到索引EXPLAIN SELECT * FROM employees.titles WHERE emp_no='10001' AND title='Senior Engineer' AND from_date='1986-06-26';最左前缀原则where查询中，被查询得越频繁的越应该放在最左边，mysql会向右一直匹配到(>、<、between、like)就停止匹配，因此只要检测到这些符号就不能用索引了MySQL 执行查询的过程客户端通过 TCP 连接发送连接请求到 MySQL 连接器，连接器会对该请求进行权限验证及连接资源分配查缓存。（当判断缓存是否命中时，MySQL 不会进行解析查询语句，而是直接使用 SQL 语句和客户端发送过来的其他原始信息。所以，任何字符上的不同，例如空格、注解等都会导致缓存的不命中。）语法分析（SQL 语法是否写错了）。 如何把语句给到预处理器，检查数据表和数据列是否存在，解析别名看是否存在歧义。优化。是否使用索引，生成执行计划。交给执行器，将数据保存到结果集中，同时会逐步将数据缓存到查询缓存中，最终将结果集返回给客户端。三范式第一范式：行不重复，列不可再分字段不可分，每个字段是原子级别的，第一个字段为ID，它就是ID不能在分成两个字段了，不能说我要把这个人的ID、名称、班级号都塞在一个字段里面，这个是不合适的，对以后的应用造成很大影响第二范式：非主依主表必须符合第一范式，非主键列必须依赖主键列。每个表只描述一个事情有主键，非主键字段依赖主键，ID字段就是主键，它能表示这一条数据是唯一的，其中“unique”表示唯一的、不允许重复的，确实它经常会修饰某个字段，保证该字段唯一性，然后再设置该字段为主键；第三范式：非主独立非主键列之间不能有依赖关系非主键字段不能相互依赖，这个怎么理解呢，比如student表，班级编号受人员编号的影响，如果在这个表中再插入班级的班主任、数学老师等信息，你们觉得这样合适吗？肯定不合适，因为学生有多个，这样就会造成班级有多个，那么每个班级的班主任、数学老师都会出现多条数据，而我们理想中的效果应该是一条班级信息对应不同的任课老师，这样更易于我们理解，这样就形成class表，那么student表和class表和teacher表中间靠哪个字段来关联呢，肯定是通过class表中的"studentNo和"teacherNo"对其进行关联，这个字段也叫做两个表的外键；事务MySQL 的四种隔离级别Read Uncommitted（读取未提交内容）在该隔离级别，所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用，因为它的性能也不比其他级别好多少。读取未提交的数据，也被称之为脏读（Dirty Read）。Read Committed（读取提交内容）这是大多数数据库系统的默认隔离级别（但不是 MySQL 默认的）。它满足了隔离的简单定义：一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓 的 不可重复读（Nonrepeatable Read），因为同一事务的其他实例在该实例处理其间可能会有新的 commit，所以同一 select 可能返回不同结果。Repeatable Read（可重读）这是 MySQL 的默认事务隔离级别，它确保同一事务的多个实例在并发读取数据时，会看到同样的数据行。不过理论上，这会导致另一个棘手的问题：幻读 （Phantom Read）。Serializable（可串行化）通过强制事务排序，使之不可能相互冲突，从而解决幻读问题。简言之，它是在每个读的数据行上加上共享锁。在这个级别，可能导致大量的超时现象和锁竞争。脏读：事务 A 读取了事务 B 更新的数据，然后 B 回滚操作，那么 A 读取到的数据是脏数据不可重复读：事务 A 多次读取同一数据，事务 B 在事务 A 多次读取的过程中，对数据作了更新并提交，导致事务 A 多次读取同一数据时，结果 不一致。幻读：系统管理员 A 将数据库中所有学生的成绩从具体分数改为 ABCDE 等级，但是系统管理员 B 就在这个时候插入了一条具体分数的记录，当系统管理员 A 改结束后发现还有一条记录没有改过来，就好像发生了幻觉一样，这就叫幻读。日志类型REDO LOG重做日志 ，提供再写入操作，恢复提交事务修改的页操作，用来保证事务的持久性。先将原始数据从磁盘中读入内存中来，修改数据的内存拷贝生成一条重做日志并写入redo log buffer，记录的是数据被修改后的值当事务commit时，将redo log buffer中的内容刷新到 redo log file，对 redo log file采用追加 写的方式定期将内存中修改的数据刷新到磁盘中UNDO LOG回滚日志 ，回滚行记录到某个特定版本，用来保证事务的原子性、一致性。在 MySQL innodb 存储引擎中用来实现多版本并发控制，这个方法叫做MVCC，本质是乐观锁的实现每个事务只会使用一个回滚段，一个回滚段在同一时刻可能会服务于多个事务。当一个事务开始的时候，会制定一个回滚段，在事务进行的过程中，当数据被修改时，原始的数据会被复制到回滚段。在回滚段中，事务会不断填充盘区，直到事务结束或所有的空间被用完。如果当前的盘区不够用，事务会在段中请求扩展下一个盘区，如果所有已分配的盘区都被用完，事务会覆盖最初的盘 区或者在回滚段允许的情况下扩展新的盘区来使用。回滚段存在于undo表空间中，在数据库中可以存在多个undo表空间，但同一时刻只能使用一个 undo表空间。当事务提交时，InnoDB存储引擎会做以下两件事情： 将undo log放入列表中，以供之后的purge操作 判断undo log所在的页是否可以重用，若可以分配给下个事务使用binlog：记录所有数据库表结构变更（例如 CREATE、ALTER TABLE）以及表数据修改（INSERT、UPDATE、DELETE）的二进制日志。MVCCMVCC 的实现依赖于：隐藏字段、Undo Log、Read ViewInnoDB 每一行数据都有一个隐藏的回滚指针，用于指向该行修改前的最后一个历史版本，这个历史版本存放在 undo log 中。如果要执行更新操作，会将原记录放入 undo log 中，并通过隐藏的回滚指针指向 undo log 中的原记录。其它事务此时需要查询时，就是查询 undo log 中这行数据的最后一个历史版本。MVCC 最大的好处是读不加锁，读写不冲突，极大地增加了 MySQL 的并发性。通过 MVCC，保证了事务 ACID 中的 I（隔离性）特性锁需要注意的是对于 InnoDB 引擎来说，读锁和写锁可以加在表上，也可以加在行上。读锁 ：也称为 共享锁 、英文用 S 表示。针对同一份数据，多个事务的读操作可以同时进行而不会 互相影响，相互不阻塞的。写锁 ：也称为 排他锁 、英文用 X 表示。当前写操作没有完成前，它会阻断其他写锁和读锁。这样 就能确保在给定的时间里，只有一个事务能执行写入，并防止其他用户读取正在写入的同一资源。表锁。开销小，加锁快；不会出现死锁；锁定粒度大，发生锁冲突的概率最高，并发度最低。行锁。开销大，加锁慢；会出现死锁；锁定粒度最小，发生锁冲突的概率最低，并发度也最高。在MySQL中只有InnoDB存储引擎可以使用行锁。lock table有如下两种表达方式：lock table xxx read，只读方式锁住xxx，该表只能被select，不能被修改。如果在lock时，该表上存在事务，则lock语句挂起，直到事务结束。多个会话可以同时对表执行该操作。lock table xxx write，读写方式锁住xxx，lock table的会话可以对表xxx做修改及查询等操作，而其他会话不能对该表做任何操作，包括select也要被阻塞。可以同时锁住多个表。隔离级别与锁的关系在Read Uncommitted级别下，读取数据不需要加共享锁，这样就不会跟被修改的数据上的排他锁冲突在Read Committed级别下，读操作需要加共享锁，但是在语句执行完以后释放共享锁；在Repeatable Read级别下，读操作需要加共享锁，但是在事务提交之前并不释放共享锁，也就是必须等待事务执行完毕以后才释放共享锁。SERIALIZABLE 是限制性最强的隔离级别，因为该级别锁定整个范围的键，并一直持有锁，直到事务完成。一些函数笔记1.计算日期差datediff(a.日期, b.日期) = 1 #a比b大一天2.四舍五入select round(1123.26723,2); #保留两位小数