SQL回顾

数据库的本质是一种特殊的文件python

数据库是由数据表组成的,数据表是真正存储数据的mysql

数据库客户端-->SQL语句-->数据库服务器-->数据库文件redis

表与表之间存在关联的数据库称为关系型数据库 (sql-server my-sql(5.1, 5.6, 5.7) Oracle(10g, 11g) db2)
非关系型数据库(mongodb redis)sql

惟一的标识一行信息的特殊的列 主键(primary key)不容许重复,不容许为空
当前表中的某个字段来自与另外一张表中的主键的值,那么这个字段称之为 外键(foreign key)
列 字段 同一类的信息
行 记录 对象的详细信息
记录的集合组成数据表,数据表的集合组成数据库文件mongodb


DQL 数据查询语言 select
DML 数据操做语言 insert, update, delete
DDL 数据定义语言 create, drop数据库

数据库服务端的安装 sudo apt-get install mysql
数据库客户端的安装 sudo apt-get install mysql-client编程

将程序的一些配置 写到配置文件中 修改的时候不用修改程序只须要修改配置文件便可(能够更好地保护程序源码)缓存

decimal() 占5位小数占2位安全

enum("状况1","状况2",..) 把全部可能出现的状况都列举出来服务器

体积比较大的文件不存在数据库中 存在第三方网站或者文件存储系统中 数据表中存储图片的url(如图片,音视频)(这个url是外键)

文件存储系统 (GFS TFS fastdfs--小文件)

数据的使用原则 合适为宜

数据约束
(not null,primary key,auto increment,unsigned 等 )

数据约束和数据类型 都保证数据的完整性

命令行链接数据库
mysql -u root -p-->须要输入密码
mysql -u -p密码

命令行数据库操做基本语句
select now();显示时间
select datdabases;查询全部数据库
create database 数据库名(不能重名) charset=utf8;建立数据库 数据库中须要汉字或字符 须要指定编码格式
alter 数据库名 character set 编码格式; 修改已建立数据库的编码格式
select datdabase(); 查看当前使用的数据库
use 数据库名; 使用一个数据库
drop database 数据库名; 删除数据库 谨慎使用最好别用

命令行表的操做

create table 表名(字段 约束,字段 约束,...); 建立表

desc 表名; 查看表结构
show tables; 查看数据库中有那些表
show create table 表名; 查看建立表的语句

select * from 表名; 查看表中的全部数据

insert into 表名 values(0,1字段的值, 2字段的值, 3字段的值,..);按照约束向表中添加一条数据(所有插入)
insert into 表名(字段1,字段2..)values(值1,值2..)----------------------------------------(部分插入)
insert into 表名(字段1,字段2..)values(值1,值2),(值1,值2),(值1,值2)... 一次插入多条数据--(多行插入)
insert into 表名 values(全部值),(全部值),... 一次插入多行彻底信息-------------------(全列多行插入)

alter table 代表 drop 字段名 删除表中的字段

