python使用mysql 昨日内容: 二. pymysql (Python操作MySQL) 事务: (重点)

一. 外键的变种 (*************)

唯一索引

unique('name') : 此列是不能重复的
联合唯一索引:
unique('name', 'age') : 这两列的值不能重复

一对多
department:
id depart_name
1 公关部
2 xxx 部

user:
id username depart_id (外键的约束)
1 root 1
2 root2 2
3 root3 1

一对一

看业务的需求
user:
id username depart_id (外键的约束)
1 root 1
2 root2 2
3 root3 1

blog:
id url user_id (唯一 + 外键约束)
1 /root/ 1
2 /root3/ 3

多对多

user:

id username 
1 root 
2 root2 
3 root3 


host:
id hostname
1 c1.com
2 c2.com
3 c3.com


user2host:

id uid hid (联合唯一 + 外键)
1 1 1
2 1 2
3 3 1
4 3 3




二. 数据行的详细操作


增:
insert into t1 (name, age) values ('lxxx', 12);
insert into t1 (name, age) values ('lxxx', 12), ('xxxxx', 13), ('xxxxxx', 13);
insert into t1 (name, age) select name, age from t2;

删:
delete from t1;
delete from t1 where name='xxx' and age!=12;

更新:
update t1 set name='xxx', age=123 where name='xxxx' and age=13;

查询:

通配符:
like name '李'
% : 匹配所有
_ : 匹配一个字符

限制取数据:
limit 从第几(索引)条开始取, 去多少条数据

分页: (***********)
page = 1,2,3,4,5...n
offset = 10

limit (page-1)*offset, offset;

排序:
order by 列名 asc(升序), desc(降序)


分组:
将数据按照某一列进行分组

group by + 聚合函数 (count/sum()/avg()/max()/min())

having

连表:
left join :
左边的全部显示

right join:
右边的全部显示

left join


今日内容:


一. 作业

navcate formysql

1、查询所有大于60分的学生的姓名和学号

思路:
那几张表:
关联 2张表: student score

select * from score left join student on score.student_id = student.sid;



查询没学过“李平”老师课的同学的学号、姓名



查询学过“李平”老师课的同学的学号、姓名



"李萍老师"教的课程ID


查询
至少有一门课与 学号为“1”的同学所学课程相同 的同学的学号和姓名


1 2,4


select course_id from score where student_id=1; ## 1,2,4


select student_id from score where course_id in (select course_id from score where student_id=1) 

select sid ,sname from student where sid in (select student_id from score where course_id in (select course_id from score where student_id=1) having sid!=1) 


select student.sid, student.sname from student left join score on student.sid = score.student_id where sid!=1 and course_id in (select course_id from score where student_id=1)




tee : 重定向导入某一个文件

二. pymysql (Python操作MySQL)

pip3 install pymysql



注意:

a. conn, cursor 用完了需要关闭资源连接

b. 查询的时候, fetchone, fetchmany, fetchall, 默认返回的是元组, 需要返回字典的话: cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

c. 删除和更新的时候, 需要在execute之后, 添加 conn.commit()



PyMySQL: (*******************************)

a. 登录验证

写sql语句的时候, %传值的时候, 需要加引号:
sql = "select * from t4 where name = '%s' and pwd = '%s'" % (username, pwd)

上面的sql语句带来的风险是:

例一:
username = zekai' #

select * from t4 where name = 'zekai' #' and pwd = ''

例二:
username = dbsahvbdsha' or 1=1 #

select * from t4 where name = 'dbsahvbdsha' or 1=1 

上面出现的问题,我们称之为 SQL注入 (**********************************)

出现问题的根源是:

因为太过于相信用户的输入, 导致我们在接受用户输入的参数的时候, 并没有对他进行转义

解决SQL注入:

1. 自己手工对用户输入的值进行转义

2. 使用execute()自动进行过滤

sql = "select * from t4 where name = %s and pwd = %s"

cursor.execute(sql,(username, pwd))

#$## 插入一条
cursor.execute(sql, ('lxxx', '1234'))

### 插入多条
data = [
('aaaaa', 'aaa'),
('bbbb', 'bbb'),
('ffff', '666'),
('rrrr', '888'),
]
cursor.executemany(sql, data)


try:
cursor.execute(sql, ('lxxx', '1234'))

### 删除和更新的时候, 需要事物提交
conn.commit()
except Exception as e:
conn.rollback()


cursor.lastrowid : 最后一行的行数


事务: (重点)

一组操作, 要么都成功, 要么都失败

特性:
原子性: 一组操作, 要么都成功, 要么都失败
一致性(Consistency):指事务发生前和发生后,数据的总额依然匹配
隔离性(Isolation):简单点说,某个事务的操作对其他事务不可见的
持久性(Durability):当事务完成后,其影响应该保留下来,不能撤消,只能通过“另开起一个事物”来抵消之前的错误

场景:
思考:
我去银行给朋友汇款,
我卡上有1000元,
朋友卡上500元,
我给朋友转账100元(无手续费),
如果,网线断了, 我的钱刚扣,而朋友的钱又没加时, 怎么办?

create table t11 (
id int auto_increment primary key,
name varchar(32) not null default '',
money int not null default 0
)engine=Innodb charset=utf8;

insert into t11 (name,money) values ('zekai', 1000), ('eagon', 500);


解决方法:

开启事务 (start transaction)

(执行sql操作)

commit : 提交上面的SQL, 让其生效

rollback: 回滚

show full tables; 显示全部类型

--------------------------------------------------------------------------

下面这些了解:

视图:

产生的原因:
如果有一个SQL语句频繁的会被使用到,比如说:
select * from t4 where id>12 and id <24;

搞一个映射,或者取一个别名
select * from t4 where id>12 and id <24 === > v1
视图:

select * from v1;

创建视图:

create view v1 as select * from t4 where id>12 and id <24;

修改视图:
alter view v1 as sql语句;

删除视图:
drop view v1;


问题:
如果原生的表数据发生了变化, 那视图会不会发生变化? 也会变化

视图中的数据会不会发生修改? 不会发生修改

应用场景:

MySQL: (DBA)
生成视图View

程序:
调用 select * from v1;



函数:

不要轻易使用

在程序中, 用代码计算, 计算好了, 再传给SQL语句执行


存储过程:

将一大堆 SQL 语句进行封装, 类似于函数, 结果就是存储过程

MySQL服务端:
DBA (写)


a. 简单的存储过程:
delimiter //
create procedure p1()
BEGIN
select * from t11;
END //
delimiter ;

程序:
call p1();

b. 传参数: (in)
delimiter //
create procedure p2(
in n1 int,
in n2 int
)
BEGIN
select * from t11 where id > n1;
END //
delimiter ;

程序:
call p2(12, 2)

c. 传入参数: (out)

delimiter //
create procedure p3(
in n1 int,
out n2 int
)
BEGIN
select * from t11 where id > n1;
set n2 = 1;
END //
delimiter ;


set @v2=123212;
call p3(12, @v2);

select @v2;


触发器:

向用户表中添加一条数据的同时, 在日志表中也添加一条记录

delimiter //
CREATE TRIGGER t1 BEFORE INSERT ON t7 FOR EACH ROW
BEGIN
insert into t11 (name, money) values ('xxx', 1234);
END //
delimiter ;