1. 概述
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。
摘自:百度百科
2. 安装(Mac版)
-
双击开始安装
- 备注:安装过程会生成随机的root密码,需要保存起来
安装结束后,到系统偏好设置里启动MySQL服务
-
配置环境变量
- vim ~/.bash_profile
- 配置变量
export PATH=$PATH:/usr/local/mysql/bin
- source ~/.bash_profile 生效命令
-
登录mysql,输入之前安装时生成的密码
mysql -u root -p
-
修改密码
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123456');
-
重置密码
- 先关闭MySQL服务
- 切换当前目录到mysql安装目录 bin下
- 调用 sudo ./mysqld_safe --skip-grant-tables 将自动重启mysql,这时可以免密登录
- 打开另外一个终端,直接用执行mysql,登录mysql
- 输入:mysql> FLUSH PRIVILEGES; 清除无密登录设置
- SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123456'); 设置密码,即可
配置支持中文
到/etc 路径下新建配置文件
vim my.cnf
输入
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates
[client]
default-character-set=utf8
[mysqld]
character-set-server=utf8
[myisamchk]
key_buffer_size = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
保存后,重新启动服务即可
- 其他系统安装可以参考:Linux和Windows MYSQL安装教程
3. 常用基础命令
- 登录命令
mysql -u<name> -p<password>
或
mysql -u <name> -p (后续提示输入密码)
- 退出mysql命令模式
exit;
- 查寻数据库中所有的数据库
show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
- 选中其中一个数据库进行操作
use <db name>;
- 显示数据库下所有的表
show tables;
- 查看表结构
describe <tableName>
- 创建数据库
create database <db name>
- 创建表
CREATE TABLE <table name> (<property name> <type>, <property name> <type>, ...);
- 插入数据(增)
INSERT INTO <table name> VALUES (<property>, <property>, ...);
- 删除数据
DELETE FROM <table name> <condition>;
- 修改数据
UPDATE <table name> SET <property>=<value> <condition>;
- 查询数据
SELECT <propertys> FROM <table name> <condition>;
-
去重查寻
select distinct <propertys> from <table name>;
-
查寻某字段满足或条件
select <propertys> from <table name> where <property> in (value1,value2,...);
或
select <propertys> from <table name> where <property>=value1 or <property>=value2 or ...; -
查寻某字段处于某区间内
select <propertys> from <table name> where <property> between value1 and value2;
或
select <propertys> from <table name> where <propery> > value1 and <propery> < value2; -
升序查寻
select * from <table name> order by <property> asc;
-
降序查寻
select * from <table name> order by <propery> desc;
-
联合字段升降序查寻
select * from <table name> order by <property1> desc, <property2> asc;
-
查寻条数
select count(<property>) from <table name> <condition>;
-
查寻字段最大值
select max(<property>) from <table name>;
-
查寻字段最小值
select min(<property>) form <table name>;
-
查寻某字段最大值整条记录
select * from <table name> order by <property> desc limit 0,1;
注:limit第一个表示起始位置,第二个表示个数
或
select * from <table name> where <property>=(select max<property> from <table name>); -
查寻某字段最小值整条记录
select * from <table name> order by <property> asc limit 0,1;
-
记算字段平均值
select avg(property) from <table name>;
-
分组查询
select <property> from <table name> group by <property>;
除了group by 的属性,必需保证查询的字段是数值是唯一的
group by 筛选--having
select <property> from <table name> group by <property> having <condition>; -
模糊查询
以x开头
select * from <table name> like 'x%';
以x结尾
select * from <table name> like '%x';
中间包含x
select * from <table name> like '%x%';
% 表示多个任意字母
_ 表示一个任意字母 -
多表查询
select <table name1>.<property1>,<table name2>.<property2> from <table name1>,<table name2> <conditions>
如果表之间的字段名不会相同的话,select 后面的字段名前的table name 可以省略。<conditions>这个条件需要包含各表之前的联系。 -
查询年 year
select year(<property>) from <table name>
-
使用正则表达式
select * from <table name> where <property> regexp <condition>;
-
字段拼接
select concat(<property1>,<property2>,...) from <table name>;
-
去空格函数
select concat(RTrim(<property1>),RTrim(<property2>) from <table name>;
RTrim 去除右边空格
LTrim 去除左边空格 -
union合并两个查询结果
select <property> from <table name> <condition>
union
select <property> from <table name> <condition>; -
any 和比较操作符一起使用,表示对比项只要any中的任意一项满足,则为true。
select * from <table name> where <property> > any(select <property> from <table name> where <condition>);
-
all 和经较符一起使用,表示对比项需要满足all中的所有项,才为true
select * from <table name> where <property> > all(select <property> from <table name> where <condition>);
-
复制表做条件查询
select * from <table name> a where <property> < (select avg(<property> from <table name> b where a.<property1>=b.<property1>)
-
取反模糊查询
select * from <table name> where not like <condition>;
- 修改表
alter table <table name> <operation>;
- 查看表创建语句
show create table <table name>;
- 使表支持中文
alter table <table name> convert to character set utf8;
- 清空表数据
truncate table <table name>;
- 删除数据库
drop database <database name>
4. 数据类型
-
数值类型
-
日期类型
-
字符串类型
char、varchar、text这三种类型比较:
(1)char: char 不用多说了,它是定长格式的,但是长度范围是 0~255. 当你想要储存一个长度不足 255 的字符时,Mysql 会用空格来填充剩下的字符。因此在读取数据时,char 类型的数据要进行处理,把后面的空格去除。
(2)varchar: 关于 varchar,有的说最大长度是 255,也有的说是 65535,查阅很多资料后发现是这样的:varchar 类型在 5.0.3 以下的版本中的最大长度限制为 255,而在 5.0.3 及以上的版本中,varchar 数据类型的长度支持到了 65535,也就是说可以存放 65532 个字节(注意是字节而不是字符!!!)的数据(起始位和结束位占去了3个字节),也就是说,在 5.0.3 以下版本中需要使用固定的 TEXT 或 BLOB 格式存放的数据可以在高版本中使用可变长的 varchar 来存放,这样就能有效的减少数据库文件的大小。
(3)text: 与 char 和 varchar 不同的是,text 不可以有默认值,其最大长度是 2 的 16 次方-1
总结起来,有几点:
经常变化的字段用 varchar
知道固定长度的用 char
尽量用 varchar
超过 255 字符的只能用 varchar 或者 text
能用 varchar 的地方不用 text
5. MySQL约束条件
1. 主键约束
定义:为属性添加一个约束可以唯一确定表中的一条记录,该属性不能重复也不能为空。
CREATE TABLE t_user (
id INT primary key,
name VARCHAR(20)
);
- 联合主键
定义:由多个属性组成主键,每个属性都不能为空,且每个属性不完全相同
CREATE TABLE t_user (
id INT,
name VARCHAR(20),
sex CHAR(1),
PRIMARY KEY(id, name)
);
//都可以成功插入数据
INSERT INTO t_user VALUES(1,'Jack','F');
INSERT INTO t_user VALUES(1,'Rose, 'M');
INSERT INTO t_user VALUES(2,'Jack;,'F');
// 无法插入数据
INSERT INTO t_user VALUES(null,'Machel','F');
- 修改主键约束
新增主键约束
alter table t_student add primary key(name);
// 或
alter table t_sutdent name varchar(20) primary key;
删除主键
alter table t_student drop primary key;
2. 自增约束
定义:属性设置自增约束后,插入数据时不需要带对应属性,其值会在最后一条记录的基础上加1。一般和主键约束一起全使用。
create table t_user2 (
id int primary key auto_increment,
name varchar(20)
);
insert into t_user2(name) values('James');
//可以指定id但是不能重复
insert into t_user2 values(4,'Jack');
3、唯一约束
定义:字段添加唯一约束后,表中该字段的所有值不能重复。和主键的区别为,唯一约束值可以为空。比如实际场景中用户的身份证。
create table t_user3 (
id int primary key auto_increment,
name varchar(20) unique
);
// 或者
create table t_user3 (
id int primary key auto_increment,
name varchar(20),
unique(name)
);
使用alter进行修改
/* add*/
alter table t_user3 add unique(name);
alter table t_user3 modify name varchar(20) unique;
/* delete*/
alter table t_user3 drop index name;
- 联合唯一
定义:由多个属性组成唯一性,属性可以为空,且每个属性不完全相同(都为空例外)
create table t_user3 (
id int primary key auto_increment,
name varchar(20),
psw varchar(20),
unique(name,psw)
);
4. 非空约束
定义:定义字段不能为空。
create table t_user4 (
id int primary key auto_increment,
account varchar(30) not null,
password varchar(30 not null
);
5. 默认约束
定义:插入一条记录,如果字段没有写入值,则会自动填充设好的默认值。
create table t_user5 {
id int primary key auto_increment,
name varchar(30),
password varchar(30) default '123456'
}
6. 外键约束
定义:一个字段的值为另一张表的主键,该约束值可以重重,也可以为空。
作用:保持数据的一致性。1、从表外键字段不能插入主表主键字段没有的值 2、主表不能直接删除被从表引用的记录
/*主表*/
create table t_class (
id int primary key auto_increment,
name varchar(30) unique not null
);
/*从表*/
create table t_student (
id int primary key auto_increment,
name varchar(30) not null,
classid int,
foreign key(classid) references t_class(id)
);
6.设计范式
1. 第一范式
设计表时,每个字段都具有原子特性,不可分割。比如:地址字段设计成一个字段,那就不满足该条件,因为这个字段可以分为:国家、省、城市、区、门牌号等。
这一原则并不是一定要遵守:
1、好处是当你要去查数据时,可以对数据进行更加祥细的分类。
2、坏外是如果你需要查的数据为各个字段的组合,你需要每次进拼接等额外操作。
这里总结为 字段原子范式。
2. 第二范式
满足第一范式的前提下,设计表时,表中的每个字段都必须依赖于主键,不能只依赖于主键的一部分(联合主键的情况)。
Eg:
有一张订单表如下:t_order 主键为联合主键(id, product_id)
id | product_id | customer_id | product_name | customer_name |
---|
因为product_name 是完全不依赖于主键的,只与product_id相关,这就不满足第二范式。为此我们应该把进行拆表来满足这个设计范式。
订单表:t_order:
id | product_id | customer_id |
---|
商品表:t_product
product_id | product_name |
---|
顾客表:t_customer
customer_id | customer_name |
---|
这样就满足了第二设计范式了。
这里总结为:主键完全依赖范式
3. 第三范式
满足第二范式的前提下,要求表中的每个字段都必须直接依赖于主键,而不是间接依赖。
Eg:
表t_order 中product_name 和主键并没有直接的依赖,而是依赖于表中product_id的值,就不满足第三范式
id | product_id | product_name | customer |
---|
我们需要修改下:
id | product_id | customer |
---|
商品表:t_product
product_id | product_name |
---|
这样子就使表中的每个字段都是直接依赖于主键了。
这里总结为:主键非间接依赖范式
7. 事务
定义
事务是mysql执行任务的最小单位。
事务提交
事务提交后将对之前执行的sql语句进行持久化,数据将无法回滚,当前事务结束
- 自动提交
自动提交开启后,每次执行一条sql语句后,都将马上提交并且返回结果。
查看自动提交状态select @@autocommit;
默认是开启的。
设置自动提交配置
0 为关闭 1 为开启
set autocommit=0;
- 手动提交
手动提交为在执行完一些sql语句后,手动调用命令进行提交
命令:commit;
事务回滚
事务回滚,可以把未提交的sql语名执行结果进行撤销。
命令:
rollback;
手动开启事务
在自动提交的状态下,也可以开启手动提交事务。
命令:
begin;
或
start transaction;
事务的四大特征(ACID)
A: 原子性:事务是执行sql任务的最小单位,不可分割
C: 一致性:事务里面的sql语句执行结果是一致的,要么都成功,要么都失败
I: 隔离性:两个事务之间都是各自独立的
D: 持久性:事务一旦提交后,数据交被持久化,回去回滚
隔离级别
-
mysql的隔离级别分为四种:
- read uncommitted;(可读取未提交内容)
事务A可以查询到事务B还未提交的事务的修改结果,如果事务B进行rollback操作后,会使事务A之前查询到的结果为错误的,这种现象称为 脏读。 - read committed;(可读取已提交内容)
可以解决脏读问题,事务A只可以查询到事务B已经提交后的数据,这就会造成事务A在事务B提交前和提交后查询的结果不一致,这种情况称为 不可重复读 - repeatable read;(可重读)
可以解决脏读、不可重复读的问题,但是会出现幻读。分别开启事务A和事务B,对当前数据进行查询,此时对事务B进行数据修改,然后提交。再次在事务A中对数据进行查询会发现的数据还是不变的,这种情况称为 幻读 - serializable;(可串行化)
完全锁住数据,当有事务A进行对数据进行修改时,其它事务要进行读写操作时,会进行等待,直到事务A提交结束。
越高的隔离级别问题越少,但是性能也相对应的会变得更差。
以下为各个隔离级别问题表
- read uncommitted;(可读取未提交内容)
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
read uncommitted | 1 | 1 | 1 |
read committed | 0 | 1 | 1 |
repeatable read | 0 | 0 | 1 |
serializable | 0 | 0 | 0 |
-
隔离级别的查询和设置
查询select @@tx_isolation;(8.0前)
select @@transation_isolation;(8.0后)
+------------------+
| @@tx_isolation |
+------------------+
| READ-UNCOMMITTED |
+------------------+设置
set session transaction isolation level read uncommitted;
8. 表的链接
1. 交叉连接 cross join
定义:交叉连接也叫叫笛卡尔积连接,第一张表是 a 的每条记录会和第二张表b 中的每条记录进行组合。
- 隐式交叉连接
select * from A, B;
- 显式交叉连接
select * from A cross join B;
2. 内连接 inner join
定义:内连接又叫等值连接,通过比较运算符根据表共有的列匹配出行
- 隐式内连接
select * from A, B where A.id=B.id;
- 显式内连接
select * from A inner join B on A.id=B.id;
3. 外连接 outer join
定义:外联接可以是左向外联接、右向外联接或完整外部联接。也就是说外连接又分为:左外连接、右外连接、全外连接。外连接需要有主表或者保留表的概念
通过业务需求,分析主从表
如果使用 LEFT JOIN ,则主表在它左边
如果使用 RIGHT JOIN ,则主表在它右边
查询结果以主表为主,从表记录匹配不到,则补 null
- 左外连接 left outer join 或 left join
select * from A left outer join B on A.id=B.id;
- 右外连接 right outer join 或 right join
select * from A right outer join B on
A.id=B.id; - 全外连接 mysql 不支持,可以通过union的方式实现
select * from A left outer join B on A.id=B.id
union
select * from A right outer join B on
A.id=B.id;