多表操作
外键
什么是外键
外键是指引用另外一个表中的一列或多列,被引用的列应该具有主键约束或唯一性约束。
外键用于建立和加强两个表数据之间的连接。
简单的来说:
MySQL的外键约束(FOREIGN KEY)是表的一个特殊字段。对于两个具有关联关系的表而言,相关联字段中的主键所在表就是主表(父表),外键所在的表就是从表(子表)。
为表添加外键约束
alter table 表名 add constranint FK_ID foreign key (外键字段名) REFERENCES 主表表名(主键字段名);
注意:
(1)查看详细表结构可以用下面的语句:
SHOW CREATR TABLE 表名;
(2)建立外键的表必须是 InnoDB 型,不能是临时表。因为在MySQL中有 InnoDB 类型的表才支持外键。
(3)定义外键名时,不能加引号,如 constraint ‘FK_ID’ 或 constraint “FK_ID” 都是错误的。
添加外键约束的参数说明
删除外键约束
alter table 表名 drop foreign key 外键名;
连接查询
当查询结果的列来源于多张表时,需要将多张表连接成一个大的数据集,再选择合适的列返回mysql。这时我们就需要使用表连接。
交叉连接
SELECT * FROM 表1 CROSS JOIN 表2
CROSS JOIN用于连接两个要查询的表,通过该语句可以查询两个表中所有的数据组合。
内连接
内连接仅选出两张表中互相匹配的记录
SELECT 查询字段 FROM 表1 [INNER] JOIN 表2 ON 表1.关系字段 = 表2.关系字段

外连接(左连接,右连接)
SELECT 所有字段 FROM 表1 LEET | RIGHT [OUTER] JION 表2 ON 表1.关系字段 = 表2.关系字段 WHERE 条件
左连接
查询的结果为两个表匹配到的数据,左表持有的数据,对于右表中不存的数据使用null填充
select * from 表1 left join 表2 on 表1.列 = 表2.列;

右连接
查询结果为两个表匹配到的数据,右表持有的数据,对于左表中不存在的数据使用null填充。
select * from 表1 right join 表2 on 表1.列 = 表2.列;

子查询
子查询是指一个查询语句嵌套在另一个查询语句内部的查询。
在执行查询语句时,首先回执行子查询中的语句,然后将返回的结果作为外层查询的过滤条件。
在子查询中可以使用IN, EXISTS, ANY, ALL操作符。
演示:
创建数据库 CREATE DATABASE chapter05;
选择使用数据库 USE chapter05;
创建表 CREATE TABLE grade( id int(4) NOT NULL PRIMARY KEY, name VARCHAR(36) );
CREATE TABLE student( sid INT(4) NOT NULL PRIMARY KEY, sname VARCHAR(36), gid int(4) NOT NULL );
为表(student)添加外键约束 ALTER TABLE student add CONSTRAINT FK_ID FOREIGN KEY (gid) REFERENCES grade(id);
查看表的结构 DESC student; DESC grade;
查看表的详细结构 SHOW CREATE TABLE student;
删除外键约束 alter TABLE student DROP FOREIGN KEY FK_ID;
查看表结构 SHOW CREATE TABLE student;
MySQL与Python交互

