摘自网上一个经典的例子:大哥和小弟

一、外键约束

MySQL通过外键约束来保证表与表之间的数据的完整性和准确性。

外键的使用条件:
    1.两个表必须是InnoDB表,MyISAM表暂时不支持外键(据说以后的版本有可能支持,但至少目前不支持);
   2.外键列必须建立了索引,MySQL 4.1.2以后的版本在建立外键时会自动创建索引,但如果在较早的版本则需要显示建立; 
   3.外键关系的两个表的列必须是数据类型相似,也就是可以相互转换类型的列,比如int和tinyint可以,而int和char则不可以;

外键的好处:可以使得两张表关联,保证数据的一致性和实现一些级联操作;

外键的定义语法:

  1. [constraint symbol] foreign key [id] (index_col_name, ...)
  2. references tbl_name (index_col_name, ...)
  3. [on delete {restrict | cascade | set null | on action | set default}]
  4. [on update {restrict | cascade | set null | on action | set default}]
  5.  
  6. 该语法可以在 create table alter table 时使用,如果不指定constraint symbolMYSQL会自动生成一个名字。
  7. on delete,on update表示事件触发限制,可设参数:
  8. restrict(限制外表中的外键改动)
  9. cascade(跟随外键改动)
  10. set null(设空值)
  11. set default(设默认值)
  12. no action(无动作,默认的)

1. 先建立1个新的数据库

2.在pycharm中新建2张table(Dage,Xiaodi)

  1. import sqlalchemy
  2. from sqlalchemy import create_engine
  3. from sqlalchemy.ext.declarative import declarative_base
  4. from sqlalchemy import Column, Integer, String,ForeignKey
  5.  
  6. engine=create_engine("mysql+pymysql://root:1234@localhost/chen")
  7. Base=declarative_base()
  8. class Dage(Base):
  9. __tablename__='Dage'
  10. id=Column(Integer,primary_key=True)
  11. name=Column(String(32))
  12. class Xiaodi(Base):
  13. __tablename__='Xiaodi'
  14. id=Column(Integer,primary_key=True)
  15. name=Column(String(32))
  16. Dage_id = Column(Integer,ForeignKey('Dage.id'))
  17. Base.metadata.create_all(engine)

在客户端show table已经创建过程

