什么是数据库?
什么是关系型数据库?
有哪些常见的数据库管理系统?
SQL发展的简要历史
SQL语言分类
* 操作系统:CentOS 7
* MySQL版本:5.6
# 查看MySQL软件
rpm -qa | grep mysql
# 卸载MySQL
yum remove -y mysql mysql-libs mysql-common
rm -rf /var/lib/mysql
rm /etc/my.cnf
wget http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm
rpm -ivh mysql-community-release-el6-5.noarch.rpm
yum install -y mysql-community-server
vim /etc/my.cnf
修改内容如下:[mysqld]
# MySQL设置大小写不敏感,默认:区分表名的大小写,不区分列名的大小写
# 0:大小写敏感;1:大小写不敏感
lower_case_table_names=1
# 默认字符集
character-set-server=utf8mb4
systemctl start mysqld
# 设置root用户密码
/usr/bin/mysqladmin -u root password '123456'
# 登录MySQL
mysql -uroot -p
# 授予root用户对所有数据库对象的全部操作权限
grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;
# 关闭linux的防火墙
systemctl stop firewalld(默认)
systemctl disable firewalld.service(设置开机不启动)
-- 创建数据库
create database 数据库名;
create database 数据库名 character set 字符集;
-- 查看数据库
-- 查看数据库服务器中所有的数据库
show databases;
-- 查看某个数据库的定义信息
show create database 数据库名;
-- 删除数据库(慎用)
drop database 数据库名;
-- 其他数据库操作命令
-- 切换数据库
use 数据库名;
-- 查看正在使用的数据库
select database();
-- 创建表 ------------------------------------------------------------
create table 表名(
字段名 类型(长度) 约束,
字段名 类型(长度) 约束,
...
);
-- 主键约束:primary key
-- 唯一约束:unique
-- 非空约束:not null
-- 注意:主键约束 = 唯一约束+非空约束
-- 查看表 ------------------------------------------------------------
-- 查看数据库中所有的表
show tables;
-- 查看表结构
desc 表名;
-- 删除表 ------------------------------------------------------------
drop table 表名;
-- 修改表 ------------------------------------------------------------
-- 修改表——添加列
alter table 表名 add 列名 类型(长度) 约束;
-- 修改表——修改列的类型、长度和约束
alter table 表名 modify 列名 类型(长度) 约束;
-- 修改表——修改列名
alter table 表名 change 旧列名 新列名 类型(长度) 约束;
-- 修改表——删除列
alter table 表名 drop 列名;
-- 修改表名
rename table 表名 to 新表名;
-- 修改表的字符集
alter table 表名 character set 字符集;
- 数字型:int
- 浮点型:double
- 字符型:varchar(可变长字符串)
- 日期类型:date(只有年月日,没有时分秒),datetime(年月日,时分秒)
- boolean类型:不支持,一般使用 tinyint 替代(值为0和1)
分类 | 类型名称 | 说明 |
---|---|---|
整数类型 | tinyint | 很小的整数 |
smallint | 小的整数 | |
mediumint | 中等大小的z整数 | |
int(integer) | 普通大小的整数 | |
小数类型 | float | 单精度浮点数 |
double | 双精度浮点数 | |
小数类型 | decimal(m, d) | 压缩严格的定点数–开发时用 |
日期类型 | year | YYYY 1901~2155 |
time | HH:MM:SS -838:59:59~838:59:59 | |
date | YYYY-MM-DD 1000-01-01~9999-12-3 | |
datetime-开发用 | YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00~9999-12-31 23:59:59 | |
timestamp | YYYY-MM-DD HH:MM:SS 1970-01-01 00:00:01UTC~2038-01-19 03:14:07UTC | |
文本、二进制类型 | CHAR(M) | M 为0~255直接的整数 |
VARCHAR(M) | M 为0~65535直接的整数 | |
TINYBLOB | 允许长度0~255字节 | |
BLOB | 允许长度0~65535字节 | |
MEDIUMBLOB | 允许长度0~167772150字节 | |
LONGBLOB | 允许长度0~4294967296字节 | |
TINYTEXT | 允许长度0~255字节 |
-- 向表中插入某些列
insert into 表名 (列名1, 列名2, 列名3, ...) values (值1, 值2, 值3, ...);
-- 向表中插入所有列
insert into 表名 values (值1, 值2, 值3, ...);
insert into 表名 (列名1, 列名2, 列名3, ...) values select (列名1, 列名2, 列名3, ...) from 表名;
insert into 表名 values select * from 表名;
- 列名数与values后面的值的个数相等
- 列的顺序与插入的值的顺序一致
- 列名的类型与插入的值要一致
- 插入值的时候不得超过最大长度
- 值如果是字符串或者日期需要加 '' 号(一般是单引号)
update 表名 set 字段名1 = 值1, 字段名2 = 值2 [where 条件];
- 列名的类型要和修改的值要一致
- 修改值的时候不能超过最大长度
- 值如果是字符串或者日期需要加 '' 号
delete from 表名 [where 条件];
-- 创建商品表
create table products(
pid int primary key auto_increment comment '商品自增主键id',
pname varchar(20) comment '商品名称',
price double comment '商品价格',
pdate datetime comment '日期',
sid varchar(20) comment '分类ID'
);
-- 添加一些数据
insert into products (pname, price, pdate, sid) values('泰国大榴莲', 98, '2018-01-01', 's001');
insert into products (pname, price, pdate, sid) values('新疆大枣', 38, '2018-11-23', 's002');
insert into products (pname, price, pdate, sid) values('新疆切糕', 68, '2019-02-25', 's003');
insert into products (pname, price, pdate, sid) values('十三香', 10, '2017-12-3', 's004');
insert into products (pname, price, pdate, sid) values('老干妈', 20, '2019-03-05', 's005');
SELECT DISTINCT
<select_list>
FROM
<left_table> <join_type>
JOIN <right_table> ON <join_condition>
WHERE
<where_condition>
GROUP BY
<group_by_list>
HAVING
<having_condition>
ORDER BY
<order_by_condition>
LIMIT <limit_number>
-- 查询所有商品
select * from products;
-- 查询商品名称和商品价格
select pname, price from products;
-- 别名查询,使用as关键字,as可以省略
-- 表别名
select * from products as p;
-- 列别名
select pname as pn from products;
-- 去重复值
select distinct price from products;
-- 查询结果是表达式(运算查询):将所有商品的价格加10进行显示
select pname, price+10 from products;
-- 查询商品名称为十三香的商品所有信息
select * from products where pname = '十三香';
-- 查询商品价格大于60元的所有商品信息
select * from products where price > 60;
>、<、=、>=、<=、<>:大于、小于、等于、大于等于、小于等于、不等于
like:使用占位符 _ 和 %
_ 代表一个字符
% 代表任意个字符
in:在某个范围中获得值(exists)
分类 | 类型名称 | 说明 |
---|---|---|
整数类型 | >、<、=、>=、<=、<> | 大于、小于、等于、大于等于、小于等于、不等于 |
BETWEEN … AND … | 显示在某一区间的值(含头含尾) | |
IN(set) | 显示in列表中的值,例:in(100, 200) | |
LIKE ‘张_’ | 模糊查询,like语句中,%代表零个或多个任意字符,_代表一个字符 | |
IS NULL | 判断是否为空 | |
逻辑运算符 | and | 多个条件同时成立 |
or | 多个条件任一成立 | |
not | 不成立 |
-- 查询所有商品,按价格进行排序
select * from products order by price;
-- 查询名称有【新】的商品信息,并按价格降序排序
select * from products where pname like '%新%' order by price desc;
-- 获取所有商品的价格的总和
select sum(price) from products;
-- 获得所有商品的平均价格
select avg(price) from products;
-- 获得所有商品的个数
select count(*) from products;
-- 根据sid字段分组,分组后统计商品的个数
select sid, count(*) from products group by sid;
-- 根据sid字段分组,分组统计每组商品的平均价格,并且平均价格大于60
select sid, avg(price) from products group by sid having avg(price) > 60;
* select语句中的列(非聚合函数列),必须出现在 group by 子句中
* group by 子句中的列,不一定要出现在 select 语句中
* 聚合函数只能出现在 select 语句中,或者 having 语句中,一定不能出现在 where 语句中
* 逻辑分页:将数据库中的数据查询到内存之后再进行分页
* 物理分页:通过 LIMIT 关键字,直接在数据库中进行分页,最终返回的数据只是分页后的数据
* 子查询允许把一个查询嵌套在另一个查询当中
* 子查询,又叫内部查询,相当于内部查询,包含内部查询的就称为外部查询
* 子查询可以包含普通的 select,可以包含任何子句,比如:distinct、group by、order by、limit、join和union等
* 但是对应的外部查询必须是以下语句之一:select、insert、update、delete
SELECT DISTINCT
<select_list>
FROM
<left_table> <join_type>
JOIN <right_table> ON <join_condition>
WHERE
<where_condition>
GROUP BY
<group_by_list>
HAVING
<having_condition>
ORDER BY
<order_by_condition>
LIMIT <limit_number>
1. FROM <left_table>
2. ON <join_condition>
3. <join_type> JOIN <right_table> 第2步和第3步会循环执行
4. WHERE <where_condition> 第4步会循环执行,每个条件的执行顺序是从左往右的
5. GROUP BY <group_by_list>
6. HAVING <having_condition>
7. SELECT DISTINCT <select_list> 分组之后才会执行 SELECT
8. ORDER BY <order_by_condition>
9. LIMIT <limit_number> LIMIT是MySQL独有的语法
-- 创建数据库
create database testQuery;
use testQuery;
-- 创建测试表
create table table1(
uid varchar(10) not null,
name varchar(10) not null,
primary key(uid)
)engine=innodb default charset=utf-8;
create table table2(
oid int not null auto_increment,
uid varchar(10),
primary key(oid )
)engine=innodb default charset=utf-8;
-- 插入数据
insert into table1(uid, name) values('aaa', 'mike'), ('bbb', 'jack'), ('ccc', 'mike'), ('ddd', 'mike');
insert into table2(uid) values('aaa'), ('aaa'), ('bbb'), ('bbb'), ('bbb'), ('ccc'), (NULL);
select a.uid, count(b.oid) as total
from table1 as a
left join table2 as b on a.uid = b.uid
where a.name = 'mike'
group by a.uid
having count(b.oid) < 2
order by total desc
limit 1;
OUTER JOIN(比如left join、right join)
,那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚表VT3
。虚表VT3
进行WHERE条件过滤,只有符合的记录才会被插入到虚拟表VT4
中。虚表VT5
。虚表VT7
中的重复列,并删除。如果在查询中指定了DISTINCT子句,则会创建一张内存临时表(如果内存放不下,就需要存放在硬盘了),这样临时表的表结构和上一步产生的虚表VT7
是一样的,不同的是对进行DISTINCT操作的列增加了一个唯一索引,以此来去除重复数据。虚表VT8
中选出从指定位置开始的指定行数据* FROM(将最近的两张表,进行笛卡尔积)---VT1
* ON(将VT1按照它的条件进行过滤)---VT2
* LEFT JOIN(保留左边表的记录)---VT3
* WHERE(过滤VT3中的记录)---VT4...VTn
* GROUP BY(对VT4的记录进行分组)---VT5
* HAVING(对VT5中的记录进行过滤)---VT6
* SELECT(对VT6中的记录,选取指定的列)---VT7
* ORDER BY(对VT7的记录进行排序)---VT8
* LIMIT(对排序之后的值进行分页)
* 单表查询:根据WHERE条件过滤表中的数据,形成中间表(这个中间表对用户是不可见的);然后根据SELECT的选择列选择相应的列进行返回最终结果。
* 两表连接查询:对两表求积并用ON条件和连接类型进行过滤形成中间表;然后根据WHERE条件过滤中间表的记录,并根据SELECT指定列的返回结果
* 多表连接查询:先对第一个和第二个表按照两表连接查询,然后用查询结果和第三个表连接查询,以此类推,直到所有的表都连接上为止,最终形成一个中间的结果表,然后根据WHERE条件过滤中间表的记录,并根据SELECT指定列的返回结果
* MySQL:从左往右执行WHERE条件
* Oracle:从右往左执行WHERE条件
-- 如何操作外键
-- 主表添加外键
alter table 表名 add [constraint][约束名称] foreign key (主表外键字段) references 从表(从表主键);
-- 主表删除外键
alter table 表名 drop foreign key 外键约束名称
CREATE TABLE wife(
id INT PRIMARY KEY ,
wname VARCHAR(20),
sex CHAR(1)
);
CREATE TABLE husband(
id INT PRIMARY KEY ,
hname VARCHAR(20),
sex CHAR(1)
);
ALTER TABLE husband ADD wid INT UNIQUE;
// 添加外键约束
alter table husband add foreign key (wid) references wife(id);
* 在商品表中添加一条记录,该记录的cid在分类表中不存在。
* 在分类表中,删除一条记录,这条记录在商品表中有外键关联。
* 用户和角色
* 1个用户对多个角色、1个角色对多个用户
* 中间表用户角色表 uid rid
create table category(
cid varchar(32) primary key,
cname varchar(100)
) charset = utf8 comment = '分类表';
create table product(
pid varchar(32) primary key,
pname varchar(40),
price double,
cid varchar(32)
) charset = utf8 comment = '商品表';
create table orders(
oid varchar(32) primary key,
totalprice double
) charset = utf8 comment = '订单表';
create table order_item(
oid varchar(32) primary key,
pid varchar(50)
) charset = utf8 comment = '订单项表';
insert into category(cid, cname) values('c001', '家电'), ('c002', '服装'), ('c003', '化妆品');
insert into product(pid, pname, price, cid) values('p001', '联想', 5000, 'c001'), ('p002', '海尔', 3000, 'c001'), ('p003', '雷神', 5000, 'c001'), ('p004', '阿迪', 1000, 'c002'), ('p005', '耐克', 1200, 'c002'), ('p006', 'NB', 800, 'c002'), ('p007', '彪马', 600, 'c002'), ('p008', '雪花秀', 1500, 'c003'), ('p009', '悦诗风吟', 1100, 'c003');
-- 隐式交叉连接
select * from A, B
-- 显示交叉连接
select * from A CROSS JOIN B
-- 隐式内连接
select * from A, B where A.id = B.id
-- 显示内连接
select * from A INNER B ON A.id = B.id
* 通过业务需求,分析主从表
* 如果使用 LEFT JOIN,则主表在左边
* 如果使用 RIGHT JOIN,则主表在右边
* 查询结果以主表为主,从表记录匹配不到,则补null
* 全外连接(FULL JOIN)MySQL不支持