Mysql基础知识

时间:2019-09-26
本文章向大家介绍Mysql基础知识,主要包括Mysql基础知识使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Mysql学习

"""
1、字段修改
    alter modify
    alter change
    alter add ''|first|after
    alter drop

2、表关系:
    一对一:外键存在两边都可以
    一对多:外键存在多的一方
    多对多:外键必须存在第三张关系表
    外键:外键是表的一个字段,值可以重复也可以唯一,值是被关联表被关联字段的值,被关联字段必须有唯一键
    foreign key(外键字段) references 被关联表(被关联字段)
    
    create table book(
        id int not null primary key auto_increment,
        name varchar(64) unique
    );
    create table author(
        id int not null primary key auto_increment,
        name varchar(64) unique
    );
    create table book_author(
        id int not null primary key auto_increment,
        book_name varchar(64),
        author_name varchar(64),
        foreign key(book_name) references book(name)
        on update cascade
        on delete cascade,
        foreign key(author_name) references author(name)
        on update cascade
        on delete cascade
    );
"""

单表查询

"""
增:
insert [into] 
    [数据库名.]表名[(字段1[, ..., 字段n])] 
values 
    (数据1[, ..., 数据n])[, ..., (数据1[, ..., 数据n])];

删:
delete from [数据库名.]表名 [条件];

改:
updata [数据库名.]表名 set 字段1=值1[, ..., 字段n=值n] [条件];

查:
select [distinct] 字段1 [[as] 别名1],...,字段n [[as] 别名n] from [数据库名.]表名 [条件];
"""

# 条件:from、where、group by、having、distinct、order by、limit => 层层筛选后的结果
# 注:一条查询语句,可以拥有多种筛选条件,条件的顺序必须按照上方顺序进行逐步筛选,distinct稍有特殊(书写位置),条件的种类可以不全
# 可以缺失,但不能乱序

去重:distinct

mysql>: 
create table t1(
    id int,
    x int,
    y int
);

mysql>: insert into t1 values(1, 1, 1), (2, 1, 2), (3, 2, 2), (4, 2, 2);

mysql>: select distinct * from t1;  # 全部数据

mysql>: select distinct x, y from t1;  # 结果 1,1  1,2  2,2

mysql>: select distinct y from t1;  # 结果 1  2

# 总结:distinct对参与查询的所有字段,整体去重(所查的全部字段的值都相同,才认为是重复数据)

数据准备

CREATE TABLE `emp`  ( 
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) NOT NULL,
  `gender` enum('男','女','未知') NULL DEFAULT '未知',
  `age` int(0) NULL DEFAULT 0,
  `salary` float NULL DEFAULT 0,
  `area` varchar(20) NULL DEFAULT '中国',
  `port` varchar(20) DEFAULT '未知',
  `dep` varchar(20),
  PRIMARY KEY (`id`)
);

INSERT INTO `emp` VALUES 
    (1, 'yangsir', '男', 42, 10.5, '上海', '浦东', '教职部'),
    (2, 'engo', '男', 38, 9.4, '山东', '济南', '教学部'),
    (3, 'jerry', '女', 30, 3.0, '江苏', '张家港', '教学部'),
    (4, 'tank', '女', 28, 2.4, '广州', '广东', '教学部'),
    (5, 'jiboy', '男', 28, 2.4, '江苏', '苏州', '教学部'),
    (6, 'zero', '男', 18, 8.8, '中国', '黄浦', '咨询部'),
    (7, 'owen', '男', 18, 8.8, '安徽', '宣城', '教学部'),
    (8, 'jason', '男', 28, 9.8, '安徽', '巢湖', '教学部'),
    (9, 'ying', '女', 36, 1.2, '安徽', '芜湖', '咨询部'),
    (10, 'kevin', '男', 36, 5.8, '山东', '济南', '教学部'),
    (11, 'monkey', '女', 28, 1.2, '山东', '青岛', '教职部'),
    (12, 'san', '男', 30, 9.0, '上海', '浦东', '咨询部'),
    (13, 'san1', '男', 30, 6.0, '上海', '浦东', '咨询部'),
    (14, 'san2', '男', 30, 6.0, '上海', '浦西', '教学部'),
    (15, 'ruakei', '女', 67, 2.501, '上海', '陆家嘴', '教学部');