show create table xiaodi;

  1. ----------------------------------------------------------------------+
  2. | xiaodi | CREATE TABLE `xiaodi` (
  3. `id` int(11) NOT NULL AUTO_INCREMENT,
  4. `name` varchar(32) DEFAULT NULL,
  5. `Dage_id` int(11) DEFAULT NULL,
  6. PRIMARY KEY (`id`),
  7. KEY `Dage_id` (`Dage_id`),
  8. CONSTRAINT `xiaodi_ibfk_1` FOREIGN KEY (`Dage_id`) REFERENCES `dage` (`id`)
  9. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

show create table dage;

3.在2张表中各插入1条数据。由于不知名的错误,需要把2个表中的数据分开创建。

  1. import sqlalchemy
  2. from sqlalchemy import create_engine
  3. from sqlalchemy.ext.declarative import declarative_base
  4. from sqlalchemy import Column, Integer, String,ForeignKey
  5. from sqlalchemy.orm import sessionmaker
  6.  
  7. engine=create_engine("mysql+pymysql://root:1234@localhost/chen")
  8. Base=declarative_base()
  9. class Dage(Base):
  10. __tablename__='Dage'
  11. id=Column(Integer,primary_key=True)
  12. name=Column(String(32))
  13. class Xiaodi(Base):
  14. __tablename__='Xiaodi'
  15. id=Column(Integer,primary_key=True)
  16. name=Column(String(32))
  17. Dage_id = Column(Integer,ForeignKey('Dage.id'))
  18. Base.metadata.create_all(engine)
  19.  
  20. Session_class=sessionmaker(bind=engine)
  21. session=Session_class()
  22. #dage1=Dage(name='I_am_dage')
  23. xiaodi1=Xiaodi(Dage_id=1,name='I_am_xiaodi')
  24. session.add_all([xiaodi1])
  25. session.commit()

查看效果:发现这种创建方式有个问题,id会自增,2张表的ID依次为1,2

4.尝试删除大哥

删除不了,因为有外键约束

插入1个小弟,因为没有大哥,所以插入不成功

5.把外键约束增加事件触发限制:

  1. alter table xiaodi drop foreign key xiaodi_ibfk_1;
    alter table xiaodi add foreign key(Dage_id) references dage(id) on delete cascade on update cascade; #意思是从表会跟随主表的改变而改变。

理论上,现在就能正常删除了。

二,多外键关联

建立一个customer表和一个地址表

表结构:

  1. from sqlalchemy import Integer, ForeignKey, String, Column
  2. from sqlalchemy.ext.declarative import declarative_base
  3. from sqlalchemy.orm import relationship
  4. from sqlalchemy import create_engine
  5.  
  6. Base = declarative_base()
  7.  
  8. class Customer(Base):
  9. __tablename__ = 'customer'
  10. id = Column(Integer, primary_key=True)
  11. name = Column(String(64))
  12. # 账单地址和邮寄地址 都关联同一个地址表
  13. billing_address_id = Column(Integer, ForeignKey("address.id"))
  14. shipping_address_id = Column(Integer, ForeignKey("address.id"))
  15.  
  16. billing_address = relationship("Address", foreign_keys=[billing_address_id])
  17. shipping_address = relationship("Address", foreign_keys=[shipping_address_id])
  18.  
  19. class Address(Base):
  20. __tablename__ = 'address'
  21. id = Column(Integer, primary_key=True)
  22. city = Column(String(64))
  23. def __repr__(self):
  24. return self.street
  25.  
  26. engine = create_engine("mysql+pymysql://root:1234@localhost/chen",
  27. encoding='utf-8')
  28. Base.metadata.create_all(engine) # 创建表结构

生成表内容:

  1. from Day12 import ex5
  2.  
  3. from sqlalchemy.orm import sessionmaker
  4.  
  5. Session_class = sessionmaker(bind=ex5.engine) # 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
  6.  
  7. session = Session_class() # 生成session实例 #cursor
  8.  
  9. addr1 = ex5.Address(city="BJ")
  10.  
  11. addr2 = ex5.Address(city="Shanghai")
  12.  
  13. addr3 = ex5.Address(city="Tianjin")
  14.  
  15. session.add_all([addr1, addr2, addr3])
  16.  
  17. c1 = ex5.Customer(name="Alex", billing_address=addr1, shipping_address=addr2)
  18.  
  19. c2 = ex5.Customer(name="Jack", billing_address=addr3, shipping_address=addr3)
  20.  
  21. session.add_all([c1, c2])
  22.  
  23. session.commit()

效果:

查询:

  1. obj=session.query(ex5.Customer).filter(ex5.Customer.name=='Alex').first()
  2. print(obj.name,obj.billing_address,obj.shipping_address)

返回结果:

  1. C:\abccdxddd\Oldboy\python-3.5.2-embed-amd64\python.exe C:/abccdxddd/Oldboy/Py_Exercise/Day12/ex4.py
  2. Alex BJ Shanghai
  3.  
  4. Process finished with exit code 0

三,多对多

1.创建表结构

  1. import sqlalchemy
  2. from sqlalchemy import Table, Column, Integer,String,DATE, ForeignKey
  3. from sqlalchemy.orm import relationship
  4. from sqlalchemy.ext.declarative import declarative_base
  5. from sqlalchemy import create_engine
  6. from sqlalchemy.orm import sessionmaker
  7.  
  8. Base=declarative_base()
  9. book_m2m_author=Table('book_m2m_author',Base.metadata,
  10. Column('book_id',Integer,ForeignKey('books.id')),
  11. Column('author_id',Integer,ForeignKey('authors.id')),
  12. )
  13.  
  14. class Book(Base):
  15. __tablename__='books'
  16. id=Column(Integer,primary_key=True)
  17. name=Column(String(64))
  18. authors=relationship('Author',secondary=book_m2m_author,backref='books')
  19. def __repr__(self):
  20. return self.name
  21.  
  22. class Author(Base):
  23. __tablename__='authors'
  24. id=Column(Integer,primary_key=True)
  25. name=Column(String(32))
  26. def __repr__(self):
  27. return self.name
  28. engine=create_engine('mysql+pymysql://root:1234@localhost/chen')
  29. Base.metadata.create_all(engine)

2. 增加表内容

  1. # 添加数据
  2.  
  3. from Day12 import ex4
  4. from sqlalchemy.orm import sessionmaker
  5. Session_class = sessionmaker(bind=ex4.engine) # 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
  6.  
  7. session = Session_class() # 生成session实例 #cursor
  8.  
  9. # 创建书
  10.  
  11. b1 = ex4.Book(name="learn python with Alex")
  12. b2 = ex4.Book(name="learn Zhangbility with Alex")
  13. b3 = ex4.Book(name="Learn hook up girls with Alex")
  14.  
  15. # 创建作者
  16.  
  17. a1 = ex4.Author(name="Alex")
  18. a2 = ex4.Author(name="Jack")
  19. a3 = ex4.Author(name="Rain")
  20.  
  21. # 关联关系
  22.  
  23. b1.authors = [a1, a3]
  24. b3.authors = [a1, a2, a3]
  25.  
  26. session.add_all([b1, b2, b3, a1, a2, a3])
  27. session.commit()

查看效果:

3. 通过作者查询书

4.通过书查作者

MySQL主键和外键使用及说明的更多相关文章

  1. MySQL的几个概念:主键,外键,索引,唯一索引

    概念: 主键(primary key) 能够唯一标识表中某一行的属性或属性组.一个表只能有一个主键,但可以有多个候选索引.主键常常与外键构成参照完整性约束,防止出现数据不一致.主键可以保证记录的唯一和 ...

  2. mysql主键,外键,索引

    主键 唯一而非空,只能有一个 作用: 1.唯一的标识一行  2.作为一个可以被外键有效引用的对象  3.保证数据完整性 设计原则: 1. 主键应当是对用户没有意义的.如果用户看到了一个表示多对多关系的 ...

  3. MySQL—概念,用户的创建,主键,外键,数据类型,表格创建

    MySQL DBMS,MySQL的概念,数据库分类,以前MySQL的部署中的一些概念 #DBMS:数据库管理系统,用于管理数据库的大型软件.mysql就是dbms的一种 #Mysql:是用于管理文件的 ...

  4. MySQL中的主键,外键有什么作用详解

    MySQL中的主键,外键有什么作用详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 学关系型数据库的同学,尤其在学习主键和外键时会产生一定的困惑.那么今天我们就把这个困惑连根拔起 ...

  5. 两种获取MySql数据库中所有表的主键和外键约束信息的Sql语句

    最近在写Rafy底层的一些东西,在数据库方面把MySql数据库集成到里面去,里面有一个需求,需要获取非系统数据库,也就是我们自己建立的数据库中所有表的主键和外键元数据列表. 第一种方法:是网上的方法, ...

  6. MySql必知必会实战练习(四)主键、外键、sql约束、联结表

    本博将对主键.外键.MySql数据库约束和联结表的相关特性进行总结和实战 1. 主键 表中的每一行都应该具有可以唯一标识自己的一列(或一组列),而这个承担标识作用的列称为主键 如果没有主键,数据的管理 ...

  7. mysql的引擎问题,主键和外键的创建问题,以及创建外键不成功,却创建了一个索引

    mysql的引擎问题: 需要知道的三个引擎:InnoDB--是一个事务处理引擎,不支持全文检索,支持事务操作,即DML操作: Memory--是一个数据存储在内存,速度很快,功能上等同于MyIsam, ...

  8. day03 MySQL数据库之主键与外键

    day03 MySQL数据库之主键与外键 昨日内容回顾 针对库的基本SQL语句 # 增 create database meng; # 查 show databases; shwo create da ...

  9. MySQL中的完整性约束条件(主键、外键、唯一、非空)

    数据库的完整性约束用来防止对数据的意外破坏,来保证数据的安全性和一致性. 主键 1.创建表时候指定主键 创建表user(id, username, age),并且id字段非空自增. CREATE TA ...

  10. MySQL主键跟外键

    定义主键和外键主要是为了维护关系数据库的完整性,总结一下: 1.主键是能确定一条记录的唯一标识,比如,一条记录包括身份正号,姓名,年龄. 身份证号是唯一能确定你这个人的,其他都可能有重复,所以,身份证 ...

随机推荐

  1. Yii2 Gridview 动态显示行或列和action列

    我们知道Yii中的GridView组件是非常好用的. 某些情况要动态显示某列,这时候就要用到visible属性 'propString' => ['attribute' => 'prope ...

  2. 解决 idea template jsp模板中使用自定义路径 模板不显示问题

    ${} 是一个模板中的关键字,所以建立时需要用 \ 注释即可正常显示  ${APP_PATH}

  3. 使用闭包的方式实现一个累加函数 addNum

    使用闭包的方式实现一个累加函数 addNum,参数为 number 类型,每次返回的结果 = 上一次计算的值 + 传入的值,如: addNum(10); //10 addNum(12); //22 a ...

  4. ubuntu18.04安装mongoDB 4.0

    STEP 1:  在终端输入GPK码 $  sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334B ...

  5. JDBC处理大数据

    1.处理大文本 package com.demo; import java.io.File; import java.io.FileNotFoundException; import java.io. ...

  6. static和构造函数初始化顺序

    abstract class demo{ public demo() {} protected void a() { System.out.println("I am parents!&qu ...

  7. dubbo SpringContainer

    dubbo SpringContainer Spring启动类容器 SPI service provider interfaces 服务提供借口 Singleton 单例 ThreadSafe 线程安 ...

  8. 5个最优秀的微信小程序UI组件库

    开发微信小程序的过程中,选择一款好用的组件库,可以达到事半功倍的效果.自从微信小程序面世以来,不断有一些开源组件库出来,下面5款就是排名比较靠前,用户使用量与关注度比较高的小程序UI组件库.还没用到它 ...

  9. 曾经我是一个只会excel的数据分析师,直到我遇到了……

    我是一个数据分析师. 准确来说我是一个当年只会excel数据透视表,就天不怕地不怕地来当数据分析师的人.当年的某一天,我的老板Q我: 小刘啊,我小姨子给了我一个全国市委书记的名单,你帮我看看,有什么规 ...

  10. HDU 5672 String

    题目链接: hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5672 bc(中文):http://bestcoder.hdu.edu.cn/contests ...