1. 数据库介绍
1.1. 数据库概述
- 数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作。
- 随着互联网的高速发展,大量的数据在不断的产生,伴随而来的是如何高效安全的存储数据和操作数据,而这一问题成为了信息时代的一个非常大的问题。
- 使用数据库可以高效的有条理的储存数据:
- 可以结构化存储大量的数据,(这个大量是相对来说大,和大数据的数仓没法比)
- 可以有效的保持数据的一致性、完整性。
1.2. 常见数据库
- 数据库又分为关系型数据库和非关系型数据库
- 常用数据库:MYSQL,Oracle,Redis,Hbase
|
数据库类型 |
数据库 |
介绍 |
|
关系型数据库 |
MYSQL |
开源免费的数据库,中型的数据库.已经被Oracle收购了.MySQL6.x版本也开始收费。 |
|
Oracle |
收费的大型数据库,Oracle公司的产品。Oracle收购SUN公司,收购MYSQL。 |
|
|
DB2 |
IBM公司的数据库产品,收费的。常应用在银行系统中. |
|
|
SQLServer |
MicroSoft 公司收费的中型的数据库。C#、.net等语言常使用。 |
|
|
SQLite |
嵌入式的小型数据库,应用在手机端。 |
|
|
非关系型数据库
|
Redis |
是一个小而美的数据库,主要用在key-value 的内存缓存,读写性能极佳 |
|
HBase |
HBase是列式数据库,目标是高效存储大量数据 |
|
|
MongoDB |
MongoDB是文档型数据库,非常接近关系型数据库的。 |
2. MySql数据库安装和使用
2.1. MySql安装
我建议用Linux安装MySQL8.0 安装步骤
安装文档在博客标签里找
2.2. 登录MySQL数据库
MySQL是一个需要账户名密码登录的数据库,登陆后使用,它提供了一个默认的root账号,使用安装时设置的密码即可登录,有两种登录方式。
方式1:
mysql -uroot -p
下面输密码输入直接回车密码不会显示的
或者
mysql -uroot -p密码
mysql --host=ip地址 --user=用户名 --password=密码
登录成功是这个鸭子

2.3. MySQL图形化开发工具-DataGrip



2.4. MySQL图形化开发工具-SQLyog


3.1. SQL概述
3.2. SQL语句介绍
结构化查询语言(Structured Query Language)简称SQL,是关系型数据库管理系统都需要遵循的规范,是数据库认识的语句。不同的数据库生产厂商都支持SQL语句,但都有特有内容。
- 普通话:各数据库厂商都遵循的ISO标准。
- 方言:数据库特有的关键字。