常用函数

"""
拼接:concat() | concat_ws()
大小写:upper() | lower()
浮点型操作:ceil() | floor() | round()
整型:可以直接运算
"""
mysql>: select name,area,port from emp;
mysql>: select name as 姓名, concat(area,'-',port) 地址 from emp;  # 上海-浦东
mysql>: select name as 姓名, concat_ws('-',area,port,dep) 信息 from emp;  # 上海-浦东-教职部

mysql>: select upper(name) 姓名大写,lower(name) 姓名小写 from emp;

mysql>: select id,salary,ceil(salary)上薪资,floor(salary)下薪资,round(salary)入薪资 from emp;

mysql>: select name 姓名, age 旧年龄, age+1 新年龄 from emp;

条件:where

# 多条件协调操作导入:where 奇数 [group by 部门 having 平均薪资] order by [平均]薪资 limit 1

mysql>: select * from emp where id<5 limit 1;  # 正常
mysql>: select * from emp limit 1 where id<5;  # 异常,条件乱序

# 判断规则
"""
比较符合:>  |  <  |  >=  |  <=  |  =  |  !=
区间符合:between 开始 and 结束 |  in(自定义容器)
逻辑符合:and  |  or  |  not
相似符合:like _|%
正则符合:regexp 正则语法
"""
mysql>: select * from emp where salary>5;
mysql>: select * from emp where id%2=0;

mysql>: select * from emp where salary between 6 and 9;

mysql>: select * from emp where id in(1, 3, 7, 20);

# _o 某o | __o 某某o | _o% 某o* (*是0~n个任意字符) | %o% *o*
mysql>: select * from emp where name like '%o%';
mysql>: select * from emp where name like '_o%';  
mysql>: select * from emp where name like '___o%';

# sql只支持部分正则语法
mysql>: select * from emp where name regexp '.*\d';  # 不支持\d代表数字,认为\d就是普通字符串
mysql>: select * from emp where name regexp '.*[0-9]';  # 支持[]语法

分组与筛选:group by | having

where与having
# 表象:在没有分组的情况下,where与having结果相同
# 重点:having可以对 聚合结果 进行筛选
mysql>: select * from emp where salary > 5;
mysql>: select * from emp having salary > 5;

mysql>: select * from emp where id in (5, 10, 15, 20);
mysql>: select * from emp having id in (5, 10, 15, 20);
聚合函数
"""
max():最大值
min():最小值
avg():平均值
sum():和
count():记数
group_concat():组内字段拼接,用来查看组内其他字段
"""
分组查询 group by
# 修改my.ini配置重启mysql服务
sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

# 在sql_mode没有 ONLY_FULL_GROUP_BY 限制下,可以执行,但结果没有意义
# 有 ONLY_FULL_GROUP_BY 限制,报错
mysql>: select * from emp group by dep;

# 分组后,表中数据考虑范围就不是 单条记录,因为每个分组都包含了多条记录,参照分组字段,对每个分组中的 多条记录 统一处理
# eg: 按部门分组,每个部门都有哪些人、最高的薪资、最低的薪资、平均薪资、组里一共有多少人

# 将多条数据统一处理,这种方式就叫 聚合
# 每个部门都有哪些人、最高的薪资、最低的薪资、平均薪资 都称之为 聚合结果 - 聚合函数操作的结果
# 注:参与分组的字段,也归于 聚合结果
Group by的用法
GROUP BY 语句根据一个或多个列对结果集进行分组。在分组的列上我们可以使用 COUNT, SUM, AVG,等函数。

mysql>: 
select 
    dep 部门,
    group_concat(name) 成员,
    max(salary) 最高薪资,
    min(salary) 最低薪资,
    avg(salary) 平均薪资,
    sum(salary) 总薪资,
    count(gender) 人数
from emp group by dep;

mysql>: select 
    dep 部门,
    max(age) 最高年龄
from emp group by dep;

