前言

使用数据库一个高效的操作是连表查询,一条查询语句能够查询到多个表的数据。在sqlalchem架构下的数据库连表查询更是十分方便。那么如何连表查询?以及数据库外键对连表查询有没有帮助呢?本篇文章就这两个问题简单解释。

建表

俗话说巧妇难为无米之炊,连表查询肯定要有表,有数据库啊。那有没有数据库是你见了垂涎三尺的呢?中国文化博大精深,饮食文化更是璀璨的明珠。我们就以中国菜系为话题,讲一讲好吃的,顺便再说一说外键和连表查询。

鲁菜  山东菜系,而且在明清两代,宫廷御膳是以鲁菜为主,鲁菜味道浓厚,喜欢葱蒜,以海鲜、汤菜和内脏为主。因为鲁菜对其他菜系的影响颇大,所以鲁菜为八大菜系之首。代表:糖醋鲤鱼

川菜 四川菜系,以成都和重庆两地菜系为主,特点是酸、甜、麻、辣、香,川菜中有五大名菜:回锅肉、水煮肉片、麻婆豆腐、宫保鸡丁、鱼香肉丝。川菜太好吃了,名菜超多。

苏菜 江苏地方风味菜,由扬州、南京、苏州三地的地方菜发展而成,是宫廷第二大菜系,今天国宴仍以苏菜为主。其中扬州菜亦称淮扬菜,因受本地自然资源影响,菜色四季有别,讲究配色以及烹饪技巧。代表作:盐水鸭,松鼠桂鱼

粤菜。就是广东菜系,在国外的中国菜馆是以粤菜为主的。粤菜分为潮汕风味、广府风味以及客家风味,又以广府风味为代表。广东地域物产丰富且新鲜,而且讲究季节性。选材要在食物的最佳的时节,做法追求食材的原汁原味,不像川菜那样破坏了食材原来的鲜味。代表作:白斩鸡

那么就以上面提到的信息来建两张表。

food表:

菜系 地区
鲁菜 山东
川菜 成都
苏菜 南京
粤菜 珠三角

famous表:

 菜系                            代表
 鲁菜 糖醋鲤鱼 
 川菜  鱼香肉丝、宫保鸡丁、水煮肉片
苏菜  松鼠桂鱼、盐水鸭
粤菜   白斩鸡

不带外键的两张表:

model.py

  1. #coding:utf-8
  2.  
  3. from sqlalchemy import create_engine
  4. from sqlalchemy.ext.declarative import declarative_base
  5. from sqlalchemy import Column,Integer,String,DATE,ForeignKey,CHAR #导入外键
  6. from sqlalchemy.orm import relationship #创建关系
  7.  
  8. engine = create_engine("mysql+mysqldb://root:12345678@localhost:3306/test?charset=utf8",
  9. encoding="utf-8")
  10.  
  11. Base = declarative_base() #生成orm基类
  12.  
  13. class Food(Base):
  14. __tablename__ = "food"
  15.  
  16. name = Column(CHAR(20),primary_key = True)
  17. location = Column(CHAR(20))
  18.  
  19. def __repr__(self):
  20. return "name:{0} location:{1}".format(self.name,self.location)
  21.  
  22. class Famous(Base):
  23. __tablename__ = 'famous'
  24. id = Column(Integer,primary_key = True)
  25. food_name = Column(CHAR(20))
  26. famous_dish = Column(CHAR(20))
  27. def __repr__(self):
  28. return "id:{0} food_name:{1} famous_dish:{2}".format(self.id,self.food_name,self.famous_dish)
  29.  
  30. Base.metadata.create_all(engine) #创建表

写入数据