准备数据
创建数据表
-- 创建一个商品 goods 数据表CREATE TABLE goods(id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT NOT NULL,NAME VARCHAR(150) NOT NULL,cate_name VARCHAR(40) NOT NULL,brand_name VARCHAR(40) NOT NULL,price DECIMAL(10,3) NOT NULL DEFAULT 0,is_show TINYINT NOT NULL DEFAULT 1,is_saleoff TINYINT NOT NULL DEFAULT 0);
插入数据
-- 插入数据INSERT INTO goods VALUES(0,'r510vc 15.6英寸笔记本','笔记本','华硕','3399',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'y400n 14.0英寸笔记本电脑','笔记本','联想','4999',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'g150th 15.6英寸游戏本','游戏本','雷神','8499',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'x550cc 15.6英寸笔记本','笔记本','华硕','2799',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'x240 超极本','超级本','联想','4880',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'u330p 13.3英寸超极本','超级本','联想','4299',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'svp13226scb 触控超极本','超级本','索尼','7999',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'ipad mini 7.9英寸平板电脑','平板电脑','苹果','1998',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'ipad air 9.7英寸平板电脑','平板电脑','苹果','3388',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'ipad mini 配备 retina 显示屏','平板电脑','苹果','2788',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'ideacentre c340 20英寸一体电脑 ','台式机','联想','3499',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'vostro 3800-r1206 台式电脑','台式机','戴尔','2899',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'imac me086ch/a 21.5英寸一体电脑','台式机','苹果','9188',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'at7-7414lp 台式电脑 linux )','台式机','宏碁','3699',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'z220sff f4f06pa工作站','服务器/工作站','惠普','4288',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'poweredge ii服务器','服务器/工作站','戴尔','5388',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'mac pro专业级台式电脑','服务器/工作站','苹果','28888',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'hmz-t3w 头戴显示设备','笔记本配件','索尼','6999',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'商务双肩背包','笔记本配件','索尼','99',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'x3250 m4机架式服务器','服务器/工作站','ibm','6888',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'商务双肩背包','笔记本配件','索尼','99',DEFAULT,DEFAULT);
分表
分表是因为当一张表的数据量比较多时,但是我们只需要查询其中的某个字段数据,就会导致查询效率降低,所以此处我们需要使用到分表。当然后面会细讲。
商品分类表
创建 商品分类 表
create table goods_cates(id int unsigned primary key auto_increment not null,name varchar(40) not null);
将 商品表 中的 商品种类 查询并插入到 商品分类表 里
insert into goods_cates (name) select cate_name from goods group by cate_name;
将 商品表 中的 商品种类 更改为 商品表分类表 对应的 id
update goods as g inner join goods_cates as c on g.cate_name=c.name set g.cate_name=c.id;
安装pymysql
在Windows操作系统上安装
Python3:pip install pymysql
Python2:pip install MySQLdb
Ubuntu安装:https://www.jianshu.com/p/d84cdb5e6273
Python操作MySQL步骤
Connection 对象
用于建立与数据库的连接
创建对象:调用 connect() 方法
conn=connect(参数列表)"""参数host:连接的mysql主机,如果本机是'localhost'参数port:连接的mysql主机的端口,默认是3306参数database:数据库的名称参数user:连接的用户名参数password:连接的密码参数charset:通信采用的编码方式,推荐使用utf8"""import pymysqlcon = pymysql.connect(host = 'localhost',port=3306,database='python-01',user='root',password = 'root',charset = 'utf8')from pymysql import *conn = connect(host = 'localhost',port=3306,database='python-01',user='root',password = 'root',charset = 'utf8')
对象的方法
- close()关闭连接
- commit()提交
- cursor()返回Cursor对象,用于执行sql语句并获得结果
Cursor对象
- 用于执行sql语句,使用频度最高的语句为select、insert、update、delete
- 获取Cursor对象:调用Connection对象的cursor()方法
cs1=conn.cursor()
对象的方法
- close()关闭 先关闭游标,在关闭链接
- execute(operation [, parameters ])执行语句,返回受影响的行数,主要用于执行insert、update、delete语句,也可以执行create、alter、drop等语句
- fetchone()执行查询语句时,获取查询结果集的第一个行数据,返回一个元组
- fetchall()执行查询时,获取结果集的所有行,一行构成一个元组,再将这些元组装入一个元组返回
使用Python连接数据库
from pymysql import *try:conn = connect(host = "localhost",port = 3306,user = "root",passwd = "root",db = 'logic_web',charset = 'utf8')cursor = conn.cursor()cursor.execute('select * from users_banner')result = cursor.fetchone()cursor.close()conn.close()except Exception as e:print("Error %d:%s"%(e.args[0],e.args[1]))
演示
sql代码
-- 创建数据库CREATE DATABASE shopping CHARSET='utf8';-- 切换数据库USE shopping;-- 创建一个商品 goods 数据表CREATE TABLE goods(id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT NOT NULL,NAME VARCHAR(150) NOT NULL,cate_name VARCHAR(40) NOT NULL,brand_name VARCHAR(40) NOT NULL,price DECIMAL(10,3) NOT NULL DEFAULT 0,is_show TINYINT NOT NULL DEFAULT 1,is_saleoff TINYINT NOT NULL DEFAULT 0);-- 插入数据INSERT INTO goods VALUES(0,'r510vc 15.6英寸笔记本','笔记本','华硕','3399',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'y400n 14.0英寸笔记本电脑','笔记本','联想','4999',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'g150th 15.6英寸游戏本','游戏本','雷神','8499',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'x550cc 15.6英寸笔记本','笔记本','华硕','2799',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'x240 超极本','超级本','联想','4880',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'u330p 13.3英寸超极本','超级本','联想','4299',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'svp13226scb 触控超极本','超级本','索尼','7999',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'ipad mini 7.9英寸平板电脑','平板电脑','苹果','1998',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'ipad air 9.7英寸平板电脑','平板电脑','苹果','3388',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'ipad mini 配备 retina 显示屏','平板电脑','苹果','2788',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'ideacentre c340 20英寸一体电脑 ','台式机','联想','3499',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'vostro 3800-r1206 台式电脑','台式机','戴尔','2899',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'imac me086ch/a 21.5英寸一体电脑','台式机','苹果','9188',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'at7-7414lp 台式电脑 linux )','台式机','宏碁','3699',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'z220sff f4f06pa工作站','服务器/工作站','惠普','4288',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'poweredge ii服务器','服务器/工作站','戴尔','5388',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'mac pro专业级台式电脑','服务器/工作站','苹果','28888',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'hmz-t3w 头戴显示设备','笔记本配件','索尼','6999',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'商务双肩背包','笔记本配件','索尼','99',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'x3250 m4机架式服务器','服务器/工作站','ibm','6888',DEFAULT,DEFAULT);INSERT INTO goods VALUES(0,'商务双肩背包','笔记本配件','索尼','99',DEFAULT,DEFAULT);-- 1.创建分类表CREATE TABLE goods_cates(id INT PRIMARY KEY AUTO_INCREMENT NOT NULL,name VARCHAR(40) NOT NULL);-- 2.给分类表添加名称-- 进行分组SELECT cate_name FROM goods GROUP BY cate_name;-- 添加数据-- 此处不是使用values,而是目标表的字段名+查询结果INSERT INTO goods_cates (name) SELECT cate_name FROM goods GROUP BY cate_name;-- 需要将goods表里面的cate_name 换成对应的idUPDATE goods g INNER JOIN goods_cates c ON g.`cate_name`=c.`name` SET g.`cate_name`=c.`id`;
python代码
import pymysql# 1.连接数据库conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='123456', db='shopping', charset='utf8')# 2.获取cursor游标对象cs = conn.cursor()# 3.通过游标对象,执行sql语句r = cs.execute('select * from goods;')print(r)# 4.获取数据# 方法一 fetchone() 获取单条数据print(cs.fetchone()) #获取第一条数据print(cs.fetchone()) #获取第二条数据# 方法二 fetchmany() size=None,默认获取的是一条数据,返回元组print(cs.fetchmany())print(cs.fetchmany(2))# 方法三 fetchall() 获取所有数据print(cs.fetchall())# 关闭# 关闭游标cs.close()# 关闭连接conn.close()