# 总结:分组后,查询条件只能为 分组字段 和 聚合函数操作的聚合结果
分组后的having
mysql>: 
select 
    dep 部门,
    group_concat(name) 成员,
    max(salary) 最高薪资,
    min(salary) 最低薪资,
    avg(salary) 平均薪资,
    sum(salary) 总薪资,
    count(gender) 人数
from emp group by dep;

# 最低薪资小于2
mysql>:
select 
    dep 部门,
    group_concat(name) 成员,
    max(salary) 最高薪资,
    min(salary) 最低薪资,
    avg(salary) 平均薪资,
    sum(salary) 总薪资,
    count(gender) 人数
from emp group by dep having min(salary)<2;

# having可以对 聚合结果 再进行筛选,where不可以

排序

排序规则
# order by 主排序字段 [asc|desc], 次排序字段1 [asc|desc], ...次排序字段n [asc|desc]
未分组状态下
mysql>: select * from emp;

# 按年龄升序
mysql>: select * from emp order by age asc;
# 按薪资降序
mysql>: select * from emp order by salary desc;

# 按薪资降序,如果相同,再按年龄降序
mysql>: select * from emp order by salary desc, age desc;
# 按龄降序,如果相同,再按薪资降序
mysql>: select * from emp order by age desc, salary desc;
分组状态下
mysql>:
select 
    dep 部门,
    group_concat(name) 成员,
    max(salary) 最高薪资,
    min(salary) 最低薪资,
    avg(salary) 平均薪资,
    sum(salary) 总薪资,
    count(gender) 人数
from emp group by dep;

# 最高薪资降序
mysql:
select 
    dep 部门,
    group_concat(name) 成员,
    max(salary) 最高薪资,
    min(salary) 最低薪资,
    avg(salary) 平均薪资,
    sum(salary) 总薪资,
    count(gender) 人数
from emp group by dep 
order by max(salary) desc;

限制 limit

# 语法:limit 条数  |  limit 偏移量,条数
mysql>: select name, salary from emp where salary<8 order by salary desc limit 1;

mysql>: select * from emp limit 5,3;  # 先偏移5条满足条件的记录,再查询3条

连表查询

连接

# 连接:将有联系的多张表通过关联(有联系就行,不一定是外键)字段,进行连接,形参一张大表
# 连表查询:在大表的基础上进行查询,就称之为连表查询

# 将表与表建立连接的方式有四种:内连接、左连接、右连接、全连接

mysql>: create database db3;
mysql>: use db3;

mysql>: 
create table dep(
    id int primary key auto_increment,
    name varchar(16),
    work varchar(16)
);
create table emp(
    id int primary key auto_increment,
    name varchar(16),
    salary float,
    dep_id int
);
insert into dep values(1, '市场部', '销售'), (2, '教学部', '授课'), (3, '管理部', '开车');
insert into emp(name, salary, dep_id) values('egon', 3.0, 2),('yanghuhu', 2.0, 2),('sanjiang', 10.0, 1),('owen', 88888.0, 2),('liujie', 8.0, 1),('yingjie', 1.2, 0);

笛卡尔积

# 笛卡尔积: 集合 X{a, b} * Y{o, p, q} => Z{{a, o}, {a, p}, {a, q}, {b, o}, {b, p}, {b, q}}

mysql>: select * from emp, dep;

# 总结:是两张表 记录的所有排列组合,数据没有利用价值

内连接

# 关键字:inner join on
# 语法:from A表 inner join B表 on A表.关联字段=B表.关联字段

mysql>: 
select 
    emp.id,emp.name,salary,dep.name,work 
from emp inner join dep on emp.dep_id = dep.id 
order by emp.id;

# 总结:只保留两个表有关联的数据

左连接

# 关键字:left join on
# 语法:from 左表 left join 右表 on 左表.关联字段=右表.关联字段

mysql>: 
select 
    emp.id,emp.name,salary,dep.name,work 
from emp left join dep on emp.dep_id = dep.id 
order by emp.id;

# 总结:保留左表的全部数据,右表有对应数据直接连表显示,没有对应关系空填充

右连接