写入数据:

  1. #coding:utf-
  2.  
  3. from sqlalchemy.orm import sessionmaker
  4. from sqlalchemy.ext.declarative import declarative_base
  5. from sqlalchemy import create_engine,Column
  6. from model import Food,Famous

  7. #中文在命令行中显示为16进制编码,所以用拼音代替,懂这个意思就行。
  8. food = {
  9. u"lu":u"shandong",
  10. u"chuan":u"chengdu",
  11. u"su":u"nanjing",
  12. u"yue":u"zhusanjiao"
  13. }
  14.  
  15. famous = [
  16. {u'lu':u'tangculiyu'},
  17. {u'chuan':u'yuxiangrousi'},
  18. {u'chuan':u'gongbaojiding'},
  19. {u'chuan':u'shuizhuroupian'},
  20. {u'su':u'songshuguiyu'},
  21. {u'su':u'yanshuiya'},
  22. {u'yue':u'baizhanji'}
  23. ]
  24.  
  25. engine = create_engine('mysql+mysqldb://root:12345678@localhost:3306/test?charset=utf8')
  26. DBSession = sessionmaker(bind=engine)
  27. session = DBSession()
  28.  
  29. for key in food:
  30. new_food = Food(name=key,location=food[key])
  31. session.add(new_food)
  32. session.commit()
  33.  
  34. for dish in famous:
  35. new_famous = Famous(food_name=dish.keys()[],famous_dish=dish.values()[])
  36. session.add(new_famous)
  37. session.commit()
  38.  
  39. session.close()

这里有一点值得注意一下,famous的外键是food_name字段,指向的是food表中主键name字段。并且这里的对应关系是1对多的。在famous表中的food_name字段重复出现了,但值只有4种。这里就是外键的特性之一:

外键对应主表的主键,外键值可以是空,可以多个对1个,但一定要在主表中主键的值里。

有关外键的具体内容可以参考前面一篇 sqlalchemy外键和relationship查询

查询

select.py

  1. #coding:utf-
  2.  
  3. from sqlalchemy.orm import sessionmaker
  4. from sqlalchemy import create_engine
  5. from model import *
  6.  
  7. #修改用户名、密码和数据库的名称为自己的
  8. engine = create_engine("mysql+mysqldb://root:12345678@localhost:3306/test",)
  9. Session_class = sessionmaker(bind=engine)
  10. session = Session_class()
  11.  
  12. query = session.query(Food).join(Famous).all()
  13.  
  14. for x in query:
  15. print x

在没有外键关联的情况下对查询是有一定的影响的,没有外键关联的情况下,直接join连表,而不指明连表的字段就会报错,因为sqlalchemy连表查询没有外键自动关联两张表。

  1. query = session.query(Food).join(Famous).all()

这个时候就需要在使用join连表时指明两张表连接的字段。

  1. query = session.query(Food,Famous).join(Famous,Famous.food_name==Food.name).all() 

带外键的表

因为不带外键的表查询时没有直接关联,所以下面使用带外键的表来看是否有优化?

  1. #coding:utf-8
  2.  
  3. from sqlalchemy import create_engine
  4. from sqlalchemy.ext.declarative import declarative_base
  5. from sqlalchemy import Column,Integer,String,DATE,ForeignKey,CHAR #导入外键
  6. from sqlalchemy.orm import relationship #创建关系
  7.  
  8. engine = create_engine("mysql+mysqldb://root:12345678@localhost:3306/test?charset=utf8",
  9. encoding="utf-8")
  10.  
  11. Base = declarative_base() #生成orm基类
  12.  
  13. class Food(Base):
  14. __tablename__ = "food"
  15.  
  16. name = Column(CHAR(20),primary_key = True)
  17. location = Column(CHAR(20))
  18.  
  19. def __repr__(self):
  20. return "name:{0} location:{1}".format(self.name,self.location)
  21.  
  22. class Famous(Base):
  23. __tablename__ = 'famous'
  24. id = Column(Integer,primary_key = True)
  25. food_name = Column(CHAR(20),ForeignKey('food.name'))
  26. food = relationship("Food",backref="dish_belong_food")
  27. famous_dish = Column(CHAR(20))
  28. def __repr__(self):
  29. return "id:{0} food_name:{1} famous_dish:{2}".format(self.id,self.food_name,self.famous_dish)
  30.  
  31. Base.metadata.create_all(engine) #创建表

加了外键的famous表,从其建表的sql来看有一条外键记录,连接到food表中的name字段。

有外键关联的表,能够直接join表,sqlalchemy会自动用外键关联这两张表,这就是sqlalchemy对查询做出的优化。

  1. query = session.query(Food,Famous).join(Famous).all()

