数据库就是一种特殊的文件。
关系型数据库核心元素:
RDBMS(Relational Database Management System),主要产品有Oracle、mysql、ms sql server、sqlite
SQL(Structured Query Language):结构化查询语言,是一种用来操作RDBMS的数据库语言。
SQL语句主要分为:
SQL语句不区分大小写,SQL语句最后要有分号 ; 结尾
在表中为了更加准确的存储数据,保证数据的正确有效,可以在创建表时,为表添加一些强制性的验证,包括数据字段的类型、约束。
常用数据类型:
特别说明:
使用数据类型的原则是:够用就行
-- 连接数据库
mysql -u root -p
-- 退出数据库
quit
exit
-- 查看数据库文件的存放位置
show GLOBAL VARIABLES like '%datadir%';
-- 显示数据库版本
SELECT version();
-- 显示时间
SELECT now();
-- 查看所有数据库
show databases;
-- 创建数据库
create database python01;
create database python02 charset=utf8;
-- 查看创建数据库的语句
show create database python01;
show create database python02;
-- 使用数据库
use python01;
-- 查看当前使用数据库
selec database();
-- 删除数据库
DROP database python01;
-- 查看当前数据库中的所有表
show tables;
-- 创建表
-- create table 数据表名(字段 类型 约束,字段 类型 约束);
create table students(
id int UNSIGNED not null auto_increment primary key,
name varchar(30),
age tinyint UNSIGNED default 0,
high decimal(5,2),
gender enum('男','女','中性','保密') default '保密',
cls_id int UNSIGNED
);
create table classes(
id int UNSIGNED not null auto_increment primary key,
name varchar(30)
);
-- 查看创建数据表的语句
show create table students;
show create table classes;
-- 查看表结构
desc students;
desc classes;
-- 修改表,添加字段
-- alter table 表名 add 列名 类型及约束;
alter table students add birthday datetime;
-- 修改表,修改字段,重命名版
-- alter table 表名 change 原列名 新列名 类型及约束;
alter table students change birthday birth datetime not null;
alter table students
-- 修改表,修改字段,不重命名版
-- alter table 表名 modify 列名 类型及约束;
alter table students modify birth date not null;
-- 修改表,删除字段
-- alter table 表名 drop 列名
alter table students drop birth;
-- 删除表
drop table students;
-- 增加,主键字段可以用0/null/default来占位
-- 全部插入:insert into 表名 values(...);
insert into classes values(0,'1班');
insert into students values(0,'小蓝',20,179.50,'男',1);
insert into students values(null,'小红',21,160,'女',1);
insert into students values(default,'小黄',22,169,3,1);
-- 部分插入:insert into 表名 (列1,...) values(值1,...);
insert into students (name,gender) values('小黑',2);
-- 多行插入
insert into students values(default,'小橙',23,171.50,'女',1),(default,'小绿',18,190.50,'男',1);
insert into students (name,gender) values('小紫','女'),('小棕','男');
-- 修改
-- update 表名 set 列1=值1,列2=值2,...
update students set gender=1;
update students set gender=2 where name='小红';
update students set gender=3,age=30 where id=4;
-- 删除
-- 物理删除
delete from students;
delete from students where name='小绿';
-- 逻辑删除
alter table students add is_delete int default 0;
update students set is_delete=1 where id=5;
-- 查询基本使用
-- 查询所有列
select * from students;
-- 一定条件查询
select * from students where name='小绿';
-- 查询指定列
select name,gender from students;
-- 使用as为列或表指定别名
select name as 姓名,gender as 性别 from students;
-- 创建数据库
create database python01;
-- 使用数据库
use python01;
-- 创建数据表students
create table students(
id int unsigned not null auto_increment primary key,
name varchar(30) default '',
age tinyint UNSIGNED default 0,
high decimal(5,2),
gender enum('男','女','中性','保密') default '保密',
cls_id int UNSIGNED,
is_delete int default 0
);
-- 创建数据表table
create table classes(
id int UNSIGNED not null auto_increment primary key,
name varchar(30) not null
);
-- 向students表中插入数据
insert into students VALUES
(0,'小周',10,150.00,2,1,0),
(0,'小杰',18,180.00,1,2,0),
(0,'小红',23,160.50,2,1,1),
(0,'小蓝',33,170.00,1,2,0),
(0,'小杨',26,187.00,3,1,0),
(0,'小晴',41,178.50,4,3,1),
(0,'小方',18,168.00,3,1,0),
(0,'小花',22,159.00,2,2,0),
(0,'小敏',9,147.00,2,1,0),
(0,'小灰',39,169.00,1,3,0);
-- 向classes表中插入数据
insert into classes values(0,'1班'),(0,'2班'),(0,'3班');
-- 查询所有字段
select * from students;
select * from classes;
-- 查询指定字段
select name,age from students;
select id,name from classes;
-- 使用as给字段起别名
select name as 姓名,age as 年龄 from students;
-- select 表名.ziduan ...from 表名
select students.name,students.age from students;
-- 使用as给表起别名
select s.name,s.age from students as s;
-- 消除重复行
select distinct gender from students;
-- 比较运算符>、<、>=、<=、=、!=
select * from students where age>=18;
select name from students where age=18;
-- 逻辑运算符and、or、not
-- and
select * from students where age>18 and age<28;
select * from students where age>18 and gender=2;
-- or
select * from students where age>18 or high>=180;
-- not
-- 不在 18岁以上的女性 这个范围内的信息
select * from students where not (age>18 and gender=2);
-- 年龄不大于18 并且是女性的信息
select * from students where not age>18 and gender=2;
-- 模糊查询like、%(替换0个或多个)、_(替换1个)、rlike(正则)
-- 查询姓名中以“小”开始的信息
select * from students where name like '小%';
-- 查询姓名中有“小”的信息
select * from students where name like '%小%';
-- 查询有2个字的信息
select * from students where name like '__';
-- 查询至少有2个字的信息
select * from students where name like '__%';
-- 查询以周开始的信息
select * from students where name rlike '^周.*';
-- 查询以周开始、伦结尾的信息
select * from students where name rlike '^周.*伦$';
-- 范围查询in(在非连续的范围内)、not in(不在非连续的范围内)、between...and...(在连续的范围内)、not between...and...(不在连续的范围内)
-- 查询年龄为18、32的信息
select * from students where age in(18,32);
-- 查询年龄不在18、32的信息
select * from students where age not in(18,32);
-- 查询年龄在18到32岁之间的信息
select * from students where age between 18 and 32;
-- 查询年龄不在18到32岁之间的信息
select * from students where age not between 18 and 32;
select * from students where not age between 18 and 32;
-- 空判断is null、is not null
select * from students where high is null;
select * from students where high is not null
-- order by 字段,asc升序、desc降序
select * from students where age between 18 and 32 and gender=1 order by age;
select * from students where age between 18 and 32 and gender=1 order by age asc;
select * from students where age between 18 and 32 and gender=1 order by age desc;
-- order by 多个字段
-- 查询年龄在18到32之间的女性,身高从高到矮排序,如果身高相同的情况下按照年龄从小到大排序
select * from students where age between 18 and 32 and gender=2 order by high desc,age asc;
-- 总数count
select count(*) as 男性人数 from students where gender=1;
select count(*) as 女性人数 from students where gender=2;
-- 最大值max
select max(age) from students;
-- 最小值min
select min(age) from students;
-- 求和sum
select sum(age) from students;
-- 平均值avg
select avg(age) from students;
select sum(age)/count(*) from students;
-- 四舍五入
-- 计算所有人的平均年龄,保留2位小数
select round(avg(age),2)from students;
select round(sum(age)/count(*),2) from students;
-- group by
-- 按照性别分组,查询所有的性别
select gender from students group by gender;
-- 计算每种性别中的人数
select gender,count(*) from students group by gender;
-- group_concat(expr)
-- 查询同种性别中的姓名和年龄
select gender,group_concat(name,"_",age) from students group by gender;
-- having
-- 查询平均年龄超过30岁的性别,以及姓名
select gender,group_concat(name),avg(age) from students group by gender having avg(age)>30;
-- 查询每种性别中的人数多于2个的信息
select gender,group_concat(name,"_",age),count(*) from students group by gender having count(*)>2;
-- limit start, end
-- 限制查询出来的数据个数
select * from students limit 2;
-- 查询前5个数据
select * from students limit 0,5;
-- 查询id为6~10的信息
select * from students limit 5,5;
-- 每页显示2个,第1个页面
select * from students limit 10,5;
当查询结果的列来源于多张表时,需要将多张表连接成一个大的数据集,再选择合适的列返回。
内连接查询:查询结果为2个表匹配到的数据。
右连接查询:查询结果为2个表匹配到的数据+右表特有的数据,对于左表中不存在的数据 使用null填充。
左连接查询:查询结果为2个表匹配到的数据+左表特有的数据,对于右表中不存在的数据 使用null填充。
-- 内连接inner join...on
-- 查询有能够对应班级的学生以及班级信息
select * from students inner join classes on students.cls_id=classes.id;
select students.*,classes.name from students inner join classes on students.cls_id=classes.id;
select students.name,classes.name from students inner join classes on students.cls_id=classes.id;
select s.name,c.name from students as s inner join classes as c on s.cls_id=c.id;
-- 查询有能够对应班级的学生以及班级信息,按照班级进行排序,班级相同时按照id排序
select c.name,s.* from students as s inner join classes as c on s.cls_id=c.id order by c.name,s.id;
-- 左连接 left join...on
-- 查询每位学生对应的班级信息
select * from students as s left join classes as c on s.cls_id=c.id;
-- 查询没有对应班级信息的学生
select * from students as s left join classes as c on s.cls_id=c.id having c.id is null;
-- 子查询
-- 查询出大于平均年龄的信息
select * from students where age>(select avg(age) from students);
-- 查询年龄最大的男生信息
select * from students where age=(select max(age) from students where gender=1);
-- 查询学生的班级号能够对应的学生信息
select * from students where cls_id in (select id from classes);
-- 创建数据表
create database jing_dong charset=utf8;
-- 使用“京东”数据库
use jing_dong;
-- 创建一个商品goods数据表
create table goods(
id int unsigned not null auto_increment primary key,
name varchar(100) not null,
cate_name varchar(40) not null,
brand_name varchar(40) not null,
price decimal(10,3) not null default 0,
is_show int not null default 1,
is_saleoff int not null default 0
);
-- 向goods表中插入数据
insert into goods values(0,'r510vc 15.6英寸笔记本','笔记本','华硕','3399',default,default);
insert into goods values(0,'y400n 14.0英寸笔记本','笔记本','联想','4999',default,default);
insert into goods values(0,'g150th 15.6英寸游戏本','游戏本','雷神','8499',default,default);
insert into goods values(0,'x550cc 15.6英寸笔记本','笔记本','华硕','2799',default,default);
insert into goods values(0,'x240 超级本','超级本','联想','4888',default,default);
insert into goods values(0,'u330p 13.3英寸超级本','超级本','联想','4299',default,default);
insert into goods values(0,'svp13226scb 触控超级本','超级本','索超','7999',default,default);
insert into goods values(0,'ipad mini 7.9英寸平板电脑','平板电脑','苹果','1998',default,default);
insert into goods values(0,'ipad air 9.7英寸平板电脑','平板电脑','苹果','3388',default,default);
insert into goods values(0,'ipad mini 配备 retina 显示屏','平板电脑','苹果','2788',default,default);
insert into goods values(0,'ideacentre c340 20英寸一体电脑','台式机','联想','3499',default,default);
insert into goods values(0,'vostro 3800-r1206 台式电脑','台式机','戴尔','2899',default,default);
insert into goods values(0,'imac me086ch/a 21.5英寸一体电脑','台式机','苹果','9188',default,default);
insert into goods values(0,'at7-7414lp 台式电脑 Linux','台式机','宏碁','3699',default,default);
insert into goods values(0,'z220sff f4f06pa工作站','服务器/工作站','惠普','4288',default,default);
insert into goods values(0,'poweredge ii服务器','服务器/工作站','戴尔','5388',default,default);
insert into goods values(0,'mac pro专业版台式电脑','服务器/工作站','苹果','28888',default,default);
insert into goods values(0,'hmz-t3w 头戴显示设备','笔记本配件','索尼','6999',default,default);
insert into goods values(0,'商务双肩背包','笔记本配件','索尼','99',default,default);
insert into goods values(0,'x3250 m4机架式服务器','服务器/工作站','ibm','6888',default,default);
-- 查询cate_name为“超级本”的商品名称,价格
select name,price from goods where cate_name='超级本';
-- 显示商品的种类
select cate_name from goods group by cate_name;
select distinct cate_name from goods;
-- 求所有电脑产品的平均价格,并且保留2位小数
select round(avg(price),2) as '平均价格' from goods;
-- 显示每种商品的平均价格
select cate_name,avg(price) from goods group by cate_name;
-- 查询每种类型的商品中最贵、最便宜、平均价、数量
select cate_name,max(price),min(price),avg(price),count(*) from goods group by cate_name;
-- 查询所有价格大于平均价格的商品,并且按照价格降序排序
select * from goods where price>(select avg(price) from goods) order by price desc;
-- 查询每种类型中最贵的电脑信息
select * from goods inner join (
select cate_name,max(price) as max_price,min(price) as min_price,avg(price) as avg_price
from goods group by cate_name
) as new_goods_info
on goods.cate_name=new_goods_info.cate_name and goods.price=new_goods_info.max_price;
-- (1)创建商品分类表goods_cates
create table if not exists goods_cates(
id int unsigned not null auto_increment primary key,
name varchar(40) not null
);
-- (2)将goods表中查询出来的商品种类写入到goods_cates表中
insert into goods_cates(name) select cate_name from goods group by cate_name;
-- (3)创建商品品牌表goods_brands,并且同时写入记录
create table if not exists goods_brands(
id int unsigned not null auto_increment primary key,
name varchar(40) not null
)select brand_name as name from goods group by brand_name;
-- (4)通过goods_cates和goods_brands数据表来更新goods表,向goods表中的cate_name写入商品分类id,向goods表中的brand_name写入商品品牌id
update goods as g inner join goods_cates as c on g.cate_name=c.name set g.cate_name=c.id;
update goods as g inner join goods_brands as b on g.brand_name=b.name set g.brand_name=b.id;
-- (5)修改表goods的结构,将cate_name名称改为cate_id并改成int类型,将brand_name名称改为brand_id并改成int类型
alter table goods
change cate_name cate_id int unsigned not null,
change brand_name brand_id int unsigned not null;
-- (6)对表googs表中的cate_id和brand_id增加外键约束
alter table goods add foreign key (cate_id) references goods_cates(id);
alter table goods add foreign key (brand_id) references goods_brands(id);
from pymysql import *
class JD(object):
def __init__(self):
# 创建connection连接
self.conn = connect(host='localhost', port=3306, user='root', password='123456', database='jing_dong',
charset='utf8')
# 获取cursor对象
self.cursor = self.conn.cursor()
def __del__(self):
# 关闭cursor对象
self.cursor.close()
# 关闭connection对象
self.conn.close()
def execute_sql(self, sql):
# 执行查询语句
self.cursor.execute(sql)
for temp in self.cursor.fetchall():
print(temp)
def show_all_items(self):
"""显示所有商品"""
sql = 'select * from goods;'
self.execute_sql(sql)
def show_cates(self):
"""显示所有商品分类"""
sql = 'select name from goods_cates;'
self.execute_sql(sql)
def show_brands(self):
"""显示所有商品品牌"""
sql = 'select name from goods_brands'
self.execute_sql(sql)
def add_brands(self):
"""添加商品分类"""
item_name=input('请输入新商品分类的名称')
sql="""insert into goods_cates (name) values ("%s")"""%item_name
self.cursor.execute(sql)
self.conn.commit()
def get_info_by_name(self):
"""根据名字查询商品"""
find_name=input('请输入要查询的商品的名字')
# 以下语句存在sql注入的漏洞,find_name=' or 1=1 or '时查出所有数据
# sql="""select * from goods where name='%s';"""%find_name
# self.execute_sql(sql)
# 防sql注入
sql="select * from goods where name=%s"
self.cursor.execute(sql,find_name)
for temp in self.cursor.fetchall():
print(temp)
def print_menu(self):
print("..........京东..........")
print("1: 所有的商品")
print("2: 所有的商品分类")
print("3: 所有商品品牌分类")
print("4: 添加一个商品分类")
print("5: 根据名字查询一个商品")
return input("请输入功能对应的序号:")
def run(self):
while True:
num = self.print_menu()
if num == "1":
# 查询所有商品
self.show_all_items()
elif num == "2":
# 查询商品分类
self.show_cates()
elif num == "3":
# 查询商品品牌分类
self.show_brands()
elif num=="4":
# 添加商品分类
self.add_brands()
elif num=="5":
# 根据名字查询商品
self.get_info_by_name()
else:
print("输入有误,请重新输入...")
def main():
# 1. 创建一个京东商城对象
jd = JD()
# 2. 调用这个对象的run方法,让其运行
jd.run()
if __name__ == '__main__':
main()
find_name=input('请输入要查询的商品的名字')
# 以下语句存在sql注入的漏洞,find_name=' or 1=1 or '时查出所有数据
sql="""select * from goods where name='%s';"""%find_name
elf.execute_sql(sql)
# 防sql注入
sql="select * from goods where name=%s"
self.cursor.execute(sql,find_name)
视图是对若干张基本表的引用,是一条select语句执行后返回的结果集,是一张虚拟的表。
基本表数据发生了改变,视图也会跟着改变。
视图的用途就是查询。
-- 定义视图
-- create view 视图名称 as select语句;
-- 查询3张表的信息
select * from goods as g left join goods_cates as c on g.cate_id=c.id left join goods_brands as b on g.brand_id=b.id;
select g.*,c.name as cate_name,b.name as brand_name from goods as g left join goods_cates as c on g.cate_id=c.id left join goods_brands as b on g.brand_id=b.id;
-- 将以上的查询结果,作为一个虚拟的表,就是视图
create view v_goods_info as select g.*,c.name as cate_name,b.name as brand_name from goods as g left join goods_cates as c on g.cate_id=c.id left join goods_brands as b on g.brand_id=b.id;
-- 查看视图
show tables;
-- 使用视图,用于查询
select * from v_goods_info;
-- 视图不支持更新
-- 以下语句会报错,update v_goods_info set name='小霸王学习机' where id=20;
-- 删除视图
drop view v_goods_info;
所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。
事务四大特性(ACID)
Atomicity原子性:一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有 操作要么全部提交成功,要么全部失败回滚,不可能只执行其中的一部分 操作。
Consistency一致性:数据库总是从一个一致性的状态转换到另一个一致性的状态。
Isolation隔离性:一个事务所做的修改在最终提交以前,对其它事务是不可见的。
Durability持久性:一旦事务提交,则其所做的修改会永久保存到数据库。
-- 开启事务
begin;
start transaction;
-- 执行修改命令
-- 提交事务
commit;
-- 回滚事务
rollback;
索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。
索引的目的在于提高查询效率。
要注意的是,建立太多的索引会影响更新和插入的速度,也会占用过多的磁盘空间。
-- 查看索引
-- show index from 表名
show index from test_index;
-- 创建索引
-- create index 索引名称 on 表名(字段名称(长度)),如果字段类型不是字符串可以不写长度部分;
-- 为表title_index的title列创建索引
create index title_index on test_index(title(10));
-- 删除索引
-- drop index 索引名 on 表名
drop index title_index on test_index;
索引Demo
-- 创建测试表test_index
create table test_index(
title varchar(10)
);
-- 通过pymysql模块,向表中加入十万条数据
from pymysql import *;
def main():
# 创建connection连接
conn = connect(host='localhost', port=3306, user='root', password='123456', database='jing_dong')
# 获取cursor对象
cursor = conn.cursor()
# 插入10万条数据
for i in range(100000):
cursor.execute("""insert into test_index values ('ha-%d')""" % i)
# 提交数据
conn.commit()
if __name__ == '__main__':
main()
-- 查询
-- 开启运行时间监测
set profiling=1;
-- 查找第1万条数据ha-99999
select * from test_index where title='ha-99999';
-- 查看执行的时间
show profiles;
-- 创建索引
-- create index 索引名称 on 表名(字段名称(长度)),如果字段类型不是字符串可以不写长度部分;
-- 为表title_index的title列创建索引
create index title_index on test_index(title(10));
-- 查找第1万条数据ha-99999
select * from test_index where title='ha-99999';
-- 再次查看执行的时间
show profiles;