# 关键字:right join on
# 语法:from A表 right join B表 on A表.关联字段=B表关联字段

mysql>: 
select 
    emp.id,emp.name,salary,dep.name,work 
from emp right join dep on emp.dep_id = dep.id 
order by emp.id;

# 总结:保留右表的全部数据,左表有对应数据直接连表显示,没有对应关系空填充

左右可以相互转化

mysql>: 
select 
    emp.id,emp.name,salary,dep.name,work 
from emp right join dep on emp.dep_id = dep.id 
order by emp.id;

mysql>: 
select 
    emp.id,emp.name,salary,dep.name,work 
from dep left join emp on emp.dep_id = dep.id 
order by emp.id;

# 总结:更换一下左右表的位置,相对应更换左右连接关键字,结果相同

全连接

mysql>: 
select 
    emp.id,emp.name,salary,dep.name,work 
from emp left join dep on emp.dep_id = dep.id 

union

select 
    emp.id,emp.name,salary,dep.name,work 
from emp right join dep on emp.dep_id = dep.id 

order by id;

# 总结:左表右表数据都被保留,彼此有对应关系正常显示,彼此没有对应关系均空填充对方

一对一与一对多情况一致

create table author(
    id int,
    name varchar(64),
    detail_id int
);
create table author_detail(
    id int,
    phone varchar(11)
);
insert into author values(1, 'Bob', 1), (2, 'Tom', 2), (3, 'ruakei', 0);
insert into author_detail values(1, '13344556677'), (2, '14466779988'), (3, '12344332255');

select author.id,name,phone from author join author_detail on author.detail_id = author_detail.id order by author.id;

select author.id,name,phone from author left join author_detail on author.detail_id = author_detail.id
union
select author.id,name,phone from author right join author_detail on author.detail_id = author_detail.id
order by id;

多对多

# 在一对一基础上,建立 作者与书 的
create table author(
    id int,
    name varchar(64),
    detail_id int
);
insert into author values(1, 'Bob', 1), (2, 'Tom', 2), (3, 'ruakei', 0);

create table book(
    id int,
    name varchar(64),
    price decimal(5,2)
);
insert into book values(1, 'python', 3.66), (2, 'Linux', 2.66), (3, 'Go', 4.66);

create table author_book(
    id int,
    author_id int,
    book_id int
);
# 数据:author-book:1-1,2  2-2,3  3-1,3
insert into author_book values(1,1,1),(2,1,2),(3,2,2),(4,2,3),(5,3,1),(6,3,3);

# 将有关联的表一一建立连接,查询所以自己所需字段
select book.name, book.price, author.name, author_detail.phone from book 
join author_book on book.id = author_book.book_id
join author on author_book.author_id = author.id
left join author_detail on author.detail_id = author_detail.id;

联合分组

# 数据来源:在单表emp下

# 联合分组:按多个字段综合结果进行分组

# 按 area与port组合后的结果进行分组,只有组合后的结果还一致,才认为是一组
select group_concat(name),area,port from emp group by area,port;

子查询

# 增:insert into 表 select子查询
# 删:delete from 表 条件是select子查询(表不能与delete表相同)
# 查:select 字段 from 表 条件是select子查询
# 改:update 表 set 字段=值 条件是select子查询(表不能与update表相同)
# 数据来源:在单表emp下

# 子查询:将一条查询sql的结果作为另一条sql的条件

# 思考:每个部门最高薪资的那个人所有信息

# 子查询的sql
select dep, max(salary) from emp group by dep;
# 子查询 - 查
select * from emp where (dep, salary) in (select dep, max(salary) from emp group by dep);

# 将子查询转换为一张表
# 创建一个存子查询数据的一张表
create table t1(dep_name varchar(64), max_salary decimal(5,2));
# 子查询 - 增
insert into t1   select dep, max(salary) from emp group by dep;
# 需求
select name, dep_name, salary 
from emp join t1 
on emp.dep=t1.dep_name and emp.salary=t1.max_salary;