连表查询

数据库连表有很多中操作,有全连接,左连接,右连接。在这些连接方式中,最基础的是全连接,看一下全连接的威力。

  1. query = session.query(Food,Famous).all()

直接查询两张表,这时查询结果是返回被连接的两个表的笛卡尔积。将两张表看做是两个列表,全连接的方式类似如下的列表乘积。

                                    

在前面使用的join连接则是一种内连接。将两张表里相同的部分连接在一起,内连接的方式如下:

  1. query = session.query(Food,Famous).join(Famous,Famous.food_name==Food.name).all()

                      

使用join的方式可以将多张表连在一起,不仅限于2张表,如果这里有还有一张介绍每一种美食的做法的一张表叫做Cook的话,将三种表连起来的写法:

  1. query = session.query(Food,Famous,Cook).join(Famous,Famous.food_name==Food.name).join(Cook,Cook.famous_name==Famous.famous).all()

只要表与表之间有关联,那么就能用join的方式将表连接在一起,前提是一定要有字段是有关联的,如果连接两张毫无干系的表,那查询结果肯定是空。

在实际的使用过程中,将想要查询的表关联起来是第一步,还有一步也很重要,那就是过滤,筛选出我们需要的字段。而筛选在sqlalchemy中使用的是filter这个关键字。例如,想要筛选出所有苏菜里的好吃的,可以这么写:

  1. query = session.query(Food,Famous).join(Famous,Famous.food_name==Food.name).filter(Food.name=='su').all()

filter的作用就是从得到连表所有的数据里过滤出我们感兴趣的数据。filte之前,我们得到的数据是这样的:

而使用了filter之后,从上面的结果中将food表中name字段为'su'的数据过滤出来,便是如下的数据:

同时还可以多级过滤,可以在前面的基础上再次过滤。比如说,我就爱吃鸭子,我在南京的美食找一找有没有和鸭子有关的好吃的,写法如下:

  1. query = session.query(Food,Famous).join(Famous,Famous.food_name==Food.name).filter(Food.name=='su').filter(Famous.famous_dish.like('%ya%')).all()

结果如下,真的找到一条记录,盐水鸭,这是南京人民的最爱啊,能把鸭子吃出花来,就像有人调侃说没有一只鸭子能走出南京!('-')

总结

所以总结一下在sqlalchemy中如何得心应手,随心所欲的过滤出自己想要的数据:

1.找到你想要查询的数据的表

2.看看你手里有什么数据

3.确定手里的数据和你要查询的数据之间有直接关系还是有间接关系

4.将有关联的表连接起来(join ,连接相关的表)

5.从得到的数据中过滤出里感兴趣的数据(filter 过滤出你需要的数据)

通用公式

query 负责你要查询的结果的字段信息

join 负责你的连表操作,可以有多个join

filetr 负责过滤你感兴趣的数据,或者符合条件的数据才能被query展示

看到这里可能有好奇宝宝会问,不是还有一个all吗?这是什么意思呢?这个就是sqlalchemy的关键字了,具体参考前面的sqlalchemy关键字使用篇

