您好!此笔记的文本和代码以网盘形式分享于文末!
因个人能力有限,错误处欢迎大家交流和指正!基础部分内容简单,但多且零散!
"""
数据库 是一个可以在一台机器上独立工作的,并且可以给我们提供高效、
便捷的方式对数据进行增删改查的一种工具
数据库的优势:
1.程序稳定性:这样任意一台服务所在的机器崩溃了都不会影响数据和另外的服务。
2.数据一致性:所有的数据都存储在一起,所有的程序操作的数据都是统一的,
就不会出现数据不一致的现象
3.并发:数据库可以良好的支持并发,所有的程序操作数据库都是通过网络,
而数据库本身支持并发的网络操作,不需要我们自己写socket
4.效率:使用数据库对数据进行增删改查的效率要高出我们自己处理文件很多。
描述事物的符号记录称为数据,数据库即存放数据的仓库;
数据库是长期存放在计算机内、有组织、可共享的数据集合。
数据库中的数据按一定的数据模型组织、描述和储存,
具有较小的冗余度、较高的数据独立性和易扩展性,并可为各种 用户共享
科学地组织和存储数据,如何高效获取和维护数据成了关键--系统软件---数据库管理系统:
如mysql、oracle、PostgreSQL、SQL Server
数据库服务器、数据管理系统、数据库、表与记录的关系(重点):
记录:1 朱葛 13234567890 22(多个字段的信息组成一条记录,即文件中的一行内容)
表:userinfo,studentinfo,courseinfo(即文件)
数据库:db(即文件夹)
数据库管理系统:如mysql(是一个软件)
数据库服务器:一台计算机(对内存要求比较高)
总结:
数据库服务器-:运行数据库管理软件
数据库管理软件:管理-数据库
数据库:即文件夹,用来组织文件/表
表:即文件,用来存放多行内容/多条记录
数据库系统的特点:
1 数据结构化(如上图odboy_stu)
2 数据共享,冗余度低,易扩充
3 数据独立性高
4 数据由DBMS统一管理和控制
a:数据的安全性保护
b:数据的完整性检查
c:并发控制
d:数据库恢复
"""
"""
MySQL
关系型数据库需要有表结构,非关系型数据库是key-value存储的,没有表结构
关系型:如sqllite,db2,oracle,access,sql server,MySQL,
注意:sql语句通用
非关系型:mongodb,redis,memcache
MySQL是一个关系型数据库管理系统,在 WEB 应用方面,MySQL是最好的 RDBMS ,
mysql的安装、启动和下载
# mysql的账号操作
#进入mysql客户端
$mysql
mysql> select user(); #查看当前用户
mysql> exit # 也可以用\q quit退出
# 默认用户登陆之后并没有实际操作的权限
# 需要使用管理员root用户登陆
$ mysql -uroot -p # mysql5.6默认是没有密码的
#遇到password直接按回车键
mysql> set password = password('root'); # 给当前数据库设置密码
# 创建账号
mysql> create user 'eva'@'192.168.10.%' IDENTIFIED BY '123';# 指示网段
mysql> create user 'eva'@'192.168.10.5' # 指示某机器可以连接
mysql> create user 'eva'@'%' #指示所有机器都可以连接
mysql> show grants for 'eva'@'192.168.10.5';查看某个用户的权限
# 远程登陆
$ mysql -uroot -p123 -h 192.168.10.3
# 给账号授权
mysql> grant all on *.* to 'eva'@'%';
mysql> flush privileges; # 刷新使授权立即生效
# 创建账号并授权
mysql> grant all on *.* to 'eva'@'%' identified by '123'
SQL : 结构化查询语言
SQL语言主要用于存取数据、查询数据、更新数据和管理关系数据库系统.
1、DDL语句 数据库定义语言: 数据库、表、视图、索引、存储过程,
例如CREATE DROP ALTER
2、DML语句 数据库操纵语言: 插入数据INSERT、删除数据DELETE、
更新数据UPDATE、查询数据SELECT
3、DCL语句 数据库控制语言: 例如控制用户的访问权限GRANT、REVOKE
1. 操作文件夹(库)
增:create database db1 charset utf8;
查:show databases;
改:alter database db1 charset latin1;
删除: drop database db1;
2. 操作文件(表)
先切换到文件夹下:use db1
增:create table t1(id int,name char);
查:show tables;
改:alter table t1 modify name char(3);
alter table t1 change name name1 char(2);
删:drop table t1;
3. 操作文件中的内容(记录)
增:insert into t1 values(1,'egon1'),(2,'egon2'),(3,'egon3');
查:select * from t1;
改:update t1 set name='sb' where id=2;
删:delete from t1 where id=1;
清空表:
delete from t1; #如果有自增id,新增的数据,
仍然是以删除前的最后一样作为起始。
truncate table t1;数据量大,删除速度比上一条快,且直接从零开始.
*auto_increment 表示:自增
*primary key 表示:约束(不能重复且不能为空);加速查找
"""
"""
mysql中的存储引擎
mysql5.6支持的存储引擎包括InnoDB、MyISAM、MEMORY、CSV、BLACKHOLE、
FEDERATED、MRG_MYISAM、ARCHIVE、PERFORMANCE_SCHEMA。
其中NDB和InnoDB提供事务安全表
常用存储引擎及适用场景
InnoDB
用于事务处理应用程序,支持外键和行级锁。
有效的降低由删除和更新导致的锁定,还可以确保事务的完整提交和回滚.
MyISAM
如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,
并且对事务的完整性、并发性要求不高,那么可以选择这个存储引擎。
MyISAM
如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,
并且对事务的完整性、并发性要求不高,那么可以选择这个存储引擎。
# 查看当前的默认存储引擎:
#
# mysql> show variables like "default_storage_engine";
#
# 查询当前数据库支持的存储引擎
#
# mysql> show engines \G;
指定存储引擎建表
1、在建表时指定
mysql> create table ai(id bigint(12),name varchar(200)) ENGINE=MyISAM;
mysql> create table country(id int(4),cname varchar(50)) ENGINE=InnoDB;
也可以使用alter table语句,修改一个已经存在的表的存储引擎。
mysql> alter table ai engine = innodb;
2、在配置文件中指定
#my.ini文件
[mysqld]
default-storage-engine=INNODB
MySQL架构总共四层
1、最上层:授权认证安全;最上层的服务并不是MySQL独有的,
如:连接处理、授权认证、安全等。
2、第二层:查询解析、分析、优化、缓存以及所有的内置函数,包括大多数的MySQL的核心服务。
如:日期、时间、数学和加密函数,
所有的跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等
3、第三层:数据的存储和提取,包含了存储引擎,
4、第四层:存储数据、表信息、用户操作日志,包含了文件系统。
"""
"""
mysql支持的数据类型:
# MySQL支持所有标准SQL数值数据类型
严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),
以及近似数值数据类型(FLOAT、REAL和DOUBLE PRECISION)
关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。
# int整数示例
# 创建表一个是默认宽度的int,一个是指定宽度的int(5)
mysql> create table t1 (id1 int,id2 int(5));
Query OK, 0 rows affected (0.02 sec)
# 像t1中插入数据1,1
mysql> insert into t1 values (1,1);
Query OK, 1 row affected (0.01 sec)
# 可以看出结果上并没有异常
mysql> select * from t1;
+------+------+
| id1 | id2 |
+------+------+
| 1 | 1 |
+------+------+
1 row in set (0.00 sec)
# 那么当我们插入了比宽度更大的值,会不会发生报错呢?
mysql> insert into t1 values (111111,111111);
Query OK, 1 row affected (0.00 sec)
# 答案是否定的,id2仍然显示了正确的数值,没有受到宽度限制的影响
mysql> select * from t1;
+------------+--------+
| id1 | id2 |
+------------+--------+
| 0000000001 | 00001 |
| 0000111111 | 111111 |
+------------+--------+
2 rows in set (0.00 sec)
# 修改id1字段 给字段添加一个unsigned表示无符号
mysql> alter table t1 modify id1 int unsigned;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc t1;
+-------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id1 | int(10) unsigned | YES | | NULL | |
| id2 | int(5) | YES | | NULL | |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
# 当给id1添加的数据大于214748364时,可以顺利插入
mysql> insert into t1 values (2147483648,2147483647);
Query OK, 1 row affected (0.00 sec)
# 当给id2添加的数据大于214748364时,会报错
mysql> insert into t1 values (2147483647,2147483648);
ERROR 1264 (22003): Out of range value for column 'id2' at row 1
# 小数示例
# 创建表的三个字段分别为float,double和decimal参数表示一共显示5位,小数部分占2位
mysql> create table t2 (id1 float(5,2),id2 double(5,2),id3 decimal(5,2));
Query OK, 0 rows affected (0.02 sec)
# 向表中插入1.23,结果正常
mysql> insert into t2 values (1.23,1.23,1.23);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t2;
+------+------+------+
| id1 | id2 | id3 |
+------+------+------+
| 1.23 | 1.23 | 1.23 |
+------+------+------+
1 row in set (0.00 sec)
# 向表中插入1.234,会发现4都被截断了
mysql> insert into t2 values (1.234,1.234,1.234);
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from t2;
+------+------+------+
| id1 | id2 | id3 |
+------+------+------+
| 1.23 | 1.23 | 1.23 |
| 1.23 | 1.23 | 1.23 |
+------+------+------+
2 rows in set (0.00 sec)
# 向表中插入1.235发现数据虽然被截断,但是遵循了四舍五入的规则
mysql> insert into t2 values (1.235,1.235,1.235);
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from t2;
+------+------+------+
| id1 | id2 | id3 |
+------+------+------+
| 1.23 | 1.23 | 1.23 |
| 1.23 | 1.23 | 1.23 |
| 1.24 | 1.24 | 1.24 |
+------+------+------+
3 rows in set (0.00 sec)
# 建新表去掉参数约束
mysql> create table t3 (id1 float,id2 double,id3 decimal);
Query OK, 0 rows affected (0.02 sec)
# 分别插入1.234
mysql> insert into t3 values (1.234,1.234,1.234);
Query OK, 1 row affected, 1 warning (0.00 sec)
# 发现decimal默认值是(10,0)的整数
mysql> select * from t3;
+-------+-------+------+
| id1 | id2 | id3 |
+-------+-------+------+
| 1.234 | 1.234 | 1 |
+-------+-------+------+
1 row in set (0.00 sec)
# 当对小数位没有约束的时候,输入超长的小数,会发现float和double的区别
mysql> insert into t3 values (1.2355555555555555555,1.2355555555555555555,1.2355555555555555555555);
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from t3;
+---------+--------------------+------+
| id1 | id2 | id3 |
+---------+--------------------+------+
| 1.234 | 1.234 | 1 |
| 1.23556 | 1.2355555555555555 | 1 |
+---------+--------------------+------+
2 rows in set (0.00 sec)
# # 日期和时间类型
表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。
# # 字符串类型
字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。
CHAR 和 VARCHAR 类型类似,但它们保存和检索的方式不同
在存储或检索过程中不进行大小写转换
# # ENUM和SET类型
ENUM中文名称叫枚举类型,它的值范围需要在创建表时通过枚举方式显示。
ENUM只允许从值集合中选取单个值,而不能一次取多个值。
set类型可以允许值集合中任意选择1或多个元素进行组合。
# # mysql表的完整性约束
# NOT NULL :非空约束,指定某列不能为空;
# UNIQUE : 唯一约束,指定某列或者几列组合不能重复
# PRIMARY KEY :主键,指定该列的值可以唯一地标识该列记录
# FOREIGN KEY :外键,指定该行记录从属于主表中的一条记录,主要用于参照完整性
"""
"""
表介绍
表就相当于文件,表中的一条记录就相当于文件的一行内容,不同的是,
表中的一条记录有对应的标题,称为表的字段
#语法:
create table 表名(
字段名1 类型[(宽度) 约束条件],
字段名2 类型[(宽度) 约束条件],
字段名3 类型[(宽度) 约束条件]
);
#注意:
1. 在同一张表中,字段名是不能相同
2. 宽度和约束条件可选
3. 字段名和类型是必须的
# 建表
create database staff;
use staff;
create table staff_info (id int,name varchar(50),age int(3),sex enum('male','female'),phone bigint(11),job varchar(11));
show tables;
desc staff_info;
select id,name,sex from staff_info;
select * from staff_info;
# 插入数据
insert into staff_info (id,name,age,sex,phone,job) values (1,'Alex',83,'female',13651054608,'IT');
insert into staff_info values (2,'Egon',26,'male',13304320533,'Teacher');
insert into staff_info values (3,'nezha',25,'male',13332353222,'IT'),(4,'boss_jin',40,'male',13332353333,'IT');
select * from staff_info;
# 查看表结构
describe [tablename];这种方法和desc [tablename];
describe staff_info;
desc staff_info;
show create table staff_info\G;
# 表的数据类型
# 表的完整性约束
# 修改表的结构
语法:
1. 修改表名
ALTER TABLE 表名
RENAME 新表名;
2. 增加字段
ALTER TABLE 表名
ADD 字段名 数据类型 [完整性约束条件…],
ADD 字段名 数据类型 [完整性约束条件…];
3. 删除字段
ALTER TABLE 表名
DROP 字段名;
4. 修改字段
ALTER TABLE 表名
MODIFY 字段名 数据类型 [完整性约束条件…];
ALTER TABLE 表名
CHANGE 旧字段名 新字段名 旧数据类型 [完整性约束条件…];
ALTER TABLE 表名
CHANGE 旧字段名 新字段名 新数据类型 [完整性约束条件…];
5.修改字段排列顺序/在增加的时候指定字段位置
ALTER TABLE 表名
ADD 字段名 数据类型 [完整性约束条件…] FIRST;
ALTER TABLE 表名
ADD 字段名 数据类型 [完整性约束条件…] AFTER 字段名;
ALTER TABLE 表名
CHANGE 字段名 旧字段名 新字段名 新数据类型 [完整性约束条件…] FIRST;
ALTER TABLE 表名
MODIFY 字段名 数据类型 [完整性约束条件…] AFTER 字段名;
# alter操作非空和唯一
create table t(id int unique,name char(10) not null);
#去掉null约束
alter table t modify name char(10) null;
# 添加null约束
alter table t modify name char(10) not null;
# 去掉unique约束
alter table t drop index id;
# 添加unique约束
alter table t modify id int unique;
alter处理null和unique约束
# # alter操作主键
1、首先创建一个数据表table_test:
create table table_test(
`id` varchar(100) NOT NULL,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`name`)
);
2、如果发现主键设置错了,应该是id是主键,但如今表里已经有好多数据了,
不能删除表再重建了,仅仅能在这基础上改动表结构。
先删除主键
alter table table_test drop primary key;
然后再增加主键
alter table table_test add primary key(id);
注:在增加主键之前,必须先把反复的id删除掉。
# # 为表添加外键
创建press表
CREATE TABLE `press` (
`id` int(11) NOT NULL,
`name` char(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ;
创建book表
CREATE TABLE `book` (
`id` int(11) DEFAULT NULL,
`bk_name` char(12) DEFAULT NULL,
`press_id` int(11) NOT NULL,
KEY `press_id` (`press_id`)
) ;
为book表添加外键
alter table book add constraint fk_id foreign key(press_id) references press(id);
删除外键
alter table book drop foreign key fk_id;
# # 小示例
# 表重命名
alter table staff_info rename staff;
desc staff;
# 删除sex列
alter table staff drop sex;
desc staff;
# 添加列
alter table staff add sex enum('male','female');
# 修改id的宽度
alter table staff modify id int(4);
desc staff;
# 修改name列的字段名
alter table staff change name sname varchar(20);
desc staff;
# 修改sex列的位置
alter table staff modify sex enum('male','female') after sname;
desc staff;
# 创建自增id主键
alter table staff modify id int(4) primary key auto_increment;
desc staff;
# 删除主键,可以看到删除一个自增主键会报错
alter table staff drop primary key;
# 需要先去掉主键的自增约束,然后再删除主键约束
alter table staff modify id int(11);
desc staff;
alter table staff drop primary key;
# 添加联合主键
alter table staff add primary key (sname,age);
# 删除主键
alter table staff drop primary key;
# 创建主键id
alter table staff add primary key (id);
desc staff;
# 为主键添加自增属性
alter table staff modify id int(4) auto_increment;
desc staff;
# # 删除表
DROP TABLE 表名;
"""
"""
多表结构的创建与分析
# 寻找两张表之间的关系
分析步骤:
#1、先站在左表的角度去找
是否左表的多条记录可以对应右表的一条记录,如果是,
则证明左表的一个字段foreign key 右表一个字段(通常是id)
#2、再站在右表的角度去找
是否右表的多条记录可以对应左表的一条记录,如果是,
则证明右表的一个字段foreign key 左表一个字段(通常是id)
#3、总结:
#多对一:
如果只有步骤1成立,则是左表多对一右表
如果只有步骤2成立,则是右表多对一左表
#多对多
如果步骤1和2同时成立,则证明这两张表时一个双向的多对一,
即多对多,需要定义一个这两张表的关系表来专门存放二者的关系
#一对一:
如果1和2都不成立,而是左表的一条记录唯一对应右表的一条记录,反之亦然。
这种情况很简单,就是在左表foreign key右表的基础上,
将左表的外键字段设置成unique即可
建立表之间的联系 关联方式:foreign key
=====================多对一=====================
# create table press(
# id int primary key auto_increment,
# name varchar(20)
# );
#
# create table book(
# id int primary key auto_increment,
# name varchar(20),
# press_id int not null,
# foreign key(press_id) references press(id)
# on delete cascade
# on update cascade
# );
#
#
# insert into press(name) values
# ('北京工业地雷出版社'),
# ('人民音乐不好听出版社'),
# ('知识产权没有用出版社')
# ;
#
# insert into book(name,press_id) values
# ('九阳神功',1),
# ('九阴真经',2),
# ('九阴白骨爪',2),
# ('独孤九剑',3),
# ('降龙十巴掌',2),
# ('葵花宝典',3)
# ;
=====================多对多=====================
关联方式:foreign key+一张新的表
create table author(
id int primary key auto_increment,
name varchar(20)
);
#这张表就存放作者表与书表的关系,即查询二者的关系查这表就可以了
create table author2book(
id int not null unique auto_increment,
author_id int not null,
book_id int not null,
constraint fk_author foreign key(author_id) references author(id)
on delete cascade
on update cascade,
constraint fk_book foreign key(book_id) references book(id)
on delete cascade
on update cascade,
primary key(author_id,book_id)
);
#插入四个作者,id依次排开
insert into author(name) values('egon'),('alex'),('yuanhao'),('wpq');
#每个作者与自己的代表作如下
egon:
九阳神功
九阴真经
九阴白骨爪
独孤九剑
降龙十巴掌
葵花宝典
alex:
九阳神功
葵花宝典
yuanhao:
独孤九剑
降龙十巴掌
葵花宝典
wpq:
九阳神功
insert into author2book(author_id,book_id) values
(1,1),
(1,2),
(1,3),
(1,4),
(1,5),
(1,6),
(2,1),
(2,6),
(3,4),
(3,5),
(3,6),
(4,1)
;
=====================一对一=====================
关联方式:foreign key+unique
create table customer(
-> id int primary key auto_increment,
-> name varchar(20) not null,
-> qq varchar(10) not null,
-> phone char(16) not null
-> );
create table student(
-> id int primary key auto_increment,
-> class_name varchar(20) not null,
-> customer_id int unique, #该字段一定要是唯一的
-> foreign key(customer_id) references customer(id) #外键的字段一定要保证unique
-> on delete cascade
-> on update cascade
-> );
#增加客户
mysql> insert into customer(name,qq,phone) values
-> ('韩蕾','31811231',13811341220),
-> ('杨澜','123123123',15213146809),
-> ('翁惠天','283818181',1867141331),
-> ('杨宗河','283818181',1851143312),
-> ('袁承明','888818181',1861243314),
-> ('袁清','112312312',18811431230)
mysql> #增加学生
mysql> insert into student(class_name,customer_id) values
-> ('脱产1班',3),
-> ('周末1期',4),
-> ('周末1期',5)
-> ;
"""
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
记录操作
MySQL数据操作: DML
在MySQL管理软件中,可以通过SQL语句中的DML语言来实现数据的操作,包括
1、使用INSERT实现数据的插入
2、UPDATE实现数据的更新
3、使用DELETE实现数据的删除
4、使用SELECT查询数据以及。
"""
"""
# 插入数据
1. 插入完整数据(顺序插入)
语法一:
INSERT INTO 表名(字段1,字段2,字段3…字段n) VALUES(值1,值2,值3…值n);
语法二:
INSERT INTO 表名 VALUES (值1,值2,值3…值n);
2. 指定字段插入数据
语法:
INSERT INTO 表名(字段1,字段2,字段3…) VALUES (值1,值2,值3…);
3. 插入多条记录
语法:
INSERT INTO 表名 VALUES
(值1,值2,值3…值n),
(值1,值2,值3…值n),
(值1,值2,值3…值n);
4. 插入查询结果
语法:
INSERT INTO 表名(字段1,字段2,字段3…字段n)
SELECT (字段1,字段2,字段3…字段n) FROM 表2
WHERE …;
# 更新数据update
语法:
UPDATE 表名 SET
字段1=值1,
字段2=值2,
WHERE CONDITION;
示例:
UPDATE mysql.user SET password=password(‘123’)
where user=’root’ and host=’localhost’;
# 删除数据delete
语法:
DELETE FROM 表名
WHERE CONITION;
示例:
DELETE FROM mysql.user
WHERE password=’’;
练习:
更新MySQL root用户密码为mysql123
删除除从本地登录的root用户以外的所有用户
"""
"""
查询数据 search
# 单表查询
语法:
SELECT DISTINCT 字段1,字段2... FROM 表名
WHERE 条件
GROUP BY field
HAVING 筛选
ORDER BY field
LIMIT 限制条数
关键字执行的优先级
from :找到表:from
where :拿着where指定的约束条件,去文件/表中取出一条条记录
group by :将取出的一条条记录进行分组group by,如果没有group by,则整体作为一组
select :执行select(去重)
distinct :
having :将分组的结果进行having过滤
order by :将结果按条件排序:order by
limit :限制结果的显示条数
# 简单查询:
1、建表
2、简单查询
#简单查询
SELECT id,emp_name,sex,age,hire_date,post,post_comment,salary,office,depart_id
FROM employee;
SELECT * FROM employee;
SELECT emp_name,salary FROM employee;
#避免重复DISTINCT
SELECT DISTINCT post FROM employee;
#通过四则运算查询
SELECT emp_name, salary*12 FROM employee;
SELECT emp_name, salary*12 AS Annual_salary FROM employee;
SELECT emp_name, salary*12 Annual_salary FROM employee;
#定义显示格式
CONCAT() 函数用于连接字符串
SELECT CONCAT('姓名: ',emp_name,' 年薪: ', salary*12) AS Annual_salary
FROM employee;
CONCAT_WS() 第一个参数为分隔符
SELECT CONCAT_WS(':',emp_name,salary*12) AS Annual_salary
FROM employee;
结合CASE语句:
SELECT
(
CASE
WHEN emp_name = 'jingliyang' THEN
emp_name
WHEN emp_name = 'alex' THEN
CONCAT(emp_name,'_BIGSB')
ELSE
concat(emp_name, 'SB')
END
) as new_name
FROM
employee;
# where约束
1. 比较运算符:> < >= <= <> !=
2. between 80 and 100 值在80到100之间
3. in(80,90,100) 值是80或90或100
4. like 'e%'
通配符可以是%或_,
%表示任意多字符
_表示一个字符
5. 逻辑运算符:在多个条件直接可以使用逻辑运算符 and or not
#1:单条件查询
SELECT emp_name FROM employee
WHERE post='sale';
#2:多条件查询
SELECT emp_name,salary FROM employee
WHERE post='teacher' AND salary>10000;
#3:关键字BETWEEN AND
SELECT emp_name,salary FROM employee
WHERE salary BETWEEN 10000 AND 20000;
SELECT emp_name,salary FROM employee
WHERE salary NOT BETWEEN 10000 AND 20000;
#4:关键字IS NULL(判断某个字段是否为NULL不能用等号,需要用IS)
SELECT emp_name,post_comment FROM employee
WHERE post_comment IS NULL;
SELECT emp_name,post_comment FROM employee
WHERE post_comment IS NOT NULL;
SELECT emp_name,post_comment FROM employee
WHERE post_comment=''; 注意''是空字符串,不是null
ps:
执行
update employee set post_comment='' where id=2;
再用上条查看,就会有结果了
#5:关键字IN集合查询
SELECT emp_name,salary FROM employee
WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ;
SELECT emp_name,salary FROM employee
WHERE salary IN (3000,3500,4000,9000) ;
SELECT emp_name,salary FROM employee
WHERE salary NOT IN (3000,3500,4000,9000) ;
#6:关键字LIKE模糊查询
通配符’%’
SELECT * FROM employee
WHERE emp_name LIKE 'eg%';
通配符’_’
SELECT * FROM employee
WHERE emp_name LIKE 'al__';
# group by
单独使用GROUP BY关键字分组
SELECT post FROM employee GROUP BY post;
注意:我们按照post字段分组,那么select查询的字段只能是post,想要获取组内的其他相关信息,需要借助函数
GROUP BY关键字和GROUP_CONCAT()函数一起使用
SELECT post,GROUP_CONCAT(emp_name) FROM employee GROUP BY post;#按照岗位分组,并查看组内成员名
SELECT post,GROUP_CONCAT(emp_name) as emp_members FROM employee GROUP BY post;
GROUP BY与聚合函数一起使用
# 按照岗位分组,并查看每个组有多少人
select post,count(id) as count from employee group by post;
# 聚合函数
#强调:聚合函数聚合的是组的内容,若是没有分组,则默认一组
示例:
SELECT COUNT(*) FROM employee;
SELECT COUNT(*) FROM employee WHERE depart_id=1;
SELECT MAX(salary) FROM employee;
SELECT MIN(salary) FROM employee;
SELECT AVG(salary) FROM employee;
SELECT SUM(salary) FROM employee;
SELECT SUM(salary) FROM employee WHERE depart_id=3;
# HAVING过滤
执行优先级从高到低:where > group by > having
#1. Where 发生在分组group by之前,因而Where中可以有任意字段,但是绝对不能使用聚合函数。
#2. Having发生在分组group by之后,因而Having中可以使用分组的字段,
无法直接取到其他字段,可以使用聚合函数
# ORDER BY 查询排序
按单列排序
SELECT * FROM employee ORDER BY salary;
SELECT * FROM employee ORDER BY salary ASC;
SELECT * FROM employee ORDER BY salary DESC;
按多列排序:先按照age排序,如果年纪相同,则按照薪资排序
SELECT * from employee
ORDER BY age,
salary DESC;
# LIMIT 限制查询的记录数
示例:
SELECT * FROM employee ORDER BY salary DESC
LIMIT 3; #默认初始位置为0
SELECT * FROM employee ORDER BY salary DESC
LIMIT 0,5; #从第0开始,即先查询出第一条,然后包含这一条在内往后查5条
SELECT * FROM employee ORDER BY salary DESC
LIMIT 5,5; #从第5开始,即先查询出第6条,然后包含这一条在内往后查5条
# 使用正则表达式查询
SELECT * FROM employee WHERE emp_name REGEXP '^ale';
SELECT * FROM employee WHERE emp_name REGEXP 'on$';
SELECT * FROM employee WHERE emp_name REGEXP 'm{2}';
小结:对字符串匹配的方式
WHERE emp_name = 'egon';
WHERE emp_name LIKE 'yua%';
WHERE emp_name REGEXP 'on$';
"""
"""
1、建表
# 多表连接查询
#重点:外链接语法
SELECT 字段列表
FROM 表1 INNER|LEFT|RIGHT JOIN 表2
ON 表1.字段 = 表2.字段;
1 交叉连接:不适用任何匹配条件。生成笛卡尔积
select * from employee,department;
2 内连接:只连接匹配的行
#找两张表共有的部分,相当于利用条件从笛卡尔积结果中筛选出了正确的结果
#department没有204这个部门,因而employee表中关于204这条员工信息没有匹配出来
select employee.id,employee.name,employee.age,employee.sex,department.name from employee inner join department on employee.dep_id=department.id;
或
select employee.id,employee.name,employee.age,employee.sex,department.name from employee,department where employee.dep_id=department.id;
3 外链接之左连接:优先显示左表全部记录
#以左表为准,即找出所有员工信息,当然包括没有部门的员工
#本质就是:在内连接的基础上增加左边有右边没有的结果
select employee.id,employee.name,department.name as depart_name from employee left join department on employee.dep_id=department.id;
4 外链接之右连接:优先显示右表全部记
#以右表为准,即找出所有部门信息,包括没有员工的部门
#本质就是:在内连接的基础上增加右边有左边没有的结果
select employee.id,employee.name,department.name as depart_name from employee right join department on employee.dep_id=department.id;
5 全外连接:显示左右两个表全部记录
全外连接:在内连接的基础上增加左边有右边没有的和右边有左边没有的结果
#注意:mysql不支持全外连接 full JOIN
#强调:mysql可以使用此种方式间接实现全外连接
select * from employee left join department on employee.dep_id = department.id
union
select * from employee right join department on employee.dep_id = department.id
;
# 符合条件连接查询
#示例1:以内连接的方式查询employee和department表,并且employee表中的age字段值必须大于25,即找出年龄大于25岁的员工以及员工所在的部门
select employee.name,department.name from employee inner join department
on employee.dep_id = department.id
where age > 25;
#示例2:以内连接的方式查询employee和department表,并且以age字段的升序方式显示
select employee.id,employee.name,employee.age,department.name from employee,department
where employee.dep_id = department.id
and age > 25
order by age asc;
# # 子查询
#1:子查询是将一个查询语句嵌套在另一个查询语句中。
#2:内层查询语句的查询结果,可以为外层查询语句提供查询条件。
#3:子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
#4:还可以包含比较运算符:= 、 !=、> 、<等
1 带IN关键字的子查询
#查询平均年龄在25岁以上的部门名
select id,name from department
where id in
(select dep_id from employee group by dep_id having avg(age) > 25);
#查看技术部员工姓名
select name from employee
where dep_id in
(select id from department where name='技术');
#查看不足1人的部门名(子查询得到的是有人的部门id)
select name from department where id not in (select distinct dep_id from employee);
2 带比较运算符的子查询
#比较运算符:=、!=、>、>=、<、<=、<>
#查询大于所有人平均年龄的员工名与年龄
select name,age from emp where age > (select avg(age) from emp);
#查询大于部门内平均年龄的员工名、年龄
select t1.name,t1.age from emp t1
inner join
(select dep_id,avg(age) avg_age from emp group by dep_id) t2
on t1.dep_id = t2.dep_id
where t1.age > t2.avg_age;
3 带EXISTS关键字的子查询
EXISTS关字键字表示存在,
"""
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
索引
索引在MySQL中也叫是一种“键”,是存储引擎用于快速找到记录的一种数据结构。
索引优化应该是对查询性能优化最有效的手段了。索引能够轻易将查询性能提高好几个数量级。
一 索引的目的在于提高查询效率,通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,
同时把随机的事件变成顺序的事件,也就是说,有了这种索引机制,
我们可以总是用同一种查找方式来锁定数据。
数据库:等值查询、范围查询(>、<、between、in)、模糊查询(like)、并集查询(or)
二、磁盘IO与预读
当一次IO时,不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓冲区内。
每一次IO读取的数据我们称之为一页(page)
三 索引的数据结构
树状图是一种数据结构,它是由n(n>=1)个有限结点组成一个具有层次关系的集合
树状图特点:
每个结点有零个或多个子结点;没有父结点的结点称为根结点;
每一个非根结点有且只有一个父结点;除了根结点外,每个子结点可以分为多个不相交的子树
B+树 :B+树是通过二叉查找树,再由平衡二叉树,B树演化而来
1.索引字段要尽量的小:
2.索引的最左匹配特性:
四 聚集索引与辅助索引
在数据库中,B+树的高度一般都在2~4层,这也就是说查找某一个键值的行记录时最多只需要2到4次IO。
数据库中的B+树索引可以分为聚集索引(clustered index)和辅助索引(secondary index)
聚集索引与辅助索引相同的是:不管是聚集索引还是辅助索引,其内部都是B+树的形式,
即高度是平衡的,叶子结点存放着所有的数据。
聚集索引与辅助索引不同的是:叶子结点存放的是否是一整行的信息
1、聚集索引
InnoDB存储引擎表是索引组织表,即表中数据按照主键顺序存放。
聚集索引(clustered index)就是按照每张表的主键构造一棵B+树,
同时叶子结点存放的即为整张表的行记录数据,也将聚集索引的叶子结点称为数据页。
同B+树数据结构一样,每个数据页都通过一个双向链表来进行链接。
如果未定义主键,MySQL取第一个唯一索引(unique)而且只含非空列(NOT NULL)作为主键,
InnoDB使用它作为聚簇索引。
如果没有这样的列,InnoDB就自己产生一个这样的ID值,它有六个字节,
而且是隐藏的,使其作为聚簇索引。
由于实际的数据页只能按照一棵B+树进行排序,因此每张表只能拥有一个聚集索引。
聚集索引的好处之一:它对主键的排序查找和范围查找速度非常快,
叶子节点的数据就是用户所要查询的数据
聚集索引的好处之二:范围查询(range query),即如果要查找主键某一范围内的数据,
通过叶子节点的上层中间节点就可以得到页的范围,之后直接读取数据页即可
2、辅助索引
辅助索引的叶子节点不包含行记录的全部数据。
节点除了包含键值以外,每个叶子节点中的索引行中还包含一个书签。
书签用来告诉InnoDB存储引擎去哪里可以找到与索引相对应的行数据。
辅助索引的存在并不影响数据在聚集索引中的组织,
因此每张表上可以有多个辅助索引,但只能有一个聚集索引。
聚集索引
1.纪录的索引顺序与无力顺序相同
因此更适合between and和order by操作
2.叶子结点直接对应数据
从中间级的索引页的索引行直接对应数据页
3.每张表只能创建一个聚集索引
非聚集索引
1.索引顺序和物理顺序无关
2.叶子结点不直接指向数据页
3.每张表可以有多个非聚集索引,需要更多磁盘和内容
多个索引会影响insert和update的速度
五 MySQL索引管理
# # 功能
#1. 索引的功能就是加速查找
#2. mysql中的primary key,unique,
联合唯一也都是索引,这些索引除了加速查找以外,还有约束的功能
# # MySQL常用的索引
普通索引INDEX:加速查找
唯一索引:
-主键索引PRIMARY KEY:加速查找+约束(不为空、不能重复)
-唯一索引UNIQUE:加速查找+约束(不能重复)
联合索引:
-PRIMARY KEY(id,name):联合主键索引
-UNIQUE(id,name):联合唯一索引
-INDEX(id,name):联合普通索引
# # 索引的两大类型hash与btree
#我们可以在创建上述索引的时候,为其指定索引类型,分两类
hash类型的索引:查询单条快,范围查询慢
btree类型的索引:b+树,层数越多,数据量指数级增长(我们就用它,因为innodb默认支持它)
#不同的存储引擎支持的索引类型也不一样
InnoDB 支持事务,支持行级别锁定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;
MyISAM 不支持事务,支持表级别锁定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;
Memory 不支持事务,支持表级别锁定,支持 B-tree、Hash 等索引,不支持 Full-text 索引;
NDB 支持事务,支持行级别锁定,支持 Hash 索引,不支持 B-tree、Full-text 等索引;
Archive 不支持事务,支持表级别锁定,不支持 B-tree、Hash、Full-text 等索引;
# # 创建/删除索引的语法
#方法一:创建表时
CREATE TABLE 表名 (
字段名1 数据类型 [完整性约束条件…],
字段名2 数据类型 [完整性约束条件…],
[UNIQUE | FULLTEXT | SPATIAL ] INDEX | KEY
[索引名] (字段名[(长度)] [ASC |DESC])
);
#方法二:CREATE在已存在的表上创建索引
CREATE [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名
ON 表名 (字段名[(长度)] [ASC |DESC]) ;
#方法三:ALTER TABLE在已存在的表上创建索引
ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL ] INDEX
索引名 (字段名[(长度)] [ASC |DESC]) ;
#删除索引:DROP INDEX 索引名 ON 表名字;
#方式一
create table t1(
id int,
name char,
age int,
sex enum('male','female'),
unique key uni_id(id),
index ix_name(name) #index没有key
);
create table t1(
id int,
name char,
age int,
sex enum('male','female'),
unique key uni_id(id),
index(name) #index没有key
);
#方式二
create index ix_age on t1(age);
#方式三
alter table t1 add index ix_sex(sex);
alter table t1 add index(sex);
#查看
mysql> show create table t1;
| t1 | CREATE TABLE `t1` (
`id` int(11) DEFAULT NULL,
`name` char(1) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`sex` enum('male','female') DEFAULT NULL,
UNIQUE KEY `uni_id` (`id`),
KEY `ix_name` (`name`),
KEY `ix_age` (`age`),
KEY `ix_sex` (`sex`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
六 测试索引
1、准备数据
2、在没有索引的前提下测试查询速度
select * from s1 where id=333333333;
3、在表中已经存在大量数据的前提下,为某个字段段建立索引,建立速度会很慢
create index a on s1<id>;
4、在索引建立完毕后,以该字段为查询条件时,查询速度提升明显
select * from s1 where id=333333333;
总结:
1. 一定是为搜索条件的字段创建索引,
比如select * from s1 where id = 333;就需要为id加上索引
2. 在表中已经有大量数据的情况下,建索引会很慢,且占用硬盘空间,建完后查询速度加快。
3. 需要注意的是:innodb表的索引会存放于s1.ibd文件中,
而myisam表的索引则会有单独的索引文件table1.MYI
MySAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。
而在innodb中,表数据文件本身就是按照B+Tree组织的一个索引结构,
这棵树的叶节点data域保存了完整的数据记录
七 正确使用索引
# # 索引未命中,若想利用索引达到预想的提高查询速度的效果,我们在添加索引时,必须遵循以下问题:
1 范围问题,或者说条件不明确,条件中出现这些符号或关键字:>、>=、<、<=、!= 、
between...and...、like、
2 尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),
表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,
3 索引列不能在条件中参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,
原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。
4 and/or
and与or的逻辑
条件1 and 条件2:所有条件都成立才算成立,但凡要有一个条件不成立则最终结果不成立
条件1 or 条件2:只要有一个条件成立则最终结果就成立
对于连续多个and:mysql会按照联合索引,从左到右的顺序找一个区分度高的索引字段
对于连续多个or:mysql会按照条件的顺序,从左到右依次判断
5 最左前缀匹配原则,非常重要的原则,对于组合索引mysql会一直向右匹配直到遇到范围查询就停止匹配,
6
- 使用函数
select * from tb1 where reverse(email) = 'egon';
- 类型不一致
如果列是字符串类型,传入条件是必须用引号引起来,不然...
select * from tb1 where email = 999;
#排序条件为索引,则select字段必须也是索引字段,否则无法命中
- order by
select name from s1 order by email desc;
当根据索引排序时候,select查询的字段如果不是索引,则速度仍然很慢
select email from s1 order by email desc;
特别的:如果对主键排序,则还是速度很快:
select * from tb1 order by nid desc;
- 组合索引最左前缀
如果组合索引为:(name,email)
name and email -- 命中索引
name -- 命中索引
email -- 未命中索引
- count(1)或count(列)代替count(*)在mysql中没有差别了
- create index xxxx on tb(title(19)) #text类型,必须制定长度
# # 其他注意事项
- 避免使用select *
- 使用count(*)
- 创建表时尽量使用 char 代替 varchar
- 表的字段顺序固定长度的字段优先
- 组合索引代替多个单列索引(由于mysql中每次只能使用一个索引,所以经常使用多个条件查询时更适合使用组合索引)
- 尽量使用短索引
- 使用连接(JOIN)来代替子查询(Sub-Queries)
- 连表时注意条件类型需一致
- 索引散列值(重复少)不适合建索引,例:性别不适合
八 联合索引与覆盖索引
联合索引是指对表上的多个列合起来做一个索引。
创建联合索引
mysql> create table t(
-> a int,
-> b int,
-> primary key(a),
-> key idx_a_b(a,b)
-> );
联合索引的好处是在第一个键相同的情况下,已经对第二个键进行了排序处理
联合索引举例
# # 覆盖索引
InnoDB存储引擎支持覆盖索引,
"""
愿有更多的朋友,在网页笔记结构上分享更逻辑和易读的形式:
链接:暂无
提取码:暂无