# 子查询 - 改(update更新的表不能 与 子查询select的表同表)
# 每个部门最大薪资+1
update t1 set max_salary=max_salary+1;
# 给t1额外增加一个新部门
insert into t1 values ('打杂部', 100);
# 子查询 - 改
update t1 set max_salary=max_salary+1 where dep_name in (select distinct dep from emp);
# 错误:update更新的表 与 子查询select的表 相同
update t1 set max_salary=max_salary+1 where dep_name in (select distinct dep_name from t1);

# 子查询 - 删
delete from t1 where dep_name in (select distinct dep from emp);
# 错误: delete删除的表 与 子查询select的表 相同
delete from t1 where dep_name in (select distinct dep_name from t1);

all与any:区间修饰条件

# 语法规则
# where id in (1, 2, 3) => id是1或2或3
# where id not in (1, 2, 3) => id不是1,2,3
# where salary < all(3, 6, 9) => salary必须小于所有情况(小于最小)
# where salary > all(3, 6, 9) => salary必须大于所有情况(大于最大)
# where salary < any(3, 6, 9) => salary只要小于一种情况(小于最大)
# where salary > any(3, 6, 9) => salary只要大于一种情况(大于最小)
in < > ()
# 案例
select * from emp where salary < all(select salary from emp where id>11);

视图:view

# 数据依赖:单表emp
"""
1)视图是存在内存中的临时表
2)视图的创建依赖select语句,所有就是select语句操作的结果形参的表
3)视图支持对数据的增删查改 ?
4)视图不允许对视图表的字段做修改
5)视图不仅支持创建,也支持更新与删除
"""
# 语法
# 创建视图
mysql>: create view 视图名[(别名们)] as select 语句;
eg>: create view v1 as select dep, max(salary) from emp group by dep;

# 创建或替换视图
mysql>: create or replace 视图名[(别名们)] as select 语句;
mysql>: alter 视图名[(别名们)] as select 语句;
eg>: create or replace view v1(dep_name, max_salary) as select dep, max(salary) from emp group by dep;
eg>: alter view v1(name, salary) as select dep, max(salary) from emp group by dep;

# 删除视图
mysql>: drop view 视图名
eg>: drop view v1;

# 视图可以作为正常表完成连表查询
select name, dep_name, salary 
from emp join v1 
on emp.dep=v1.dep_name and emp.salary=v1.max_salary;

视图的增删改

# 前提:视图的增删改操作可以直接映射给真实表(本质就是对真实表进行操作)

# 视图可以完成增删改,增删改本质是直接对创建视图的真实表进行操作
create or replace view v2 as select id,name,age,salary from emp;
update v2 set salary=salary+1 where id=1;
delete from v2 where id=1;

create or replace view v3 as select * from emp;
insert into v3 values(1, 'yangsir', '男', 66, 1.11, '上海', '那噶的', '教职部');

# 总结:操作视图,会影响真实表,反之也会影响
update emp set salary=salary+1 where id=1;

事务

# 事务:通常一些业务需要多条sql参与,参与的sql会形参一个执行整体,该整体我们就称之为 事务
# 简而言之:事务 - 就是保护多条执行的sql语句
# 比如:转账就是一个事务:从一个用户将资金转出,再将资金转入到另一个用户

""" 事务的四大特性
1.原子性:事务是一组不可分割的单位,要么同时成功,要么同时不成功
2.一致性:事物前后的数据完整性应该保持一致(数据库的完整性:如果数据库在某一时间点下,所有的数据都符合所有的约束,则称数据库为完整性的状态)
3.隔离性:事物的隔离性是指多个用户并发访问数据时,一个用户的事物不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离
4.持久性:持久性是指一个事物一旦被提交,它对数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
"""

# mysql中事务的执行
create table bank(
    id int,
    name varchar(16),
    money decimal(65, 2)
);
insert into bank values(1, 'Tom', 10), (2, "Bob", 10);

# 假设出现以下执行情况

# 没有事务支持情况下,Tom的钱就丢了
update bank set money=money-1 where name='Tom';
update bank set money=money+1 where name='ruakei';

# 将两条sql看做事务处理
# 开启事务
begin;
update bank set money=money-1 where name='Tom';
update bank set money=money+1 where name='ruakei';
# 确认无误,提交事务
commit;
# 确认有误,回滚
rollback;

