Mysql
- 登陆
mysql -uroot -p
- 退出
exit quit
- 链接远程
mysql -h127.0.0.1 -uroot -p
- 启动mysql服务
sudo ./support-files/mysql.server start
DDL
创建
create database dbtest;
create database if not exists dbtest2;
//指定字符集
create database if not exists dbtest3 character set gbk;
create table student(
id int,
name varchar(32),
age int,
score double(4,1),
birthday date,
insert_time timestamp
);
create table student1 like student;
查询
SHOW DATABASES
show create databases mysql;
show tables
desc user;
show create table newStudent;
修改
alter database dbtest3 character set utf8;
alter table student rename to newStudent;
alter table newStudent character set gbk;
alter table newStudent add gender varchar(10);
alter table newStudent change gender sex varchar(20);
alter table newStudent modify sex varchar(5);
alter table newStudent drop sex;
删除
drop database dbtest;
drop database dbtest2 if exists;
drop table if exists student1;
使用
select database();
use dbtest3
DML
增加数据
INSERT INTO student(id, `name`, age) VALUES (1, 'zhangsan', 20);
INSERT INTO student VALUES (2, 'lisi', 20, 132.3, NULL, NULL);
INSERT INTO student VALUES (3, 'huangliu', 20, 132.3, "1892-11-12", NULL);
INSERT INTO student VALUES (3, 'huangliu', 20, 132.3, "1892-11-12", CURRENT_TIMESTAMP);
删除数据
DELETE FROM student WHERE id=1
- 删除数据后新增数据导致主键不连续的解决方法,删除后执行,或者添加前执行
ALTER TABLE sys_user AUTO_INCREMENT = 1
TRUNCATE TABLE student;
修改数据
UPDATE student set age = 22, score = 233.4 WHERE id = 4
DQL
基本查询
SELECT * FROM student;
SELECT name, age FROM student;
SELECT DISTINCT score FROM student;
SELECT name, age, score, age + score FROM student;
//有null的归零
SELECT name, age, score, age + IFNULL(score,0) FROM student;
SELECT name, age, score, age + IFNULL(score,0) AS 总分 FROM student;
SELECT name, age math, score, age + IFNULL(score,0) 总分 FROM student;
条件查询
//大于
SELECT * FROM student WHERE age > 20;
//不等于 != 也可以
SELECT * FROM student WHERE age <> 31;
//并列
SELECT * FROM student WHERE age > 20 AND age < 40;
//包括20和30
SELECT * FROM student WHERE age BETWEEN 20 and 40;
//或者
SELECT * FROM student WHERE age = 20 OR age = 31;
SELECT * FROM student WHERE age IN (20, 35, 41);
SELECT * FROM student WHERE birthday IS NULL;
SELECT * FROM student WHERE birthday IS NOT NULL;
SELECT * FROM student WHERE `name` LIKE '_ad%';
//姓名是四个字符
SELECT * FROM student WHERE `name` LIKE '____';
//包含w
SELECT * FROM student WHERE `name` LIKE '%w%';
排序查询
//降序
SELECT * FROM student ORDER BY age DESC;
//第一个排序一样时,才会执行第二个条件
SELECT * FROM student ORDER BY age ASC, score DESC;
聚合函数
- 将一列数据作为整体,进行纵向的计算
- 排除了非空的数据,一般选择非空的列
- 数量
SELECT COUNT(`name`) FROM student;
//处理空值
SELECT COUNT(IFNULL(birthday,"0000-00-00")) 数量 FROM student;
SELECT COUNT(*) FROM student;
SELECT MAX(score) FROM student;
SELECT MIN(score) FROM student;
SELECT SUM(score) FROM student;
SELECT AVG(score) FROM student;
分组查询
- 分组之后查询的字段:分组字段、聚合函数
- 把某一字段相同的内容取出分组
SELECT age, AVG(score) FROM student GROUP BY age;
SELECT age, AVG(score), COUNT(id) FROM student GROUP BY age;
//在分组前进行条件限定
SELECT age, AVG(score), COUNT(id) FROM student WHERE score > 100 GROUP BY age;
//在分组后进行条件限定
SELECT age, AVG(score), COUNT(id) FROM student WHERE score > 100 GROUP BY age HAVING COUNT(id) > 1;
//别名判断
SELECT age, AVG(score), COUNT(id) number FROM student WHERE score > 100 GROUP BY age HAVING number > 1;
where在分组前进行限定,如果不满足条件,则不参与分组;不可以进行聚合函数的判断
having在分组之后进行限定,如果不满足结果,则不会被查询;可以进行聚合函数的判断
分页查询
SELECT * FROM student LIMIT 0,3;
- 开始的索引 = (当前的页码 - 1) * 每页显示的条数
DCL
- 定义数据库权限、创建用户
DBA数据库管理员
- 查询,切换到
mysql数据库
SELECT * FROM `user`;
CREATE USER '用户名'@'主机' IDENTIFIED BY '密码';
CREATE USER 'zhangsan'@'localhost' IDENTIFIED BY '123456789';
// %表示可以在任意主机使用用户登陆数据库
CREATE USER 'lisi'@'%' IDENTIFIED BY '123456789';
DROP USER 'zhangsan'@'localhost';
ALTER user 'lisi'@'%' IDENTIFIED BY '987654321';
权限管理
SHOW GRANTS FOR 'lisi'@'%';
//给lisi授予查询dbtest3.Commpany的查看权限
GRANT SELECT ON dbtest3.Commpany TO 'lisi'@'%';
GRANT SELECT, DELETE,UPDATE ON dbtest3.Commpany TO 'lisi'@'%';
//授予所有权限
GRANT ALL ON *.* TO 'zhangsan'@'localhost';
//撤销lisi对dbtest3.Commpany的更新权限
REVOKE UPDATE ON dbtest3.Commpany FROM 'lisi'@'%';
//撤销所有权限
REVOKE ALL ON *.* FROM 'zhangsan'@'localhost';
约束
- 对表中的数据进行限定,保证数据的正确性、有效性和完整性
主键约束
primary key
- 非空且唯一
- 复合主键,不能重复
PRIMARY KEY (rid, uid)
- 一张表只能有一个字段为主键,表中记录的唯一标识
CREATE TABLE per (
id INT PRIMARY KEY,
`name` VARCHAR(20) NOT NULL UNIQUE
);
ALTER TABLE per DROP PRIMARY KEY;
ALTER TABLE per MODIFY id INT PRIMARY KEY;
- 自动增长,每次插入都会自加1,不成功也会,插入语句时不需要给主键值
CREATE TABLE per (
id INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(20) NOT NULL UNIQUE
);
ALTER TABLE per MODIFY id INT;
ALTER TABLE per MODIFY id INT AUTO_INCREMENT;
非空约束
not null
- 不能为空,插入数据时,不能为空值
CREATE TABLE per (
id INT,
`name` VARCHAR(20) NOT NULL
);
ALTER TABLE per MODIFY `name` VARCHAR(20);
ALTER TABLE per MODIFY `name` VARCHAR(20) NOT NULL;
唯一约束
CREATE TABLE per (
id INT,
`name` VARCHAR(20) NOT NULL UNIQUE
);
ALTER TABLE per DROP INDEX `name`;
ALTER TABLE per MODIFY `name` VARCHAR(20) UNIQUE;
外键约束
foreign key
- 格式
CONSTRAINT 外键名 FOREIGN KEY (外键列名称 本表的字段) REFERENCES 要关联的表的名称(主键名称)
- 让表与表产生关联,从而保证数据的正确性
CREATE TABLE Department (
id INT PRIMARY KEY AUTO_INCREMENT,
dep_name VARCHAR(30) NOT NULL,
dep_location VARCHAR(30) NOT NULL
);
CREATE TABLE Employee (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL UNIQUE,
age INT NOT NULL,
dep_id INT,
CONSTRAINT emp_dep_fk FOREIGN KEY (dep_id) REFERENCES Department(id)
);
ALTER TABLE Employee DROP FOREIGN KEY emp_dep_fk;
ALTER TABLE Employee ADD CONSTRAINT emp_dep_fk FOREIGN KEY (dep_id) REFERENCES Department(id);
级联操作
- 要先删除外键约束,重新添加
- 更新和删除,可以单独设置,也可以同时设置
- 级联更新,改变被关联的表,原表内容也会被改变
ALTER TABLE Employee ADD CONSTRAINT emp_dep_fk FOREIGN KEY (dep_id) REFERENCES Department(id) ON CASCADE;
ALTER TABLE Employee ADD CONSTRAINT emp_dep_fk FOREIGN KEY (dep_id) REFERENCES Department(id) ON UPDATE CASCADE;
多表查询
- 要完成多表查询,要消除无用的数据
- 查询所有,笛卡尔积,由两个集合AB,取这两个集合的所有组成情况
SELECT * FROM employee, dept;
内连接查询
SELECT * FROM employee, dept WHERE employee.dept_id = dept.id
SELECT employee.name, dept.name, gender FROM employee, dept WHERE employee.dept_id = dept.id
//专业版
SELECT
t1.name, t2.name, t1.gender
FROM
employee t1, dept t2
WHERE
t1.dept_id = t2.id
SELECT * FROM employee INNER JOIN dept ON employee.dept_id = dept.id;
//INNER 省略
SELECT * FROM employee JOIN dept ON employee.dept_id = dept.id;
外连接查询
- 左外连接查询,查询的是左表所有的数据以及与右表的交集
SELECT
t1.*, t2.`name`
FROM
employee t1
LEFT JOIN
dept t2
ON
t1.dept_id = t2.id;
- 右外连接查询,查询的是右表所有的数据以及与左表的交集
SELECT
t1.*, t2.`name`
FROM
employee t1
RIGHT JOIN
dept t2
ON
t1.dept_id = t2.id;
子查询
- 查询中嵌套查询,嵌套的查询为子查询
- 子查询的结果是单行单列的,大于小于等于的单一条件,一个条件,一个类型的返回
SELECT * FROM employee WHERE employee.salary = (SELECT MAX(salary) FROM employee);
//查询比平均工资少的
SELECT * FROM employee WHERE employee.salary < (SELECT AVG(salary) FROM employee);
- 子查询的结果是多行单列的,多个条件,一种类型的返回
SELECT * FROM employee WHERE dept_id IN (SELECT id FROM dept WHERE name = '财务部' OR name = '市场部');
SELECT * FROM employee WHERE dept_id IN (SELECT id FROM dept WHERE name IN ('财务部', '市场部'));
- 子查询的结果是多行多列的,多个条件,多个类型的返回,子查询可以作为虚拟表
SELECT * FROM dept t1, (SELECT * FROM employee WHERE employee.join_date > '2013-08-29') t2
WHERE t1.id = t2.dept_id;
事务
- 如果一个包含多个步骤的操作被事务管理,要么同时成功提交事物,要么失败进行回滚
- Mysql事务中默认自动提交,一条DML语句会自动提交一次事务;
Oracle数据库默认手动提交
- 修改事务的默认提交方式
SELECT @@autocommit;
SET @@autocommit = 0;
START TRANSACTION
COMMIT
ROLLBACK
四大特征
- 原子性,是不可分割的最小操作单位,要么同时成功,要么同时失败
- 持久性,当事务提交或回滚后,数据库会持久化得保存数据
- 隔离性,多个事务之间,相互独立
- 一致性,事务操作前后,数据总量不变,例
转钱操作中,两个人的钱合起来是永远不变的
隔离级别
- 如果多个事务操作同一批数据,会引发一些问题,设置不同的隔离级别就可以解决这些问题
- 问题
脏读,一个事务读取到另一个事务没有提交的数据
不可重复读(虚读),在同一个事务中,两次读取到的数据不一样
幻读,一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,但第一个事务查询不到自己的修改
read uncommitted 读未提交 产生的问题 脏读、不可重复读、幻读
read committed 读已提交,处理的过程中的变化数据不可读 产生的问题 不可重复读、幻读(Oracle默认)
repeatable read 可重复读 产生的问题 幻读(mysql默认)
serializable 串行化,多线程加锁 解决的所有问题
SELECT @@transaction_isolation;
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
数据库
数据库的设计
一对一的关系
- 正反都相对应,人和身份证
- 在任意一方添加外键,指向另一张表的主键,为外键添加唯一约束
一对多的关系
- 部门和员工
- 在多的一方建立外键,指向一的一方的主键,员工的部分外键指向部门
多对多的关系
- 学生和课程/老师
- 需要借助第三张表,中间表至少包含两个字段,这两个字段作为中间表的外键,分别指向两张表的主键
案例
- 旅游网页,多个线路对应一个类别,多个线路被多个用户收藏