吃货眼中的sqlalchemy外键和连表查询的更多相关文章

  1. MySQL数据库(4)_MySQL数据库外键约束、表查询

    一.外键约束 创建外键 --- 每一个班主任会对应多个学生 , 而每个学生只能对应一个班主任 ----主表 CREATE TABLE ClassCharger( id TINYINT PRIMARY ...

  2. 数据库 SQL 外键约束 多表查询

    多表设计与多表查询 1.外键约束        表是用来保存现实生活中的数据的,而现实生活中数据和数据之间往往具有一定的关系,我们在使用表来存储数据时,可以明确的声明表和表之前的依赖关系,命令数据库来 ...

  3. sqlalchemy外键和relationship查询

    前面的文章中讲解了外键的基础知识和操作,上一篇文章讲解了sqlalchemy的基本操作.前面两篇文章都是作为铺垫,为下面的文章打好基础.记得初一时第一次期中考试时考的不好,老爸安慰我说:“学习是一个循 ...

  4. SQLAlchemy(三):外键、连表关系

    SQLAlchemy03 /外键.连表关系 目录 SQLAlchemy03 /外键.连表关系 1.外键 2.ORM关系以及一对多 3.一对一的关系 4.多对多的关系 5.ORM层面的删除数据 6.OR ...

  5. SQLAlchemy03 /外键、连表关系

    SQLAlchemy03 /外键.连表关系 目录 SQLAlchemy03 /外键.连表关系 1.外键 2.ORM关系以及一对多 3.一对一的关系 4.多对多的关系 5.ORM层面的删除数据 6.OR ...

  6. MySQL的外键,修改表,基本数据类型,表级别操作,其他(条件,通配符,分页,排序,分组,联合,连表操作)

    MySQL的外键,修改表,基本数据类型,表级别操作,其他(条件,通配符,分页,排序,分组,联合,连表操作): a.创建2张表 create table userinfo(nid int not nul ...

  7. django模型中有外键关系的表删除相关设置

    0904自我总结 django模型中有外键关系的表删除相关设置 一.一对一 例如有Author.AuthorDetail两表 author = models.OneToOneField(to='Aut ...

  8. MySQL数据库 外键,级联, 修改表的操作

    1.外键: 用来建立两张表之间的关系 - 一对多 - 多对多 - 一对一 研究表与表之间的关系: 1.定义一张 员工部门表 id, name, gender, dep_name, dep_desc - ...

  9. sqlalchemy外键的一些东西

    sqlalchemy中让MySQL支持中文字符 engine = create_engine("mysql+pymysql://root:mysql8@localhost/mysqltest ...

随机推荐

  1. myeclipse中更改默认jdk版本出错( Target is not a JDK root. System library was not found)

    原因是我的本地jdk版本是9.0,将jdk版本更改至8.0即可导入成功. jdk9.0导入myeclipse中去会有此类问题的发生,因此没有必要使用最新的jdk版本.

  2. Android利用Handler异步获取子线程中的产生的值

        本文首发于cartoon的博客     转载请注明出处:https://cartoonyu.github.io/cartoon-blog     近段时间有一个需求:在线获取图片并且显示在界面 ...

  3. 计算机原理以及PythonIDE配置和使用

    计算机基础 在巩固了昨日学习知识的基础上,增加了新的内容 整个关于计算机基础的学习可以浓缩为五个问题 什么是编程? 人与计算机之间的交互操作,使人可以奴役计算机从而让其代替人类工作的行为 操作系统有什 ...

  4. react开发中的小细节

    目前开始使用react余遇到的问题还不是很多,但还是希望总结一下. react中的属性prop: 在react中组件的父子组件的通信是基于prop的,当然对于底层的东西不是特别了解,但可以说一说它的基 ...

  5. abp(net core)+easyui+efcore实现仓储管理系统——使用 WEBAPI实现CURD (十二)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...

  6. git和githup

    一:Git简介 1.1:VCS的历史 Git是一款代码管理工具(Version Control System),傲视群雄,是目前世界上最先进的免费开源的分布式版本控制系统,没有之一! VCS版本控制系 ...

  7. 【JDK】JDK源码分析-ReentrantLock

    概述 在 JDK 1.5 以前,锁的实现只能用 synchronized 关键字:1.5 开始提供了 ReentrantLock,它是 API 层面的锁.先看下 ReentrantLock 的类签名以 ...

  8. Codeforces 468C Hack it!

    https://www.luogu.org/problemnew/show/CF468C http://codeforces.com/contest/468/problem/C #include &l ...

  9. oracle 正确删除归档日志,并清除 V$ARCHIVED_LOG 数据

    1. 连接 RMAN 管理 rman target / 2. 查看归档日志列表 RMAN> crosscheck archivelog all; 3. 删除所有归档日志 RMAN> DEL ...

  10. linux环境下搭建自动化Jenkins管理工具

    一.搭建一个jak--tomcat服务器到自己的linux服务器上 具体的服务器搭建这里可以参考华华大佬的博客:https://www.cnblogs.com/liulinghua90/p/46614 ...