pymysql:python操作mysql

安装

>: pip3 install pymysql

增删改查

# 选取操作的模块 pymysql

# pymysql连接数据库的必要参数:主机、端口、用户名、密码、数据库
# 注:pymysql不能提供创建数据库的服务,数据库要提前创建
import pymysql

# 1)建立数据库连接对象 conn
# 2)通过 conn 创建操作sql的 游标对象
# 3)编写sql交给 cursor 执行
# 4)如果是查询,通过 cursor对象 获取结果
# 5)操作完毕,端口操作与连接


# 1)建立数据库连接对象 conn
conn = pymysql.connect(user='root', passwd='root', database='oldboy')
# conn = pymysql.connect(user='root', passwd='root', database='oldboy', autocommit=True)

# 2)通过 conn 创建操作sql的 游标对象
# 注:游标不设置参数,查询的结果就是数据元组,数据没有标识性
# 设置pymysql.cursors.DictCursor,查询的结果是字典,key是表的字段
cursor = conn.cursor(pymysql.cursors.DictCursor)

# 3)编写sql交给 cursor 执行
创建表
# 创建表
sql1 = 'create table t1(id int, x int, y int)'
cursor.execute(sql1)
sql2 = 'insert into t1 values(%s, %s, %s)'

# 增1
cursor.execute(sql2, (1, 10, 100))
cursor.execute(sql2, (2, 20, 200))
# 重点:在创建conn对象时,不设置autocommit,默认开启事务,增删改操作不会直接映射到数据库中,
# 需要执行 conn.commit() 动作
conn.commit()

# 增多
cursor.executemany(sql2, [(3, 30, 300), (4, 40, 400)])
conn.commit()
sql3 = 'delete from t1 where id=%s'
cursor.execute(sql3, 4)
conn.commit()
sql4 = 'update t1 set y=666 where id=2'
cursor.execute(sql4)
conn.commit()
sql5 = 'select * from t1'
row = cursor.execute(sql5)  # 返回值是受影响的行
print(row)

# 4)如果是查询,通过 cursor对象 获取结果
# fetchone() 偏移一条取出,fetchmany(n) 偏移n条取出,fetchall() 偏移剩余全部
r1 = cursor.fetchone()
print(r1)
r2 = cursor.fetchone()
print(r2)
r3 = cursor.fetchmany(1)
print(r3)
r4 = cursor.fetchall()
print(r4)
# 5)操作完毕,端口操作与连接
cursor.close()
conn.close()

游标操作

import pymysql
from pymysql.cursors import DictCursor

# 1)建立数据库连接对象 conn
conn = pymysql.connect(user='root', passwd='root', db='oldboy')
# 2)通过 conn 创建操作sql的 游标对象
cursor = conn.cursor(DictCursor)
# 3)编写sql交给 cursor 执行
sql = 'select * from t1'
# 4)如果是查询,通过 cursor对象 获取结果
row = cursor.execute(sql)
if row:
    r1 = cursor.fetchmany(2)
    print(r1)

    # 操作游标
    # cursor.scroll(0, 'absolute')  # absolute绝对偏移,游标重置,从头开始偏移
    cursor.scroll(-2, 'relative')  # relative相对偏移,游标在当前位置进行左右偏移

    r2 = cursor.fetchone()
    print(r2)

# 5)操作完毕,端口操作与连接
cursor.close()
conn.close()

pymysql事务

import pymysql
from pymysql.cursors import DictCursor
conn = pymysql.connect(user='root', passwd='root', db='oldboy')
cursor = conn.cursor(DictCursor)

try:
    sql = 'create table t2(id int, name char(4), money int)'
    row = cursor.execute(sql)
    print(row)
except:
    print('表已创建')
    pass

# 空表才插入
row = cursor.execute('select * from t2')
if not row:
    sql = 'insert into t2 values(%s,%s,%s)'
    row = cursor.executemany(sql, [(1, 'tom', 10), (2, 'Bob', 10)])
    conn.commit()


