Python mysql,事务,索引,视图

数据库,也就是学习如何操作数据,管理数据

对数据库的操作

-- 数据库的操作
数据库:存储数据的仓库

默认安装数据库的路径在: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.列
内连接查询:查询的结果为两个表匹配到的数据
内连接查询.png
使用内连接查询班级表与学生表
select * from students inner join classes on students.cls_id = classes.id;
右连接查询:查询的结果为两个表匹配到的数据,右表特有的数据,对于左表中不存在的数据使用null填充
右连接查询.png
使用右连接查询班级表与学生表
select * from students as s right join classes as c on s.cls_id = c.id;
左连接查询:查询的结果为两个表匹配到的数据,左表特有的数据,对于右表中不存在的数据使用null填充
左连接查询.png
使用左连接查询班级表与学生表,此处使用了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基础
数据库进阶

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270