3.3. SQL语句分类
SQL分类:
- 数据定义语言:简称DDL(Data Definition Language),用来定义数据库对象:数据库,表,列等。关键字:create,alter,drop等
- 数据操作语言:简称DML(Data Manipulation Language),用来对数据库中表的记录进行更新。关键字:insert,delete,update等
- 数据控制语言:简称DCL(Data Control Language),用来定义数据库的访问权限和安全级别,及创建用户。
- 数据查询语言:简称DQL(Data Query Language),用来查询数据库中表的记录。关键字:select,from,where等
3.4. SQL通用语法
- SQL语句可以单行或多行书写,以分号结尾
- 可使用空格和缩进来增强语句的可读性
- MySQL数据库的SQL语句不区分大小写,关键字建议使用大写例如:SELECT * FROM user。
- 同样可以使用/**/的方式完成注释 -- #
- MySQL中的我们常使用的数据类型如下
#创建数据库 -- 创建数据库如果存在就报错 -- create database 数据库名; CREATE DATABASE demo; -- 创建数据库如果数据库不存在就创建,如果存在就啥也不干 CREATE DATABASE IF NOT EXISTS demo; -- 创建数据库并在创建数据库时插入字符集 -- create database 数据库名 character set 字符集 CREATE DATABASE demo CHARACTER SET UTF-8; ##查看MySQL服务器中的数据库 SHOW DATABASES; ##查看数据库中的表在数据库下 SHOW TABLES;
# 查看正在使用的数据库
select database();
##查看表结构 -- desc 表名
##删除数据库 -- drop database 数据库名; DROP DATABASE demo; SHOW DATABASES; -- 发现数据库demo不见了 -- 为了做实验我们在给创回来 CREATE DATABASE demo; ##使用数据库 -- use 数据库名; USE demo; ## 查看正在使用的数据库 SELECT DATABASE(); ## 创建数据库的数据表if not exists 作用和创建数据库时的作用一样 -- create table if not exists 表名(字段名 字段类型[长度] 约束 ); CREATE TABLE puser( pid VARCHAR(20) PRIMARY KEY, pname VARCHAR(20), page INT ) -- primary key 主键,被主键修饰字段中的数据,不能重复、不能为null。 ##查看表结构 -- desc 表名 DESC puser; ##删除表 DROP TABLE puser; -- 为了实验还是把上面的表建回来 #修改表结构 -- alter table 表名 类类型【长度】 约束; -- 为表添加一个字段 ALTER TABLE puser ADD psex VARCHAR(10); -- 改变表字段 ALTER TABLE puser CHANGE psex 性别 VARCHAR(5); -- 删除表中的一列 ALTER TABLE puser DROP 性别; -- 该变表名 RENAME TABLE puser TO tuser; # 表的插入操作 -- 向表中插入某些字段 -- insert into 表 (字段1,字段2,字段3..) values(值1,值2,值3..); -- 向表中插入所有字段,字段的顺序为创建表时的顺序 -- insert into 表 values(值1,值2,值3..) ## 注意内容和字段 INSERT INTO tuser(pid,pname,page) VALUES('111','zhangsan',33); INSERT INTO tuser VALUES('222','wangwu',66); -- 一次插入多个值 INSERT INTO tuser VALUES('333','赵六',33),('444','钱七',33); # 更新表记录:update -- 更新符号条件记录的指定字段 -- update 表名 set 字段名=值,字段名=值,... where 条件; UPDATE tuser SET page = 18 WHERE pname = '钱七'; -- 列名的类型与修改的值要一致. -- 修改值得时候不能超过最大长度. -- 除了数值类型外,其它的字段类型的值必须使用引号引起 # 删除记录:delete -- 删除表中的一条记录 当然也也以根据需求删除多行记录 DELETE FROM tuser WHERE pid='111'; -- 清空表数据 TRUNCATE tuser; ## 主键约束 -- 方式一:创建表时,在字段描述处,声明指定字段为主键: CREATE TABLE Persons1 ( Id INT PRIMARY KEY, LastName VARCHAR(255), FirstName VARCHAR(255), Address VARCHAR(255), City VARCHAR(255) ) -- 方式二:创建表时,在constraint约束区域,声明指定字段为主键 -- 格式:[constraint 名称] primary key (字段列表) -- 关键字constraint可以省略,如果需要为主键命名,constraint不能省略,主键名称一般没用。 -- 字段列表需要使用小括号括住,如果有多字段需要使用逗号分隔。声明两个以上字段为主键,我们称为联合主键 CREATE TABLE Persons2 ( FirstName VARCHAR(255), LastName VARCHAR(255), Address VARCHAR(255), City VARCHAR(255), CONSTRAINT pk_PersonID PRIMARY KEY (FirstName, LastName) ) ## 删除主键约束 ALTER TABLE Persons DROP PRIMARY KEY; ## 自动增长列 -- 我们通常希望在每次插入新记录时,数据库自动生成字段的值。 -- 我们可以在表中使用 auto_increment(自动增长列)关键字,自动增长列类型必须是整形,自动增长列必须为键(一般是主键) CREATE TABLE Persons4 ( Id INT PRIMARY KEY AUTO_INCREMENT, LastName VARCHAR(255), FirstName VARCHAR(255), Address VARCHAR(255), City VARCHAR(255) ) -- 向persons添加数据时,可以不为Id字段设置值,也可以设置成null,数据库将自动维护主键值 INSERT INTO Persons (FirstName,LastName) VALUES ('Bill','Gates') INSERT INTO Persons (Id,FirstName,LastName) VALUES (NULL,'Bill','Gates') -- 默认AUTO_INCREMENT 的开始值是 1,如果希望修改起始值,请使用下列 SQL 语法 ALTER TABLE Persons AUTO_INCREMENT=100 ##非空约束 -- NOT NULL 约束强制列不接受 NULL 值。 -- NOT NULL 约束强制字段始终包含值。这意味着,如果不向字段添加值,就无法插入新记录或者更新记录。 -- 下面的 SQL 语句强制 "Id" 列和 "LastName" 列不接受 NULL 值 CREATE TABLE Persons5 ( Id INT NOT NULL, LastName VARCHAR(255) NOT NULL, FirstName VARCHAR(255), Address VARCHAR(255), City VARCHAR(255) ) ## 唯一约束 -- UNIQUE 约束唯一标识数据库表中的每条记录。 -- UNIQUE 和 PRIMARY KEY 约束均为列或列集合提供了唯一性的保证。 -- PRIMARY KEY 拥有自动定义的 UNIQUE 约束。 -- 请注意,每个表可以有多个 UNIQUE 约束,但是每个表只能有一个 PRIMARY KEY 约束。 -- 添加唯一约束 -- 创建表时,在字段描述处,声明唯一: CREATE TABLE Persons ( Id INT UNIQUE, LastName VARCHAR(255) NOT NULL, FirstName VARCHAR(255), Address VARCHAR(255), City VARCHAR(255) ) # DQL数据查询语言 -- 准备工作 #创建商品表: CREATE TABLE product( pid INT PRIMARY KEY, pname VARCHAR(20), price DOUBLE, category_id VARCHAR(32) ); INSERT INTO product(pid,pname,price,category_id) VALUES(1,'联想',5000,'c001'); INSERT INTO product(pid,pname,price,category_id) VALUES(2,'海尔',3000,'c001'); INSERT INTO product(pid,pname,price,category_id) VALUES(3,'雷神',5000,'c001'); INSERT INTO product(pid,pname,price,category_id) VALUES(4,'杰克琼斯',800,'c002'); INSERT INTO product(pid,pname,price,category_id) VALUES(5,'真维斯',200,'c002'); INSERT INTO product(pid,pname,price,category_id) VALUES(6,'花花公子',440,'c002'); INSERT INTO product(pid,pname,price,category_id) VALUES(7,'劲霸',2000,'c002'); INSERT INTO product(pid,pname,price,category_id) VALUES(8,'香奈儿',800,'c003'); INSERT INTO product(pid,pname,price,category_id) VALUES(9,'相宜本草',200,'c003'); INSERT INTO product(pid,pname,price,category_id) VALUES(10,'面霸',5,'c003'); INSERT INTO product(pid,pname,price,category_id) VALUES(11,'好想你枣',56,'c004'); INSERT INTO product(pid,pname,price,category_id) VALUES(12,'香飘飘奶茶',1,'c005'); INSERT INTO product(pid,pname,price,category_id) VALUES(13,'海澜之家',1,'c002'); ## 简单查询 #1.查询所有的商品. SELECT * FROM product; #2.查询商品名和商品价格. SELECT pname,price FROM product; #3.别名查询.使用的关键字是as(as可以省略的). #3.1表别名: SELECT * FROM product AS p; #3.2列别名: SELECT pname AS pn FROM product; #4.去掉重复值. SELECT DISTINCT price FROM product; #5.查询结果是表达式(运算查询):将所有商品的价格+10元进行显示. SELECT pname,price+10 FROM product;
条件查询
|
比较运算符 |
> < <= >= = <> != |
大于、小于、大于(小于)等于、不等于 |
|
BETWEEN ...AND... |
显示在某一区间的值(含头含尾) |
|
|
IN(set) |
显示在in列表中的值,例:in(100,200) |
|
|
LIKE ‘张%’ LIKE ‘%涛%’ |
模糊查询,Like语句中, %代表零个或多个任意字符, _代表一个字符, 例如:first_name like ‘_a%’; |
|
|
IS NULL IS NOT NULL |
判断是否为空 |
|
|
逻辑运算符 |
and |
多个条件同时成立 |
|
or |
多个条件任一成立 |
|
|
not |
不成立,例:where not(salary>100); |
#查询商品名称为“花花公子”的商品所有信息: SELECT * FROM product WHERE pname = '花花公子'; #查询价格为800商品 SELECT * FROM product WHERE price = 800; #查询价格不是800的所有商品 SELECT * FROM product WHERE price != 800; SELECT * FROM product WHERE price <> 800; SELECT * FROM product WHERE NOT(price = 800); #查询商品价格大于60元的所有商品信息 SELECT * FROM product WHERE price > 60; #查询商品价格在200到1000之间所有商品 SELECT * FROM product WHERE price >= 200 AND price <=1000; SELECT * FROM product WHERE price BETWEEN 200 AND 1000; #查询商品价格是200或800的所有商品 SELECT * FROM product WHERE price = 200 OR price = 800; SELECT * FROM product WHERE price IN (200,800); #查询含有'霸'字的所有商品 SELECT * FROM product WHERE pname LIKE '%霸%'; #查询以'香'开头的所有商品 SELECT * FROM product WHERE pname LIKE '香%'; #查询第二个字为'想'的所有商品 SELECT * FROM product WHERE pname LIKE '_想%'; #查询没有分类的商品 SELECT * FROM product WHERE category_id IS NULL; #查询有分类的商品 SELECT * FROM product WHERE category_id IS NOT NULL; ## 排序查询 -- 通过order by语句,可以将查询出的结果进行排序。暂时放置在select语句的最后。 -- SELECT * FROM 表名 ORDER BY 排序字段 ASC|DESC; -- ASC 升序 (默认) -- DESC 降序 SELECT * FROM 表名 ORDER BY 排序字段 ASC|DESC; ASC 升序 (默认) DESC 降序 #1.使用价格排序(降序) SELECT * FROM product ORDER BY price DESC; #2.在价格排序(降序)的基础上,以分类排序(降序) SELECT * FROM product ORDER BY price DESC,category_id DESC; #3.显示商品的价格(去重复),并排序(降序) SELECT DISTINCT price FROM product ORDER BY price DESC; # 分组查询 -- 分组查询是指使用group by字句对查询信息进行分组。 -- 格式: -- SELECT 字段1,字段2… FROM 表名 GROUP BY分组字段 HAVING 分组条件; -- 分组操作中的having子语句,是用于在分组后对数据进行过滤的,作用类似于where条件。 -- having与where的区别: -- 1).having是在分组后对数据进行过滤.,where是在分组前对数据进行过滤 -- 2).having后面可以使用分组函数(统计函数),where后面不可以使用分组函数。 -- 实例: #1 统计各个分类商品的个数 SELECT category_id ,COUNT(*) FROM product GROUP BY category_id ; #2 统计各个分类商品的个数,且只显示个数大于1的信息 SELECT category_id ,COUNT(*) FROM product GROUP BY category_id HAVING COUNT(*) > 1; ## 分页查询 -- 分页查询在项目开发中常见,由于数据量很大,显示屏长度有限,因此对数据需要采取分页显示方式。 -- 例如数据共有30条,每页显示5条,第一页显示1-5条,第二页显示6-10条。 SELECT 字段1,字段2... FROM 表明 LIMIT M,N -- M: 整数,表示从第几条索引开始,计算方式 (当前页-1)*每页显示条数 -- N: 整数,表示查询多少条数据 -- SELECT 字段1,字段2... FROM 表明 LIMIT 0,5 -- SELECT 字段1,字段2... FROM 表明 LIMIT 5,5 #查询product表的前5条记录 SELECT * FROM product LIMIT 0,5; # insert into select语句 -- INSERT INTO SELECT 语句从一个表复制数据,然后把数据插入到一个已存在的表中。 -- 基本语法: -- INSERT INTO table2 -- SELECT column_name(s) -- FROM table1; -- 实例: CREATE TABLE product2( pid INT PRIMARY KEY, pname VARCHAR(20), price DOUBLE ); INSERT INTO product2 SELECT pid,pname,price FROM product WHERE category_id = 'c001';
8.聚合查询
#1 查询商品的总条数
SELECT COUNT(*) FROM product;
#2 查询价格大于200商品的总条数
SELECT COUNT(*) FROM product WHERE price > 200;
#3 查询分类为'c001'的所有商品的总和
SELECT SUM(price) FROM product WHERE category_id = 'c001';
#4 查询分类为'c002'所有商品的平均价格
SELECT AVG(price) FROM product WHERE category_id = 'c002';
#5 查询商品的最大价格和最小价格
SELECT MAX(price),MIN(price) FROM product;
9. 多表操作
实际开发中,一个项目通常需要很多张表才能完成。例如:一个商城项目就需要分类表(category)、商品表(products)、订单表(orders)等多张表。且这些表的数据之间存在一定的关系,接下来我们将在单表的基础上,一起学习多表方面的知识。