delete from 表名; 删除表中全部数据
truncate 表名; 清空表 主键也抹去至0`
drop table 表名; 删除表,表结构也也删除 慎用 不要用,没学过
rename table test to test1; 修改表的名字

insert into 表名 values(0,1字段的值, 2字段的值, 3字段的值,.);按照约束向表中添加一条数据(增)

update 表名 set 字段="新值",字段="新值",... where id=须要修改的人的id 更新表数据------(改)

select 字段 as 别名,... from 表名;-----------------------------------------------------(查)

delete from 表名 where 条件; 删除条件指定的表中的数据 ---------------------------------(删)

查的强化拓展

给表起别名 select 表别名.字段1,表别名.字段2,.... from 表名 as 表别名;
若是给表起了别名,可是非要用原表名那是不行的.!!

 

去重 select distinct 字段 from 表; 查询字段中的数据并去重

条件查询
select 字段1,字段2 from 表名 where 条件; >,>=,=,<,<=,(!=,<>) <>不通用 ----------算术运算符
select * from 表名 where 条件1 and 条件2; and,or,not,----------------------------逻辑运算符
select * from 表名 where 字段 like "条件"; %-->任意个字符,_一个任意字符 ---------模糊查询
select * from 表名 where 字段 rlike "^小.*月$";"^以什么开头 .*任意个字符 以什么结尾$"------正则
select * from 表名 where 字段 in (18,30,45); 非连续范围,可取反--------------------范围查询
select * from 表名 where 字段 between 值and 值;连续范围,可取反 -------------------范围查询
select * from 表名 where 字段 not between 值and 值;连续范围取反 ------------------范围查询
select * from 表名 where 字段 is null;判断某个字段的值为空------------------------空判断
select * from 表名 where 字段 is not null;判断某个字段的值不为空------------------判断不为空

排序
select * from 表名 where (age between 18 and 30 ) and gender = "女" order by age desc;
order by 多个条件时优先知足前面的条件
asc 升序(默认)
desc 降序

聚合函数
select count(*) as 别名 from 表名 where 条件; count() 总数
select max(字段) as 别名 from 表名; max()最大值min()最小值
select sum(字段) from 表名; sum()求和
select avg(字段) from 表名; avg()求平均
select round(avg(字段),保留的小数位数) from 表名; avg()求平均round()保留小数位数(四舍五入)

分组
select 字段1,字段2 from 表名 group by 字段1,字段2;按照字段1字段2进行分组
select gender,count(*) from students group by gender;查看分组中的人数

group_concat组链接函数
select gender,count(*),group_concat(name) from students group by gender;显示分组中具体的人物信息

having
select gender,group_concat(name,age) from students group by gender having avg(age)>30;查询平均年龄超过30岁的性别,以及姓名

rollup 汇总
select gender,count(*) from students group by gender with rollup;按性别分组查看每组的人数和总人数

limit 起始位置,每页显示的数据个数 分页显示
limit (第n页-1)*每页要显示的个数,每页要显示的个数
select * from students limit 0,5; 第一页,显示五个数据
select * from students limit 5,5; 第二页,显示五个数据
select * from students limit 10,5;第三页,显示五个数据
limit 必须 放置在语句最后

连接查询
外连接
左外连接
以左表为主没有查询到的数据补null
select * from students left join classes on students.cls_id = classes.id;
右外连接
以右表为主没有查询到的数据补null
select * from students right join classes on students.cls_id = classes.id;

内连接 两张表有交集
inner join on
select * from 表名inner join 表名; 笛卡尔积;
select * from 表名1inner join 表名2 on 表名1.字段1=表名2.字段2;
select students.* ,classes.name from students inner join classes on students.cls_id = classes.id;

select students.name as 姓名 ,classes.name as 班级 from students inner join classes on students.cls_id= classes.id group by classes.name desc;
+-----------+--------------+
| 姓名 | 班级 |
+-----------+--------------+
| 小月月 | python_02期 |
| 刘亦菲 | python_02期 |
| 刘德华 | python_02期 |
| 程坤 | python_02期 |
| 凤姐 | python_02期 |
| 周杰伦 | python_01期 |
| 黄蓉 | python_01期 |
| 王祖贤 | python_01期 |
| 小明 | python_01期 |
| 彭于晏 | python_01期 |
+-----------+--------------+
select c.name,s.name
from students as s inner join classes as c on s.cls_id = c.id order by c.name ,s.id asc;

多表联合查询
select * from students , classes where students.cls_id = classes.id;

行子查询
select 语句中嵌套select 语句
select * from students where age >(select avg(age) from students);
大于平均年龄的人

列子查询
select id from classes where id = 1;
select * from students where students.cls_id in(select id from classes);
select * from students where students.cls_id in(select id from classes where id =1);

自关联 将多张表合到一张表中本质就是一张表
能够解决无限分表的问题 层次关系分明时使用
select * from -----areas as county -----inner join----areas as city----on----county.pid = city.aid and city.atitle="武汉市";

 


拆分表
字段改名时使用 便于表的维护

流程
1创建空表good_cates 两个字段 id name
create table goods_cates(id int unsigned not null primary key auto_increment,name varchar(40) not null);

2把原表里的字段cate_name的数据查询出来插入到新表good_cates中
###select cate name from goods group by cate_name;
insert into goods_cates(name) select cate_name from goods group by cate_name;

3经过good_cates表的数据更新原表的数据, 把新表的id替换给原表的字段的值
selsect * from goods inner join goods_cates on goods.cate_name = goods_cates.name;
update (goods inner join goods_cates on goods.cate_name = goods_cates.name) set goods.cate_name = goods_cates.id;
4修改原表的字段的类型 和新表的主键的类型一致 而且要把原表字段名改成_id
alter table goods change name cate_name cate_id int unsigened notnull;-->更名

 

1 创建空表goods_brands 两个字段 id name 插入数据
create table goods_brands (id int unsigned not null primary key auto_increment,
name varchar(40) not null) select brand_name as name from goods group by brand_name;

2 同步数据
select * from goods inner join goods_brabds on goods.brand_name = goods_brands.name:

3 改变类型
update (goods_brands inner join goods on goods_brands.name = goods.brand_name) set goods.brand_name = goods_brands.id;

4 修改表结构
alter table goods change brand_name brand_id int unsigned not null;


外键的使用 限制非法数据的插入 使用外键致使数据库更新数据的性能大大下降
添加外键约束
alter table 要修改的表名 add foreign key (要修改的表的外键字段) references 参考表(主键字段);
建立表的时候就能够添加外键约束
取消外键约束
show create table 表名; 获得外键名称
alter table goods drop foreign key 外键名称;

不使用外键 添加约束的方法
使用应用程序 获取表中的id 使用 for 循环 判断新插入的数据是否合法(在内存中判断)

 

数据库编程
流程
开始--->建立链接对象---->建立游标cursor对象--->执行sql--->关闭cursor对象--->关闭connection--->结束

建立链接对象
conn = connect(host="localhost",port=3306,user="root",password="mysql",database="jing_dong",charset="utf8")

host: 链接的MySQL主机
port:MySQL主机的端口默认3306
database:数据库的名称
user:链接的用户
password :用户的密码
charset: utf8

调用Connection对象的cursor()方法
cur =conn.cursor()

定义要执行的sql语句
sql = "sql语句"

经过链接对象获取游标对象 cursor
游标对象=链接对象.cursor()

使用游标对象操做sql语句
sql语句的结果=游标对象.execute(sql语句)
print(sql语句的结果)

经过游标对象获取数据
游标对象.fetchall()获取全部结果集 格式是元组套元组
游标对象.fetchone()获取下一条结果集
游标对象.fetchmany(要获取的行数)获取多行结果集 格式是元组套元组

若是sql语句更新了数据库中的数据须要提交
conn.commit()

游标对象 cur.close()
关闭链接 conn.close()
提交数据 conn.commit()
撤销数据 conn.rollback()


sql注入
sql语句不进行过滤 经过非法语句能够攻进数据库获取全部数据
经过sql注入 where后的条件语句恒为真
语法
' or 1=1 or '1
' or 1=1 or '1== True
防止sql注入
select * from goods where name = %s;---设置参数化列表机制
使用execute()函数本身拼接sql语句
execut(sql,[录入的数据])


数据库备份
mysqldump –uroot –p 数据库名 > python.sql;

数据库恢复
首先建立 新数据库名 设置编码
执行 数据库备份的代码
mysql -uroot –p 新数据库名 < python.sql

> 重定向覆盖写入

 

视图
把复杂的aql语句封装起来的虚表,在物理内存中并不存在 能够直接对视图进行查询

提升重用性,像函数
对数据库进行重构更改,不影响程序运行
提升安全性,对用户展现指定字段,屏蔽重要的其它字段
让数据更加清晰

建立视图
create view v_视图名 as select 语句;
建立视图时不容许有相同的字段名,须要给字段起别名
原表的数据发生变化,视图里的内容也会发生相应的变化

视图能够指向新的数据 就是 修改视图
alter view v_视图名 as 新的select语句;

删除视图
drop view v_视图名;

事务 InnoDB引擎的数据库才支持事务
Transaction 做为一个基本工做单元执行的一系列sql语句要么所有执行成功,要么所有失败
四大特性
原子性 一整个单位不能拆分
一致性 客户端的操做的结果一致
隔离性 多个客户端都开启事务操做同一数据,一方不提交就会阻塞,另外一方就没法操做数据,是行级锁机制
持久性 一旦提交所做的修改会永久保存到数据库

开启事务
begin 或者 start transaction;
提交事务 没有提交以前数据是在缓存区,一旦提交数据就会保存到数据库文件中
commit
回滚事务 在没有提交以前是能够回滚地,可是提交以后是没法回滚的,回滚是无效地
rollback
mysql 客户端默认是开启事务,默认提交
pyrthon程序中默认开启事务,须要手动提交

 

索引
查看表中是否存在索引
show index from 表名;
建立索引 建立索引时会建立B树数据结构因此时间比较慢
create index 索引名 on 表名(字段名);
删除索引
drop index 索引名 on 表名;
查询
set profiling =1; 设置时间监测
查找数据地sql语句
show profiles; 查看用时时长
索引会占用磁盘空间

 

MySQL用户管理
建立特定的帐户,给予这个帐户特定的权限
建立用户 并授予权限
使用root帐户登录
grant 权限列表 on 数据库名 to "用户名" @ "访问主机" identified by "新建立的帐户地密码";
访问主机一般使用 百分号% 表示此帐户可使用任何ip的主机登陆访问此数据库
访问主机能够设置成 localhost或具体的ip,表示只容许本机或特定主机访问
刷新权限:flush privileges;
给用户配置权限
grant 权限 on 数据库 to 用户名@localhost with grant option;
修改用户密码
update user set authentication_string=password('新密码') where user='用户名';
修改用户名
rename '用户名'@'主机' to '新用户名'@'主机';
回收权限
reveke 权限 on 数据库 from "用户名"@"主机";
删除用户
drop user "用户名"@"主机";
delete from user where user = "要删除的用户名";

每一个权限修改命令执行以后须要刷新权限
flush privileges;


数据库设计

三范式
第一范式---列的原子性, 列不能拆分
第二范式---表必须有主键,非主键字段必须依赖主键,而不能只依赖于主键的一部分
第三范式---非主键字段必须直接依赖于主键,不能存在传递依赖A-->B-->C-->主键 传递依赖容易产生数据冗余
范式必须同时知足 不知足就拆表

E-R实体关系模型
一对一 任何以访添加字段表示两张表关系均可以

一对多 须要在多的一方添加字段表示两张表的关系

多对多 须要添加中间表,表中添加两个字段,分别是两张表的主键

 


数据库主从配置

策略型服务器 负载均衡
主服务器存储数据 从服务器用来备份
写数据往主服务器写 --> 写到二进制日志文件中 --> 从服务器读取日志文件数据保存在本地保持和主服务器数据一致 -|-|-|- 读取数据时从 从服务器读取 达到 读写分离 ,负载均衡,数据备份

主从配置的机制
数据库备份
数据库恢复
主服务器的配置文件mysqld.cnf 的 43 注释掉 84行85行 不能注释 84server-id 不能与从服务器同样
从服务器配置文件mysqld.cnf 84行的log_bin注释掉
把主服务器数据导入到从服务器中
建立一个同步帐户slave
获取主服务器的二进制配置文件信息
从服务器链接主服务器 开启同步 start slave
查看同步状态 show slave status /G;

 

 

 

 

 

 

 

 


命令行中sql语句必需要以分号结尾,来表示语句结束

ctrl+a 行首
ctrl+e 行尾
数据库引擎 InnoDB支持事务.行级锁, MyISM 不支持

添加字段(列名) ALTER TABLE people ADD COLUMN name VARCHAR(100) DEFAULT NULL COMMENT '姓名'

相关文章
相关标签/搜索