# 可能会出现异常的sql
"""
try:
    sql1 = 'update t2 set money=money-1 where name="tom"'
    cursor.execute(sql1)
    sql2 = 'update t2 set moneys=money+1 where name="Bob"'
    cursor.execute(sql2)
except:
    print('转账执行异常')
    conn.rollback()
else:
    print('转账成功')
    conn.commit()
"""

try:
    sql1 = 'update t2 set money=money-1 where name="tom"'
    r1 = cursor.execute(sql1)
    sql2 = 'update t2 set money=money+1 where name="ruakei"'  # 转入的人不存在
    r2 = cursor.execute(sql2)
except:
    print('转账执行异常')
    conn.rollback()
else:
    print('转账没有异常')
    if r1 == 1 and r2 == 1:
        print('转账成功')
        conn.commit()
    else:
        conn.rollback()

sql注入

import pymysql
from pymysql.cursors import DictCursor
conn = pymysql.connect(user='root', passwd='root', db='oldboy')
cursor = conn.cursor(DictCursor)

try:
    sql = 'create table user(id int, name char(4), password char(6))'
    row = cursor.execute(sql)
    print(row)
except:
    print('表已创建')
    pass

# 空表才插入
row = cursor.execute('select * from user')
if not row:
    sql = 'insert into user values(%s,%s,%s)'
    row = cursor.executemany(sql, [(1, 'tom', '123'), (2, 'bob', 'abc')])
    conn.commit()



# 用户登录
usr = input('usr: ')
pwd = input('pwd: ')

# 自己拼接参数一定有sql注入,将数据的占位填充交给pymysql

"""
sql = 'select * from user where name="%s" and password="%s"' % (usr, pwd)
row = cursor.execute(sql)
if row:
    print('登录成功')
else:
    print('登录失败')
"""
sql = 'select * from user where name=%s and password=%s'
row = cursor.execute(sql, (usr, pwd))
if row:
    print('登录成功')
else:
    print('登录失败')


# 知道用户名时
# 输入用户时:
#   tom => select * from user where name="tom" and password="%s"
#   tom" # => select * from user where name="tom" #" and password="%s"

# 不自定义用户名时
#   " or 1=1 # => select * from user where name="" or 1=1 #" and password="%s"

索引

# 索引就是 键 - key

"""
1)键 是添加给数据库表的 字段 的
2)给表创建 键 后,该表不仅会形参 表结构、表数据,还有 键的B+结构图
3)键的结构图是需要维护的,在数据完成增、删、改操作时,只要影响到有键的字段,结构图都要维护一次
    所以创建键后一定会降低 增、删、改 的效率
4)键可以极大的加快查询速度(开发需求中,几乎业务都和查有关系)
5)建立键的方式:主键、外键、唯一键、index
"""

import pymysql
from pymysql.cursors import DictCursor
conn = pymysql.connect(user='root', passwd='root', db='oldboy')
cursor = conn.cursor(DictCursor)

# 创建两张表
# sql1 = """create table a1(
#     id int primary key auto_increment,
#     x int,
#     y int
# )"""
# cursor.execute(sql1)
# sql2 = """create table a2(
#     id int primary key auto_increment,
#     x int,
#     y int,
#     index(x)
# )"""
# cursor.execute(sql2)

# 每个表插入5000条数据
# import random
# for i in range(1, 5001):
#     x = i
#     y = random.randint(1, 5000)
#     cursor.execute('insert into a1(x, y) values(%s, %s)', (x, y))
#     cursor.execute('insert into a2(x, y) values(%s, %s)', (x, y))
#
# conn.commit()

import time
# a1的x、a1的id、a2的x
b_time = time.time()
sql = 'select * from a1 where id=4975'
cursor.execute(sql)
e_time = time.time()
print(e_time - b_time)

b_time = time.time()
sql = 'select * from a1 where x=4975'
cursor.execute(sql)
e_time = time.time()
print(e_time - b_time)

b_time = time.time()
sql = 'select * from a2 where x=4975'
cursor.execute(sql)
e_time = time.time()
print(e_time - b_time)

原文地址:https://www.cnblogs.com/kangwy/p/11594547.html