数据库,多表数据

---恢复内容开始---

多表数据:

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);

emp
+----+----------+--------+--------+
| id | name     | salary | dep_id |
+----+----------+--------+--------+
|  1 | egon     |      3 |      2 |
|  2 | yanghuhu |      2 |      2 |
|  3 | sanjiang |     10 |      1 |
|  4 | owen     |  88888 |      2 |
|  5 | liujie   |      8 |      1 |
|  6 | yingjie  |    1.2 |      0 |
+----+----------+--------+--------+

dep
+----+-----------+--------+
| id | name      | work   |
+----+-----------+--------+
|  1 | 市场部    | 销售   |
|  2 | 教学部    | 授课   |
|  3 | 管理部    | 开车   |
+----+-----------+--------+

多表连接=>虚拟的单表
内连接

左表 inner join 右表 on 两表有关联的字段的条件 
select  * from emp inner join dep on emp.dep_id = dep.id;

左连接 
左表 left join 右表 on 两表有关联的字段的条件
select * from  emp left join dep on emp.dep_id = dep.id;

右连接
左表 right join 右表  on 两表有关联的字段的条件

全连接
select * from emp left join dep  on emp.dep_id = dep.id
union
select * from emp right join dep on emp.dep_id = dep.id;

总结,内连接,两表之间存在对应关系的行数才会显示
        左连接 左表所有行数都会显示
        右连接 右表所有行数都会显示
        全连接,将左连接和右连接的结果去重

练习:
查询每一位员工对应的工作职责
select emp.name ,dep.work from emp left join dep on emp.dep_id = dep.id;
2.查询每一个部门下的员工们及员工职责
select  max(dep.name) "部门" , group_concat(emp.name)  "员工",max(dep.work)  "职责"  from emp right join dep on emp.dep_id = dep.id group by emp.dep_id; 

pymysql模块

#数据库不存在报错,用户和密码不正确报错,port 为数字,其他都是字符串形式
1.建立连接
c = pymysql.connect(host = "localhost",port = 3306,db = "db5",user = "root",password = "123")

2.设置游标
①cursor = c.cursor()#fetchone结果以元组输出,fetchall的结果是元组,元素是每行元素组成的元组
②cursor = c.cursor(pymysql.cursor.DictCursor)#fetchone结果以字典输出,fetchall的结果是列表,元素是每行元素组成的字典

3.书写sql语句,并执行其结果
sql = "slect * from emp"
line = cursor.execute(sql)#返回数据总行数,修改或新增的话返回修改或新增的行数

查询
都无法读出字段信息,没有数据可读时都不会报错
①fetchone一次读一行
②fetchmany(num)指定行数读
③fetchall()全读

4.指针移动:
cursor.scroll(num,mode)
#mode两种(字符串)
①"relative"相对移动
#num>0 向前,num<0 向后
num可移动范围报错
②"absolute"绝对移动
num范围0到line-1,超范围报错

5.提交,不提交的话,无法保存修改和新增的数据
c.commit()

6.断开连接
cursor.close()
c.close()

pymysql sql注入
mysql注释:
/**/
-- 两杠加空格

根本原理:就根据程序的字符串拼接name='%s',我们输入一个xxx' -- haha,用我们输入的xxx加'在程序中拼接成一个判断条件name='xxx' -- haha'

import pymysql
c = pymysql.connect(host ="localhost",port = 3306,db= "db5",user ="root",passwd="123")
cursor = c.cursor(pymysql.cursors.DictCursor)
name = input("input your name>>:").strip()
pwd = input("input your pwd>>:").strip()
sql = "select * from user where name = '%s' and pwd ='%s' "%(name,pwd)
line = cursor.execute(sql)
if line:
    print("login successful")
else:
    print("login fail")


input your name>>:bob
input your pwd>>:123
login successful


 "select * from user where name = '%s' and pwd ='%s' "
原理 name = '%s'    %s就是我们输入的数据
-- 后面会认为是空格 需要 再加分号
select * from user where usr="aaa" or 1=1 -- hehe" and pwd="000";
知道用户名时
bob';-- ' 两个分号是匹配最外侧两个分号,也就是%s外面的两个分号用
input your name>>:bob';-- '
input your pwd>>:fafadsfdsa
login successful
当不知道用户名时
dsafa' or 1=1; -- '
input your name>>:dsafa' or 1=1; -- '
input your pwd>>:fdafsa
login successful

解决方案

# 原来是我们对sql进行字符串拼接
# sql="select * from userinfo where name='%s' and password='%s'" %(user,pwd)
# res=cursor.execute(sql)

#改写为(execute帮我们做字符串拼接,我们无需且一定不能再为%s加引号了)
sql="select * from userinfo where name=%s and password=%s" #!!!注意%s需要去掉引号,因为pymysql会自动为我们加上
res=cursor.execute(sql,[user,pwd]) #pymysql模块自动帮我们解决sql注入的问题,只要我们按照pymysql的规矩来。

---恢复内容结束---

猜你喜欢

转载自www.cnblogs.com/robert-zhou/p/10257421.html