mysql主键外键_MySQL主键和外键使用及说明

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

一、外键约束

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

外键的使用条件:

1.两个表必须是InnoDB表,MyISAM表暂时不支持外键(据说以后的版本有可能支持,但至少目前不支持);

2.外键列必须建立了索引,MySQL 4.1.2以后的版本在建立外键时会自动创建索引,但如果在较早的版本则需要显示建立;

3.外键关系的两个表的列必须是数据类型相似,也就是可以相互转换类型的列,比如int和tinyint可以,而int和char则不可以;

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

外键的定义语法:

[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个新的数据库

17a6712a0079eaadb8a763ea952620c4.png

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

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已经创建过程

f0f8024e9bf96f17551071e59ff9fa98.png

show create table xiaodi;

----------------------------------------------------------------------+

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

dc16fde37ffb8f0d2a4e893bfb1db35a.png

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

eb7c4a01e52a7ac2f84ecde60faeb662.png

4.尝试删除大哥

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

fcf641c16de11307072f0f8c329b5215.png

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

b22c87c97392e6e28b838d9933cbc6a1.png

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

效果:

e0611e340ee2fbb32667fe4b6c7f4f18.png

查询:

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

查看效果:

8931b980c7ff3ced413cf8a7e3ce98d5.png

3. 通过作者查询书

7021be1ee375e9b8746f56c962bab9a9.png

4.通过书查作者

cf6ee6dae6d20a82d297107ea7f452eb.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/409141.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python学习笔记--迭代器

转载自理解Python的迭代器 首先,廖雪峰老师的教程中解释了迭代器和生成器,这篇文章只是补充和我个人的总结。 什么是迭代 可以直接作用于for循环的对象统称为可迭代对象(Iterable)。 可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterat…

【转载】周鸿祎:做产品体验先把自己切换到二傻子模式

我唯一能自吹的地方,就是本人在互联网里可能犯的错最多,挨的骂最多,然后也经历了很多失败,所以这样才有一些真实的感受。 建议大家把《定位》和《创新者的窘境》、《创新者的解答》这几本书放在身边反复读。你经历得越多&#xff…

mysql临时关闭索引功能_MYSQL中常用的强制性操作(例如强制索引)

mysql常用的hint对于经常使用oracle的朋友可能知道,oracle的hint功能种类很多,对于优化sql语句提供了很多方法。同样,在mysql里,也有类似的hint功能。下面介绍一些常用的。强制索引 FORCE INDEX复制代码代码如下:SELECT * FROM TA…

python学习--windows下安装Numpy包的错误:Unable to find vcvarsall.bat

今天在安装numpy包的时候,无论是通过pip install numpy 还是上网下载numpy包后安装都是出现问题:error: Unable to find vcvarsall.bat,于是百度了下,看到Windows下安装Python包(Numpy)的错误:Unabletofindvcvarsall.b…

使用多行sql字符串时,要注意不要忽略了空格

使用李刚老师编著的《疯狂Java讲义》(第2版)学习MySql数据库与JDBC编程(使用Java 7 ),其中第601页的ConnMySql.java 程序代码在Eclipse上运行,出现错误。 import java.sql.*; public class ConnMySql{publi…

Python学习笔记---理解zip()函数

转载自Python零碎知识(2):强大的zip 一、代码引导 首先看这一段代码: 1 >>> name(jack,beginman,sony,pcky)2 >>> age(2001,2003,2005,2000)3 >>> for a,n in zip(name,age):4 print a,n5 6 输出:7 jack 20018 beginma…

mysql8.0.11 安装顺序_mysql 8.0.11 安装步骤详解

本文为大家分享了mysql 8.0.11 安装步骤,供大家参考,具体内容如下第一步:下载安装包MYSQL官方下载地址:官方下载这里第一项是在线安装,第二项是离线包安装,我选择的是第二项(不用管你电脑是多少位的操作系统…

HDU1258 DFS

题意&#xff1a;求n个数中的某些数的和等于t&#xff0c;并输出 dfs 记录下已经输出过的&#xff0c;然后每次比较一下&#xff0c;这样就能避免重复 View Code 1 #include<stdio.h>2 #include<string.h>3 #include<stdlib.h>4 #include<algorithm>5…

Python 问题--encode、decode及shell中文输出

最近在使用python的时候&#xff0c;涉及到中文输出的时候经常会出现乱码的问题&#xff0c;所以就上网搜索了下&#xff0c;参考了1.Python字符串的encode与decode研究心得乱码问题解决方法&#xff1b; 2.python 中编码的再次学习 此外&#xff0c;更多详细字符编码的可以看…

MYSQL中什么是规范化_如何规范化SQL数据库

小编典典这是在脚本中标准化表的示例。我建议你做这样的事情e.g Table: tbl_tmpDataDate, ProductName, ProductCode, ProductType, MarketDescription, Units, Value2010-01-01, Arnotts Biscuits, 01, Biscuit, Store 1, 20, 20.002010-01-02, Arnotts Biscuits, 01, Biscuit…

python 模块学习--Numpy

Numpy是Python的一个科学计算库&#xff0c;提供了矩阵运算的功能。安装方法可以直接使用pip install numpy命令&#xff0c;也可以在http://sourceforge.net/projects/numpy/files/NumPy/上下载与python相应版本的exe文件。 这里就记录下在学习和使用Numpy中所用过的一些函数…

jsp 的 for循环

jsp 的 for循环jsp中同样可以使用for语句来循环输出内容。for与if一块使用会使得程序流程更加灵活。达到一些我们想要的效果例如&#xff1a;<% page language"java" contentType"text/html;" charsetutf-8"%><html><head><titl…

MySQl求奇数和函数_收集的48个Shell脚本小技巧

0. shell 调试复制代码 代码如下:sh -x somefile.sh在somefile.sh 文件里加上setx set-x1. 用 && || 简化if else复制代码 代码如下:gzip -t a.tar.gzif [[ 0 $? ]]; thenecho "good zip"elseecho "bad zip"fi可以简化为&#xff1a;复制代码 代…

python 问题

在使用python中&#xff0c;特别是使用第三方库的时候&#xff0c;有时候会遇到一些问题&#xff0c;这里就记录下遇到过的问题&#xff0c;以及从网上搜索得到的解决方法。1.使用PIL中&#xff0c;使用字体时&#xff1a;ImportError: The _imagingft C module is not install…