数据库,也就是学习如何操作数据,管理数据
对数据库的操作
-- 数据库的操作
数据库:存储数据的仓库
默认安装数据库的路径在:C:\ProgramData\MySQL\MySQL Server 5.7\Data
创建的 database 都在这个目录下
主键:非空切唯一
不分大小写
从一个数据库中跳转到另一个数据库,也是用use
-- 链接数据库
mysql -uroot -p
mysql -uroot -pmysql
-- 退出数据库
exit/quit/ctrl+d
-- sql语句最后需要有分号;结尾
-- 显示数据库版本
select version();
-- 显示时间
select now();
-- 查看所有数据库
show databases;
-- 创建数据库
-- create database 数据库名 charset=utf8;
create database python04; 默认字符编码是utf8
create database python04new charset=utf8;
create database if not exists libai; 创建数据库(如果不存在就创建,存在就不创建,不会报错)
但会显示警告
show warning; 查看警告信息
-- 显示创建数据库的信息
-- show crate database ....
show create database python04;
alter database libai character set utf8; 将libai 数据库编码格式更改为utf8
-- 查看当前使用的数据库
select database();
-- 使用数据库
-- use 数据库的名字
use python04new;
-- 删除数据库
-- drop database 数据库名;
drop database python04;
-- 数据表的操作
-- 查看当前数据库中所有表
show tables;
-- 创建表
-- auto_increment表示自动增长
-- not null 表示不能为空
-- primary key 表示主键
-- default 默认值
-- create table 数据表名字 (字段 类型 约束[, 字段 类型 约束]);
create table xxxxx(id int, name varchar(30));
create table yyyyy(id int primary key not null auto_increment, name varchar(30));
create table zzzzz(
id int primary key not null auto_increment,
name varchar(30)
);
-- 查看表结构
-- desc 数据表的名字;
desc xxxxx;
-- 创建students表(id、name、age、high、gender、cls_id)
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
);
insert into students values(0, "老王", 18, 188.88, "男", 0);
select * from students;
-- 创建classes表(id、name)
create table classes(
id int unsigned not null auto_increment primary key,
name varchar(30)
);
insert into classes values(0, "python04大神");
select * from classes;
-- 查看表的创建语句
-- show create table 表名字;
show create table students;
-- 修改表-添加字段
-- alter table 表名 add 列名 类型;
alter table students add birthday datetime;
-- 修改表-修改字段:不重命名版
-- alter table 表名 modify 列名 类型及约束;
alter table students modify birthday date;
-- 修改表-修改字段:重命名版
-- alter table 表名 change 原名 新名 类型及约束;
alter table students change birthday birth date default "2000-01-01";
-- 修改表-删除字段
-- alter table 表名 drop 列名;
alter table students drop high;
-- 删除表
-- drop table 表名;
-- drop database 数据库;
-- drop table 数据表;
drop table xxxxx;
-- 增删改查(curd)
-- 增加
-- 全列插入
-- insert [into] 表名 values(...)
-- 主键字段 可以用 0 null default 来占位
-- 向classes表中插入 一个班级
insert into classes values(0, "菜鸟班");
students 表
+--------+-------------------------------------+------+-----+------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------------------------------+------+-----+------------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(30) | YES | | NULL | |
| age | tinyint(3) unsigned | YES | | 0 | |
| gender | enum('男','女','中性','保密') | YES | | 保密 | |
| cls_id | int(10) unsigned | YES | | NULL | |
| birth | date | YES | | 2000-01-01 | |
+--------+-------------------------------------+------+-----+------------+----------------+
-- 向students表插入 一个学生信息
insert into students values(0, "小李飞刀", 20, "女", 1, "1990-01-01");
insert into students values(null, "小李飞刀", 20, "女", 1, "1990-01-01");
insert into students values(default, "小李飞刀", 20, "女", 1, "1990-01-01");
-- 失败
-- insert into students values(default, "小李飞刀", 20, "第4性别", 1, "1990-02-01");
-- 枚举中 的 下标从1 开始 1---“男” 2--->"女"....
insert into students values(default, "小李飞刀", 20, 1, 1, "1990-02-01");
-- 部分插入
-- insert into 表名(列1,...) values(值1,...)
insert into students (name, gender) values ("小乔", 2);
-- 多行插入
insert into students (name, gender) values ("大乔", 2),("貂蝉", 2);
insert into students values(default, "西施", 20, "女", 1, "1990-01-01"), (default, "王昭君", 20, "女", 1, "1990-01-01");
-- 修改
-- update 表名 set 列1=值1,列2=值2... where 条件;
update students set gender=1; -- 全部都改
update students set gender=1 where name="小李飞刀"; -- 只要name是小李飞刀的 全部的修改
update students set gender=1 where id=3; -- 只要id为3的 进行修改
update students set age=22, gender=1 where id=3; -- 只要id为3的 进行修改
-- 查询基本使用
-- 查询所有列
-- select * from 表名;
select * from students;
---定条件查询
select * from students where name="小李飞刀"; -- 查询 name为小李飞刀的所有信息
select * from students where id>3; -- 查询 name为小李飞刀的所有信息
-- 查询指定列
-- select 列1,列2,... from 表名;
select name,gender from students;
-- 可以使用as为列或表指定别名
-- select 字段[as 别名] , 字段[as 别名] from 数据表 where ....;
select name as 姓名,gender as 性别 from students;
-- 字段的顺序
select id as 序号, gender as 性别, name as 姓名 from students;
-- 删除
-- 物理删除
-- delete from 表名 where 条件
delete from students; -- 整个数据表中的所有数据全部删除
delete from students where name="小李飞刀";
-- 逻辑删除
-- 用一个字段来表示 这条信息是否已经不能再使用了
-- 给students表添加一个is_delete字段 bit 类型
alter table students add is_delete bit default 0;
update students set is_delete=1 where id=6;
创建表格
CREATE TABLE employee( // 创建一个table,必须在数据库中
id TINYINT PRIMARY KEY auto_increment, // 设置主键PRIMARY KEY,唯一auto_increment,
name VARCHAR(25), // name 在0-25个字符之间
gender boolean,
age INT DEFAULT 20, // 默认值为20
department VARCHAR(20),
salary DOUBLE(7,2) // 七位数字,小数后两位 如:22222.55
)
show tables; 查看所有表格信息
desc employee; 查看 employee 表格信息,也可以用 show create table employee;
alter table employee add is_married tinyint(1); 为表格添加一个字段,
mysql> alter table employee add A INT, // 可以用逗号间隔,来添加多个字段
-> add B VARCHAR(20);
alter table employee drop A; 删除字段
alter table employee modify age smallint not null default 18 after name; // 更改 age 的类型,not null ,default 18, 放在 name 字段后面
alter table employee change department depart varchar(20) after salary; // 更改 department 字段的名称,必须加上字段类型,放在 salary 字段后面
rename table employee to employ; // 修改表名,改为 employ
mysql> insert into employ (id,name,age,gender,salary,depart,is_married) // 插入数据,每个都对应着
-> values(1,"libai",20,1,2000,"海贼王",0);
select * from employ; // 显示 table 的数据
mysql> insert into employ (name,gender,salary,depart) // 插入数据,不全
-> value("132",1,5000,"吴");
mysql> insert into employ (name,gender,salary,depart) // 插入多条数据
-> values("talent",0,200,"one"),
-> ("and",0,400,"one");
insert into employ values (8,"hello",88,0,900,"简洁",0); // 不写字段名就要全部写上 , id改为8之后,就由8开始走了
update employ set gender=0 where name="how"; // 修改数据,where 为筛选
delete from employ where id=10; // 删除数据
delete from employ; // 删除表
truncate table employ; // 删除表
mysql> select name,js from examresult; // 筛选出表中的数据
+-------+------+
| name | js |
+-------+------+
| yuan | 98 |
| xialv | 35 |
| alex | 59 |
| wusir | 88 |
| alvin | 88 |
| yuan | 86 |
| libai | 10 |
| libai | 10 |
+-------+------+
8 rows in set (0.00 sec)
mysql> select distinct js,name from examresult; // 筛选出表中的数据,剔除重复的
+------+-------+
| js | name |
+------+-------+
| 98 | yuan |
| 35 | xialv |
| 59 | alex |
| 88 | wusir |
| 88 | alvin |
| 86 | yuan |
| 10 | libai |
+------+-------+
7 rows in set (0.00 sec)
mysql> select name,js+10,django+10,openstack+10 from examresult; // 只是加上10显示,并没有更改数据
+-------+-------+-----------+--------------+
| name | js+10 | django+10 | openstack+10 |
+-------+-------+-----------+--------------+
| yuan | 108 | 108 | 108 |
| xialv | 45 | 108 | 77 |
| alex | 69 | 69 | 72 |
| wusir | 98 | 99 | 92 |
| alvin | 98 | 108 | 77 |
| yuan | 96 | 110 | 65 |
| libai | 20 | 20 | 20 |
| libai | 20 | 20 | 20 |
+-------+-------+-----------+--------------+
8 rows in set (0.04 sec)
mysql> select name,js+django+openstack from examresult; // 加起来显示
+-------+---------------------+
| name | js+django+openstack |
+-------+---------------------+
| yuan | 294 |
| xialv | 200 |
| alex | 180 |
| wusir | 259 |
| alvin | 253 |
| yuan | 241 |
| libai | 30 |
| libai | 30 |
+-------+---------------------+
8 rows in set (0.00 sec)
mysql> select name,js+django+openstack 总成绩 from examresult; // 用总成绩来当字段
+-------+--------+
| name | 总成绩 |
+-------+--------+
| yuan | 294 |
| xialv | 200 |
| alex | 180 |
| wusir | 259 |
| alvin | 253 |
| yuan | 241 |
| libai | 30 |
| libai | 30 |
+-------+--------+
8 rows in set (0.04 sec)
分组查询,通常和聚集函数组合使用
select * from admin group by age;
外键约束
primary key,not null,unique
foreign key 保证数据的一致性
查询
SELECT c.id,c.sex,c.age,o.title,o.price FROM customers as c,orders as o where c.id=o.cid order by c.id,o.id;
join连接查询--内连接
select c.id,c.sex,c.age,o.title,o.price from customers as c join orders as o on c.id=o.id;
外连接--left,有的客户没订单,也显示该客户,但其订单数据都为null
mysql> select c.id,c.name,c.sex,c.age,o.title from customers as c left join orders o on c.id=o.cid order by c.id;
+----+--------+-----+-----+---------+
| id | name | sex | age | title |
+----+--------+-----+-----+---------+
| 1 | libai | 1 | 22 | package |
| 2 | talent | 0 | 25 | watch |
| 3 | oop | 0 | 24 | pants |
| 10 | name01 | 1 | 23 | NULL |
+----+--------+-----+-----+---------+
外连接--right,有的订单没客户,客户端补齐null
mysql> select c.id,c.name,c.sex,c.age,o.title from customers as c right join orders o on c.id=o.cid order by c.id;
+------+--------+------+------+---------+
| id | name | sex | age | title |
+------+--------+------+------+---------+
| NULL | NULL | NULL | NULL | title01 |
| 1 | libai | 1 | 22 | package |
| 2 | talent | 0 | 25 | watch |
| 3 | oop | 0 | 24 | pants |
+------+--------+------+------+---------+
union:集合查询
1.纵向合成若干查询的结果
2.select c.id,c.name from customers as c union select o.id,o.title from orders as o;
3.union all,包含重复数据
select * from customers where id<=3 union all select * from customers;
范围运算:
1. select * from customers where id=1 or id=2;
2. select * from customers where id between 1 and 3;
3. select * from customers where id in(1,2);
4. all
5. any
-- 数据的准备
-- 创建一个数据库
create database python_test charset=utf8;
-- 使用一个数据库
use python_test;
-- 显示使用的当前数据是哪个?
select database();
-- 创建一个数据表
-- students表
create table students(
id int unsigned primary key auto_increment not null,
name varchar(20) default '',
age tinyint unsigned default 0,
height decimal(5,2),
gender enum('男','女','中性','保密') default '保密',
cls_id int unsigned default 0,
is_delete bit default 0
);
-- classes表
create table classes (
id int unsigned auto_increment primary key not null,
name varchar(30) not null
);
-- 查询
-- 查询所有字段
-- select * from 表名;
select * from students;
select * from classes;
select id, name from classes;
-- 查询指定字段
-- select 列1,列2,... from 表名;
select name, age from students;
-- 使用 as 给字段起别名
-- select 字段 as 名字.... from 表名;
select name as 姓名, age as 年龄 from students;
-- select 表名.字段 .... from 表名;
select students.name, students.age from students;
-- 可以通过 as 给表起别名
-- select 别名.字段 .... from 表名 as 别名;
select students.name, students.age from students;
select s.name, s.age from students as s;
-- 失败的select students.name, students.age from students as s;
-- 消除重复行
-- distinct 字段
select distinct gender from students;
-- 条件查询
-- 比较运算符
-- select .... from 表名 where .....
-- >
-- 查询大于18岁的信息
select * from students where age>18;
select id,name,gender from students where age>18;
-- <
-- 查询小于18岁的信息
select * from students where age<18;
-- >=
-- <=
-- 查询小于或者等于18岁的信息
-- =
-- 查询年龄为18岁的所有学生的名字
select * from students where age=18;
-- != 或者 <>
-- 逻辑运算符
-- and
-- 18到28之间的所以学生信息
select * from students where age>18 and age<28;
-- 失败select * from students where age>18 and <28;
-- 18岁以上的女性
select * from students where age>18 and gender="女";
select * from students where age>18 and gender=2;
-- or
-- 18以上或者身高查过180(包含)以上
select * from students where age>18 or height>=180;
-- not
-- 不在 18岁以上的女性 这个范围内的信息
-- select * from students where not age>18 and gender=2;
select * from students where not (age>18 and gender=2);
-- 年龄不是小于或者等于18 并且是女性
select * from students where (not age<=18) and gender=2;
-- 模糊查询
-- like
-- % 替换1个或者多个
-- _ 替换1个
-- 查询姓名中 以 "小" 开始的名字
select name from students where name like "小%";
-- 查询姓名中 有 "小" 所有的名字
select name from students where name like "%小%";
-- 查询有2个字的名字
select name from students where name like "__";
-- 查询有3个字的名字
select name from students where name like "___";
-- 查询至少有2个字的名字
select name from students where name like "__%";
-- rlike 正则
-- 查询以 周开始的姓名
select name from students where name rlike "^周.*";
-- 查询以 周开始、伦结尾的姓名
select name from students where name rlike "^周.*伦$";
-- 范围查询
-- in (1, 3, 8)表示在一个非连续的范围内
-- 查询 年龄为18、34的姓名
select name,age from students where age=18 or age=34;
select name,age from students where age=18 or age=34 or age=12;
select name,age from students where age in (12, 18, 34);
-- not in 不非连续的范围之内
-- 年龄不是 18、34岁之间的信息
select name,age from students where age not in (12, 18, 34);
-- between ... and ...表示在一个连续的范围内
-- 查询 年龄在18到34之间的的信息
select name, age from students where age between 18 and 34;
-- not between ... and ...表示不在一个连续的范围内
-- 查询 年龄不在在18到34之间的的信息
select * from students where age not between 18 and 34;
select * from students where not age between 18 and 34;
-- 失败的select * from students where age not (between 18 and 34);
-- 空判断
-- 判空is null
-- 查询身高为空的信息
select * from students where height is null;
select * from students where height is NULL;
select * from students where height is Null;
-- 判非空is not null
select * from students where height is not null;
-- 排序
-- order by 字段
-- asc从小到大排列,即升序
-- desc从大到小排序,即降序
-- 查询年龄在18到34岁之间的男性,按照年龄从小到到排序
select * from students where (age between 18 and 34) and gender=1;
select * from students where (age between 18 and 34) and gender=1 order by age;
select * from students where (age between 18 and 34) and gender=1 order by age asc;
-- 查询年龄在18到34岁之间的女性,身高从高到矮排序
select * from students where (age between 18 and 34) and gender=2 order by height desc;
-- order by 多个字段
-- 查询年龄在18到34岁之间的女性,身高从高到矮排序, 如果身高相同的情况下按照年龄从大到小排序
select * from students where (age between 18 and 34) and gender=2 order by height desc,id desc;
-- 查询年龄在18到34岁之间的女性,身高从高到矮排序, 如果身高相同的情况下按照年龄从小到大排序,
-- 如果年龄也相同那么按照id从大到小排序
select * from students where (age between 18 and 34) and gender=2 order by height desc,age asc,id desc;
-- 按照年龄从小到大、身高从高到矮的排序
select * from students order by age asc, height desc;
-- 聚合函数
-- 总数
-- count
-- 查询男性有多少人,女性有多少人
select * from students where gender=1;
select count(*) from students where gender=1;
select count(*) as 男性人数 from students where gender=1;
select count(*) as 女性人数 from students where gender=2;
-- 最大值
-- max
-- 查询最大的年龄
select age from students;
select max(age) from students;
-- 查询女性的最高 身高
select max(height) from students where gender=2;
-- 最小值
-- min
-- 求和
-- sum
-- 计算所有人的年龄总和
select sum(age) from students;
-- 平均值
-- avg
-- 计算平均年龄
select avg(age) from students;
-- 计算平均年龄 sum(age)/count(*)
select sum(age)/count(*) from students;
-- 四舍五入 round(123.23 , 1) 保留1位小数
-- 计算所有人的平均年龄,保留2位小数
select round(sum(age)/count(*), 2) from students;
select round(sum(age)/count(*), 3) from students;
-- 计算男性的平均身高 保留2位小数
select round(avg(height), 2) from students where gender=1;
-- select name, round(avg(height), 2) from students where gender=1;
-- 分组
-- group by
-- 按照性别分组,查询所有的性别
select name from students group by gender;
select * from students group by gender;
select gender from students group by gender;
-- 失败select * from students group by gender;
-- 计算每种性别中的人数
select gender,count(*) from students group by gender;
-- 计算男性的人数
select gender,count(*) from students where gender=1 group by gender;
-- group_concat(...)
-- 查询同种性别中的姓名
select gender,group_concat(name) from students where gender=1 group by gender;
select gender,group_concat(name, age, id) from students where gender=1 group by gender;
select gender,group_concat(name, "_", age, " ", id) from students where gender=1 group by gender;
-- having
-- 查询平均年龄超过30岁的性别,以及姓名 having avg(age) > 30
select gender, group_concat(name),avg(age) from students group by gender having avg(age)>30;
-- 查询每种性别中的人数多于2个的信息
select gender, group_concat(name) from students group by gender having count(*)>2;
-- 分页
-- limit start, count
-- 限制查询出来的数据个数
select * from students where gender=1 limit 2;
-- 查询前5个数据
select * from students limit 0, 5;
-- 查询id6-10(包含)的书序
select * from students limit 5, 5;
-- 每页显示2个,第1个页面
select * from students limit 0,2;
-- 每页显示2个,第2个页面
select * from students limit 2,2;
-- 每页显示2个,第3个页面
select * from students limit 4,2;
-- 每页显示2个,第4个页面
select * from students limit 6,2; -- -----> limit (第N页-1)*每个的个数, 每页的个数;
-- 每页显示2个,显示第6页的信息, 按照年龄从小到大排序
-- 失败select * from students limit 2*(6-1),2;
-- 失败select * from students limit 10,2 order by age asc;
select * from students order by age asc limit 10,2;
select * from students where gender=2 order by height desc limit 0,2;
-- 连接查询
-- inner join ... on
-- select ... from 表A inner join 表B;
select * from students inner join classes;
-- 查询 有能够对应班级的学生以及班级信息
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;
-- 查询 有能够对应班级的学生以及班级信息,显示学生的所有信息,只显示班级名称
select s.*, c.name from students as s inner join classes as c on s.cls_id=c.id;
-- 在以上的查询中,将班级姓名显示在第1列
select c.name, s.* from students as s inner join classes as c on s.cls_id=c.id;
-- 查询 有能够对应班级的学生以及班级信息, 按照班级进行排序
-- select c.xxx s.xxx from student as s inner join clssses as c on .... order by ....;
select c.name, s.* from students as s inner join classes as c on s.cls_id=c.id order by c.name;
-- 当时同一个班级的时候,按照学生的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
-- 查询每位学生对应的班级信息
select * from students as s left join classes as c on s.cls_id=c.id;
-- 查询没有对应班级信息的学生
-- select ... from xxx as s left join xxx as c on..... where .....
-- select ... from xxx as s left join xxx as c on..... having .....
select * from students as s left join classes as c on s.cls_id=c.id having c.id is null;
select * from students as s left join classes as c on s.cls_id=c.id where c.id is null;
-- right join on
-- 将数据表名字互换位置,用left join完成
-- 自关联
-- 省级联动 url:http://demo.lanrenzhijia.com/2014/city0605/
-- 查询所有省份
select * from areas where pid is null;
-- 查询出山东省有哪些市
select * from areas as province inner join areas as city on city.pid=province.aid having province.atitle="山东省";
select province.atitle, city.atitle from areas as province inner join areas as city on city.pid=province.aid having province.atitle="山东省";
-- 查询出青岛市有哪些县城
select province.atitle, city.atitle from areas as province inner join areas as city on city.pid=province.aid having province.atitle="青岛市";
select * from areas where pid=(select aid from areas where atitle="青岛市")
-- 子查询
-- 标量子查询
-- 查询出高于平均身高的信息
-- 查询最高的男生信息
select * from students where height = 188;
select * from students where height = (select max(height) from students);
-- 列级子查询
-- 查询学生的班级号能够对应的学生信息
-- select * from students where cls_id in (select id from classes);
inner join 和 left join , mysql 不支持 全外连接
要点:
1. where 是对原表中的数据进行判断,having 是对查出来的结果进行判断
2. limit 语句要放在最后
3. 尽量少用外键,外键效率低
连接查询
当查询结果的列来源于多张表时,需要将多张表连接成一个大的数据集,再选择合适的列返回
mysql支持三种类型的连接查询,分别为:内连接,右连接,左连接
语法:
select * from 表1 inner或left或right join 表2 on 表1.列 = 表2.列
内连接查询:查询的结果为两个表匹配到的数据
使用内连接查询班级表与学生表
select * from students inner join classes on students.cls_id = classes.id;
右连接查询:查询的结果为两个表匹配到的数据,右表特有的数据,对于左表中不存在的数据使用null填充
使用右连接查询班级表与学生表
select * from students as s right join classes as c on s.cls_id = c.id;
左连接查询:查询的结果为两个表匹配到的数据,左表特有的数据,对于右表中不存在的数据使用null填充
使用左连接查询班级表与学生表,此处使用了as为表起别名,目的是编写简单
select * from students as s left join classes as c on s.cls_id = c.id;
Python 使用 pymysql 操作 MYSQL数据库,pymysql 就是在python里面操作原生MySQL的方式
在生成SQL字符串时,要使用pymysql自带的模块进行处理,避免被注入风险。
from pymysql import *
class JD:
def __init__(self):
self.conn = connect(host="localhost", port=3306, database="jing_dong", user="root", password="root", charset="utf8")
self.cs1 = self.conn.cursor()
def show_all(self):
count = self.cs1.execute("select * from goods order by id asc")
print("查询到" + str(count) + "条数据")
for i in range(count):
result = self.cs1.fetchone()
print(result)
def show_products(self):
count = self.cs1.execute("select brand_name from goods group by brand_name")
print("查询到" + str(count) + "条数据")
for i in range(count):
result = self.cs1.fetchone()
print(result[0], end=", ")
print()
def insert(self):
name = input("name:")
cate_name = input("cate_name:")
brand_name = input("brand_name:")
price = input("price:")
is_show = input("in_show:")
is_saleoff = input("is_saleoff:")
count = self.cs1.execute("""insert into goods (name, cate_name, brand_name, price, is_show, is_saleoff) values ("%s", %s, "%s", %s, %s, %s)""" %(name, cate_name, brand_name, price, is_show, is_saleoff))
print("插入" + str(count) + "条数据")
def find(self):
brand_name = input("请输入要查询的电脑品牌:")
# 有SQL注入风险
# sql = """select * from goods where brand_name='%s'""" %brand_name
# print("------->%s<---------" %sql)
# 安全的方式,构造参数列表
count = self.cs1.execute("""select * from goods where brand_name='%s'""",[brand_name])
print("查询到" + str(count) + "条数据")
for i in range(count):
result = self.cs1.fetchone()
print(result)
def __del__(self):
self.cs1.close()
self.conn.close()
def run(self):
while True:
print("1.显示所有商品")
print("2.显示所有商品分类")
print("3.插入一条商品数据")
print("4.通过商品名称查询商品信息")
num = input("请输入num:")
if num == "1":
self.show_all()
elif num == "2":
self.show_products()
elif num == "3":
self.insert()
elif num == "4":
self.find()
else:
print("输入错误,程序退出")
self.__del__()
break
def main():
jd = JD()
jd.run()
if __name__ == '__main__':
main()
事务四大特性(ACID):原子性、一致性、隔离性、持久性
事务四大特性(简称ACID)
1. 原子性(Atomicity)
2. 一致性(Consistency)
3. 隔离性(Isolation)
4. 持久性(Durability)
一个很好的事务处理系统,必须具备这些标准特性:
原子性(atomicity)
一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,
对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性
一致性(consistency)
数据库总是从一个一致性的状态转换到另一个一致性的状态。(如果事务最终没有提交,事务中所做的修改也不会保存到数据库中。)
隔离性(isolation)
通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。
持久性(durability)
一旦事务提交,则其所做的修改会永久保存到数据库。(此时即使系统崩溃,修改的数据也不会丢失。)
表的引擎类型必须是innodb类型才可以使用事务,这是mysql表的默认引擎
1. 开启事务,命令如下:
开启事务后执行修改命令,变更会维护到本地缓存中,而不维护到物理表中
begin;
或者
start transaction;
2. 提交事务,命令如下
将缓存中的数据变更维护到物理表中
commit;
3. 回滚事务,命令如下:
放弃缓存中变更的数据
rollback;
在开启事务后,对表的操作未提交之前,本地可以看到数据变化,另一个客户端是看不到数据变化的
如果两个客户端都对同一行数据进行修改,一个客户端修改后(未提交),另一个也去修改(只能查看,不能修改)会被堵塞
事务的并发执行导致3个现象
1.脏读,B事务读取了A事务未提交的数据,如果A事务回滚,则B事务出现脏读。
2.不可重复读,一个事务在进行相同条件的查询,连续的两次或两次以上,每次结果都不同。
3.幻读,虚读,一个事务在进行相同条件的查询,连续的两次或两次以上,在稍后的查询中会发现一些原来没有的记录。
ANSI SQL,隔离级别(避免出现哪种事务并发现象)
1-read uncommited,读未提交
2-read commited,读已提交(oracle默认值)
4-repeatable read,可以重复读(mysql开启事务后的默认值)
8-Serializable,串行化
随着隔离级别的提升,安全性越好,但性能越差。
设置MySQL的隔离级别
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
行级锁定
1.多个事务并发修改同一条记录。
row lock
表级锁定,性能较差
Mysql 的索引
当数据库中数据量很大时,查找数据会变得很慢
优化方案:索引
索引是什么
索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。
更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度
查看索引
show index from 表名;
创建索引
如果指定字段是字符串,需要指定长度,建议长度与定义字段时的长度一致
字段类型如果不是字符串,可以不填写长度部分
create index 索引名称 on 表名(字段名称(长度))
删除索引:
drop index 索引名称 on 表名;
为表title_index的title列创建索引:
create index title_index on test_index(title(10));
注意:
要注意的是,建立太多的索引将会影响更新和插入的速度,因为它需要同样更新每个索引文件。
对于一个经常需要更新和插入的表格,就没有必要为一个很少使用的where字句单独建立索引了,
对于比较小的表,排序的开销不会很大,也没有必要建立另外的索引。
建立索引会占用磁盘空间
Python 的视图
对于复杂的查询,往往是有多个数据表进行关联查询而得到,如果数据库因为需求等原因发生了改变,
为了保证查询出来的数据与之前相同,则需要在多个地方进行修改,维护起来非常麻烦
解决办法:定义视图
视图是什么
通俗的讲,视图就是一条SELECT语句执行后返回的结果集。所以我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上。
视图是对若干张基本表的引用,一张虚表,查询语句执行的结果,不存储具体的数据(基本表数据发生了改变,视图也会跟着改变);
方便操作,特别是查询操作,减少复杂的SQL语句,增强可读性;
定义视图,建议以v_开头
create view 视图名称 as select语句;
查看视图,查看表会将所有的视图也列出来
show tables;
使用视图,视图的用途就是查询
select * from v_stu_score;
删除视图
drop view 视图名称;
drop view v_stu_sco;
视图的作用
1. 提高了重用性,就像一个函数
2. 对数据库重构,却不影响程序的运行
3. 提高了安全性能,可以对不同的用户
4. 让数据更加清晰
MySQL基础
数据库进阶