9.1. 表与表之间的关系
一对多关系:
常见实例:客户和订单,分类和商品,部门和员工.
一对多建表原则:在从表(多方)创建一个字段,字段作为外键指向主表(一方)的主键.


9.2. 外键约束
现在我们有两张表“分类表”和“商品表”,为了表明商品属于哪个分类,通常情况下,
我们将在商品表上添加一列,用于存放分类cid的信息,此列称为:外键

此时“分类表category”称为:主表,“cid”我们称为主键。“商品表products”称为:从表,category_id称
为外键。我们通过主表的主键和从表的外键来描述主外键关系,呈现就是一对多关系。
外键特点:
- 从表外键的值是对主表主键的引用。
- 从表外键类型,必须与主表主键类型一致
声明外键约束
语法:
alter table 从表 add [constraint] [外键名称] foreign key (从表外键字段名) references 主表 (主表的主键); |
[外键名称] 用于删除外键约束的,一般建议“_fk”结尾
alter table 从表 drop foreign key 外键名称
使用外键目的:保证数据完整性
9.3. 一对多操作

category分类表,为一方,也就是主表,必须提供主键cid
products商品表,为多方,也就是从表,必须提供外键category_id
###创建分类表 create table category( cid varchar(32) PRIMARY KEY , cname varchar(100) #分类名称 ); # 商品表 CREATE TABLE products ( pid varchar(32) PRIMARY KEY , name VARCHAR(40) , price DOUBLE , category_id varchar(32) ); #添加约束 alter table products add constraint product_fk foreign key (category_id) references category (cid);
#1 向分类表中添加数据 INSERT INTO category (cid ,cname) VALUES('c001','服装'); #2 向商品表添加普通数据,没有外键数据,默认为null INSERT INTO products (pid,pname) VALUES('p001','商品名称'); #3 向商品表添加普通数据,含有外键信息(category表中存在这条数据) INSERT INTO products (pid ,pname ,category_id) VALUES('p002','商品名称2','c001'); #4 向商品表添加普通数据,含有外键信息(category表中不存在这条数据) -- 失败,异常 INSERT INTO products (pid ,pname ,category_id) VALUES('p003','商品名称2','c999'); #5 删除指定分类(分类被商品使用) -- 执行异常 DELETE FROM category WHERE cid = 'c001';
10. 多表查询

