摘自网上一个经典的例子:大哥和小弟python
1、外键约束mysql
MySQL经过外键约束来保证表与表之间的数据的完整性和准确性。web
外键的使用条件:
1.两个表必须是InnoDB表,MyISAM表暂时不支持外键(听说之后的版本有可能支持,但至少目前不支持);
2.外键列必须创建了索引,MySQL 4.1.2之后的版本在创建外键时会自动建立索引,但若是在较早的版本则须要显示创建;
3.外键关系的两个表的列必须是数据类型类似,也就是能够相互转换类型的列,好比int和tinyint能够,而int和char则不能够;sql
外键的好处:可使得两张表关联,保证数据的一致性和实现一些级联操做;数据库
外键的定义语法:session
[constraint symbol] foreign key [id] (index_col_name, ...) references tbl_name (index_col_name, ...) [on delete {restrict | cascade | set null | on action | set default}] [on update {restrict | cascade | set null | on action | set default}] 该语法能够在 create table 和 alter table 时使用,若是不指定constraint symbol,MYSQL会自动生成一个名字。 on delete,on update表示事件触发限制,可设参数: restrict(限制外表中的外键改动) cascade(跟随外键改动) set null(设空值) set default(设默认值) no action(无动做,默认的)
1. 先创建1个新的数据库spa
2.在pycharm中新建2张table(Dage,Xiaodi)3d
import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String,ForeignKey
engine=create_engine("mysql+pymysql://root:1234@localhost/chen")
Base=declarative_base()
class Dage(Base):
__tablename__='Dage'
id=Column(Integer,primary_key=True)
name=Column(String(32))
class Xiaodi(Base):
__tablename__='Xiaodi'
id=Column(Integer,primary_key=True)
name=Column(String(32))
Dage_id = Column(Integer,ForeignKey('Dage.id'))
Base.metadata.create_all(engine)
在客户端show table已经建立过程rest
show create table xiaodi;code
----------------------------------------------------------------------+
| xiaodi | CREATE TABLE `xiaodi` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
`Dage_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `Dage_id` (`Dage_id`),
CONSTRAINT `xiaodi_ibfk_1` FOREIGN KEY (`Dage_id`) REFERENCES `dage` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
show create table dage;
3.在2张表中各插入1条数据。因为不知名的错误,须要把2个表中的数据分开建立。
import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String,ForeignKey from sqlalchemy.orm import sessionmaker engine=create_engine("mysql+pymysql://root:1234@localhost/chen") Base=declarative_base() class Dage(Base): __tablename__='Dage' id=Column(Integer,primary_key=True) name=Column(String(32)) class Xiaodi(Base): __tablename__='Xiaodi' id=Column(Integer,primary_key=True) name=Column(String(32)) Dage_id = Column(Integer,ForeignKey('Dage.id')) Base.metadata.create_all(engine) Session_class=sessionmaker(bind=engine) session=Session_class() #dage1=Dage(name='I_am_dage') xiaodi1=Xiaodi(Dage_id=1,name='I_am_xiaodi') session.add_all([xiaodi1]) session.commit()
查看效果:发现这种建立方式有个问题,id会自增,2张表的ID依次为1,2
4.尝试删除大哥
删除不了,由于有外键约束
插入1个小弟,由于没有大哥,因此插入不成功
5.把外键约束增长事件触发限制:
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表和一个地址表
表结构:
from sqlalchemy import Integer, ForeignKey, String, Column from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship from sqlalchemy import create_engine Base = declarative_base() class Customer(Base): __tablename__ = 'customer' id = Column(Integer, primary_key=True) name = Column(String(64)) # 帐单地址和邮寄地址 都关联同一个地址表 billing_address_id = Column(Integer, ForeignKey("address.id")) shipping_address_id = Column(Integer, ForeignKey("address.id")) billing_address = relationship("Address", foreign_keys=[billing_address_id]) shipping_address = relationship("Address", foreign_keys=[shipping_address_id]) class Address(Base): __tablename__ = 'address' id = Column(Integer, primary_key=True) city = Column(String(64)) def __repr__(self): return self.street engine = create_engine("mysql+pymysql://root:1234@localhost/chen", encoding='utf-8') Base.metadata.create_all(engine) # 建立表结构
生成表内容:
from Day12 import ex5 from sqlalchemy.orm import sessionmaker Session_class = sessionmaker(bind=ex5.engine) # 建立与数据库的会话session class ,注意,这里返回给session的是个class,不是实例 session = Session_class() # 生成session实例 #cursor addr1 = ex5.Address(city="BJ") addr2 = ex5.Address(city="Shanghai") addr3 = ex5.Address(city="Tianjin") session.add_all([addr1, addr2, addr3]) c1 = ex5.Customer(name="Alex", billing_address=addr1, shipping_address=addr2) c2 = ex5.Customer(name="Jack", billing_address=addr3, shipping_address=addr3) session.add_all([c1, c2]) session.commit()
效果:
查询:
obj=session.query(ex5.Customer).filter(ex5.Customer.name=='Alex').first() print(obj.name,obj.billing_address,obj.shipping_address)
返回结果:
C:\abccdxddd\Oldboy\python-3.5.2-embed-amd64\python.exe C:/abccdxddd/Oldboy/Py_Exercise/Day12/ex4.py
Alex BJ Shanghai
Process finished with exit code 0
三,多对多
1.建立表结构
import sqlalchemy from sqlalchemy import Table, Column, Integer,String,DATE, ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker Base=declarative_base() book_m2m_author=Table('book_m2m_author',Base.metadata, Column('book_id',Integer,ForeignKey('books.id')), Column('author_id',Integer,ForeignKey('authors.id')), ) class Book(Base): __tablename__='books' id=Column(Integer,primary_key=True) name=Column(String(64)) authors=relationship('Author',secondary=book_m2m_author,backref='books') def __repr__(self): return self.name class Author(Base): __tablename__='authors' id=Column(Integer,primary_key=True) name=Column(String(32)) def __repr__(self): return self.name engine=create_engine('mysql+pymysql://root:1234@localhost/chen') Base.metadata.create_all(engine)
2. 增长表内容
# 添加数据 from Day12 import ex4 from sqlalchemy.orm import sessionmaker Session_class = sessionmaker(bind=ex4.engine) # 建立与数据库的会话session class ,注意,这里返回给session的是个class,不是实例 session = Session_class() # 生成session实例 #cursor # 建立书 b1 = ex4.Book(name="learn python with Alex") b2 = ex4.Book(name="learn Zhangbility with Alex") b3 = ex4.Book(name="Learn hook up girls with Alex") # 建立做者 a1 = ex4.Author(name="Alex") a2 = ex4.Author(name="Jack") a3 = ex4.Author(name="Rain") # 关联关系 b1.authors = [a1, a3] b3.authors = [a1, a2, a3] session.add_all([b1, b2, b3, a1, a2, a3]) session.commit()
查看效果:
3. 经过做者查询书
4.经过书查做者