CREATE TABLE tab_category (
cid INT PRIMARY KEY AUTO_INCREMENT,
cname VARCHAR(100) NOT NULL UNIQUE
);
CREATE TABLE tab_route(
rid INT PRIMARY KEY AUTO_INCREMENT,
rname VARCHAR(100) NOT NULL UNIQUE,
price DOUBLE,
rdate DATE,
cid INT,
FOREIGN KEY (cid) REFERENCES tab_category(cid)
);
CREATE TABLE tab_user (
uid INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(100) NOT NULL UNIQUE,
PASSWORD VARCHAR(30) NOT NULL,
NAME VARCHAR(100),
birthday DATE,
sex CHAR(1) DEFAULT '男',
telephone VARCHAR(11),
email VARCHAR(100)
);
CREATE TABLE tab_favorite (
rid INT,
DATE DATETIME,
uid INT,
PRIMARY KEY (rid, uid),
FOREIGN KEY (rid) REFERENCES tab_route(rid),
FOREIGN KEY (uid) REFERENCES tab_user(uid)
);
数据库范式
- 递次规范
- 第一范式,每一列都是不可分割的原子数据项
- 第二范式,非码属性必须完全依赖于候选码,在1NF的基础上清除非主属性对主码的部分函数依赖,表中总有一个属性或者属性组,能决定其他所有属性
- 第三范式,在2NF的基础上,任何非主属性不依赖于其他非主属性,消除传递依赖
概念
- 函数依赖,如果A属性的值可以确定唯一的B数据,则B依赖于A,例如
学号依赖于姓名
- 完全函数依赖,如果A是一个属性组,B的确定依赖于A属性组的所有属性,例如
学号+课程名称决定分数,分数完全依赖学号+课程名称
- 部分函数依赖,如果A是一个属性组,B属性值的确定,只需要依赖A属性组的某一些属性,例如
学号+课程中,只需要学号就可以确定姓名,姓名部分依赖于A
- 传递函数依赖,如果通过A的属性(属性组)的值,可以唯一确定B属性的值,又可以通过B属性(属性组)的值,唯一确定C的值,则C传递函数依赖于A,例如
姓名和学号可以确定系,系可以确定系主任
- 码,一张表中,一个属性或者属性组,可以确定其他所有属性,例如
学号+课程名称可以确定成绩、系、姓名等
- 主属性:码属性组中的所有属性
- 非主属性,非码属性的所有属性
备份与还原
命令行
mysqldump -uroot -p123456789 dbtest3 > /Users/apple/Desktop/test/my.sql
//先创建,再还原资源
create database dbtest3;
use dbtest3;
source /Users/apple/Desktop/test/my.sql;