CREATE TABLE category ( cid VARCHAR(32) PRIMARY KEY , cname VARCHAR(50) ); CREATE TABLE products( pid VARCHAR(32) PRIMARY KEY , pname VARCHAR(50), price INT, flag VARCHAR(2), #是否上架标记为:1表示上架、0表示下架 category_id VARCHAR(32), CONSTRAINT products_fk FOREIGN KEY (category_id) REFERENCES category (cid) );
#分类 INSERT INTO category(cid,cname) VALUES('c001','家电'); INSERT INTO category(cid,cname) VALUES('c002','服饰'); INSERT INTO category(cid,cname) VALUES('c003','化妆品'); #商品 INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p001','联想',5000,'1','c001'); INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p002','海尔',3000,'1','c001'); INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p003','雷神',5000,'1','c001'); INSERT INTO products (pid, pname,price,flag,category_id) VALUES('p004','JACK JONES',800,'1','c002'); INSERT INTO products (pid, pname,price,flag,category_id) VALUES('p005','真维斯',200,'1','c002'); INSERT INTO products (pid, pname,price,flag,category_id) VALUES('p006','花花公子',440,'1','c002'); INSERT INTO products (pid, pname,price,flag,category_id) VALUES('p007','劲霸',2000,'1','c002'); INSERT INTO products (pid, pname,price,flag,category_id) VALUES('p008','香奈儿',800,'1','c003'); INSERT INTO products (pid, pname,price,flag,category_id) VALUES('p009','相宜本草',200,'1','c003');
- 内连接查询(使用的关键字 inner join -- inner可以省略)
- 隐式内连接:select * from A,B where 条件; 这个不推荐效率太慢
- 显示内连接:select * from A inner join B on 条件;
- 外连接查询(使用的关键字 outer join -- outer可以省略)
- 左外连接:left outer join
- select * from A left outer join B on 条件;
- 右外连接:right outer join
- select * from A right outer join B on 条件;
#1.查询哪些分类的商品已经上架 #隐式内连接 SELECT DISTINCT c.cname FROM category c , products p WHERE c.cid = p.category_id AND p.flag = '1'; #内连接 SELECT DISTINCT c.cname FROM category c INNER JOIN products p ON c.cid = p.category_id WHERE p.flag = '1'; #2.查询所有分类商品的个数 #左外连接 INSERT INTO category(cid,cname) VALUES('c004','奢侈品'); SELECT cname,COUNT(category_id) FROM category c LEFT OUTER JOIN products p ON c.cid = p.category_id GROUP BY cname;
下面通过一张图说明连接的区别

嵌套查询 #3 子查询, 查询“化妆品”分类上架商品详情 #隐式内连接 SELECT p.* FROM products p , category c WHERE p.category_id=c.cid AND c.cname = '化妆品'; #子查询 ##作为查询条件 SELECT * FROM products p WHERE p.category_id = ( SELECT c.cid FROM category c WHERE c.cname='化妆品' ); ##作为另一张表 SELECT * FROM products p , (SELECT * FROM category WHERE cname='化妆品') c WHERE p.category_id = c.cid; #查询“化妆品”和“家电”两个分类上架商品详情 SELECT * FROM products p WHERE p.category_id in ( SELECT c.cid FROM category c WHERE c.cname='化妆品' or c.name='家电' );
MySql索引
概述
- 索引是 MySQL 中一种十分重要的数据库对象。它是数据库性能调优技术的基础,常用于实现数据的快速检索。
- 索引就是根据表中的一列或若干列按照一定顺序建立的列值与记录行之间的对应关系表,实质上是一张描述索引列的列值与原表中记录行之间一一对应关系的有序表。
在 MySQL 中,通常有以下两种方式访问数据库表的行数据:
- 顺序访问
- 顺序访问是在表中实行全表扫描,从头到尾逐行遍历,直到在无序的行数据中找到符合条件的目标数据。这种方式实现比较简单,但是当表中有大量数据的时候,效率非常低下。
- 索引访问
- 索引访问是通过遍历索引来直接访问表中记录行的方式。使用这种方式的前提是对表建立一个索引,在列上创建了索引之后,查找数据时可以直接根据该列上的索引找到对应记录行的位置,从而快捷地查找到数据。索引存储了指定列数据值的指针,根据指定的排序顺序对这些指针排序。
例如,在学生基本信息表 students 中,如果基于 student_id 建立了索引,系统就建立了一张索引列到实际记录的映射表,当用户需要查找 student_id 为 12022 的数据的时候,系统先在 student_id 索引上找到该记录,然后通过映射表直接找到数据行,并且返回该行数据。因为扫描索引的速度一般远远大于扫描实际数据行的速度,所以采用索引的方式可以大大提高数据库的工作效率。
- 索引的分类
根据存储方式的不同,MySQL 中常用的索引在物理上分为以下两类。
- B-树索引 B-树索引又称为 BTREE 索引,目前大部分的索引都是采用 B-树索引来存储的。B-树索引是一个典型的数据结构,基于这种树形数据结构,表中的每一行都会在索引上有一个对应值。因此,在表中进行数据查询时,可以根据索引值一步一步定位到数据所在的行。
- 哈希索引 哈希(Hash)一般翻译为“散列”,也有直接音译成“哈希”的,就是把任意长度的输入(又叫作预映射,pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。
- HASH 索引不是基于树形的数据结构查找数据,而是根据索引列对应的哈希值的方法获取表的记录行。
根据索引的具体用途,MySQL 中的索引在逻辑上分为以下 3 类:
- 普通索引 普通索引是最基本的索引类型,唯一任务是加快对数据的访问速度,没有任何限制。创建普通索引时,通常使用的关键字是 INDEX 或 KEY。
- 唯一性索引 唯一性索引是不允许索引列具有相同索引值的索引。如果能确定某个数据列只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字 UNIQUE 把它定义为一个唯一性索引。
- 创建唯一性索引的目的往往不是为了提高访问速度,而是为了避免数据出现重复。
- 主键索引 主键索引是一种唯一性索引,即不允许值重复或者值为空,并且每个表只能有一个主键。主键可以在创建表的时候指定,也可以通过修改表的方式添加,必须指定关键字 PRIMARY KEY。
方式1-直接创建 CREATE INDEX indexName ON mytable(username([length])); 如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length。 方式2-修改表结构(添加索引) ALTER table tableName ADD INDEX indexName(columnName) 方式3-创建表的时候直接指定 CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, INDEX indexName(username(length)) ); 11.3.1.2. 查询索引 #1、查看表中所有索引 SHOW INDEX FROM table_name; #2、查看数据库所有索引 SELECT * FROM mysql.`innodb_index_stats` a WHERE a.`database_name` = '数据库名'; #2、查看某一表索引 SELECT * FROM mysql.`innodb_index_stats` a WHERE a.`database_name` = '数据库名' and a.table_name like '%表名%'; 11.3.1.3. 删除索引 DROP INDEX [indexName] ON mytable; alter table mytable drop index indexName; 11.3.2. 唯一索引 它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式: 11.3.2.1. 创建索引: 方式1-直接创建 CREATE UNIQUE INDEX indexName ON mytable(username(length)) 方式2-修改表结构(添加索引) ALTER table mytable ADD UNIQUE [indexName] (username(length)) 方式3-创建表的时候直接指定 CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, UNIQUE [indexName] (username(length)) ); 11.3.2.2. 删除索引 DROP INDEX [indexName] ON mytable; alter table mytable drop index indexName;
11.4. 索引的使用原则和注意事项
虽然索引可以加快查询速度,提高 MySQL 的处理性能,但是过多地使用索引也会造成以下弊端:
- 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
- 除了数据表占数据空间之外,每一个索引还要占一定的物理空间。如果要建立聚簇索引,那么需要的空间就会更大。
- 当对表中的数据进行增加、删除和修改的时候,索引也要动态地维护,这样就降低了数据的维护速度。
- 对于那些在查询中很少使用或参考的列不应该创建索引。因为这些列很少使用到,所以有索引或者无索引并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度,并增大了空间要求。
12. MySql开窗函数
12.1. 概述
MySql在8.0的版本增加了对开窗函数的支持,终于可以在MySql使用开窗函数了。
开窗函数的语法结构:
#Key word :Partiton by & order by |
Mysql中支持的开窗函数有很多,这里重点给大家介绍三个:row_number(),rank()
,dense_rank()
12.1. 开窗函数介绍
row_number(),rank(),dense_rank()这三个函数都是用于返回结果集的分组内每行的排名
三者区别:
row_number:不管排名是否有相同的,都按照顺序1,2,3…..n
rank:排名相同的名次一样,同一排名有几个,后面排名就会跳过几次
dense_rank:排名相同的名次一样,且后面名次不跳跃

create table employee (empid int,ename varchar(20) ,deptid int ,salary decimal(10,2)); insert into employee values(1,'刘备',10,5500.00); insert into employee values(2,'赵云',10,4500.00); insert into employee values(2,'张飞',10,3500.00); insert into employee values(2,'关羽',10,4500.00); insert into employee values(3,'曹操',20,1900.00); insert into employee values(4,'许褚',20,4800.00); insert into employee values(5,'张辽',20,6500.00); insert into employee values(6,'徐晃',20,14500.00); insert into employee values(7,'孙权',30,44500.00); insert into employee values(8,'周瑜',30,6500.00); insert into employee values(9,'陆逊',30,7500.00);
对employee表中按照deptid进行分组,并对每一组的员工按照薪资进行排名:
SELECT empid, ename, deptid, salary, row_number() over (PARTITION BY deptid ORDER BY salary DESC) AS row_number1, rank() OVER (PARTITION BY deptid ORDER BY salary desc) AS rank2, dense_rank() OVER (PARTITION BY deptid ORDER BY salary desc) AS dense_rank3 FROM employee;
浙公网安备 33010602011771号