首页 > 数据库 >新建数据库顺序思路

新建数据库顺序思路

时间:2024-03-07 18:13:01浏览次数:37  
标签:Book 顺序 objects 新建 数据库 publish book app01 id

 

 

表之间存在三种关系:多对一、一对一、多对多,那如何确定两张表之间的关系呢?按照下述步骤操作即可

左表<------------------------------->右表

# 步骤一:先分析
#分析1、先站在左表的角度
是否左表的多条记录可以对应右表的一条记录

#分析2、再站在右表的角度去找
是否右表的多条记录可以对应左表的一条记录

# 步骤二:后确定关系
# 多对一
如果只有"分析1"成立,那么可以确定两张表的关系是:左表多对一右表,关联字段应该创建在左表中,然后foreign key 右表一个字段(通常是id)
如果只有"分析2"成立,那么可以确定两张表的关系是:右表多对一左表,关联字段应该创建在右表中,然后foreign key 左表一个字段(通常是id)

# 一对一
如果"分析1"和"分析2"都不成立,而是左表的一条记录唯一对应右表的一条记录,反之亦然。这种情况很简单,就是在左表foreign key右表的基础上,将左表的关联字段设置成unique即可

# 多对多
如果"分析1"和"分析2"同时成立,则证明这两张表是一个双向的多对一,即多对多,需要创建一张单独的新表来专门存放二者的关系,关联字段应该创建在新表中,然后在新表中分别foreign key两张表的id字段

 

 

 

我们以一个图书管理系统为背景,设计了下述四张表,让我们来找一找它们之间的关系

书籍表:app01_book

出版社表:app01_publish

作者表:app01_author

作者详细信息表:app01_authordetail

例1、app01_book与app01_publish

找关系

左表(app01_book)<------------------------------->右表(app01_publish)

# 步骤一:
#分析1、先站在左表的角度
左表的多条记录代表多版本书籍,右表的一条记录代表一个出版社,多本书籍对应同一个出版社 ✔️

#分析2、再站在右表的角度去找
右表的多条记录代表多个出版社,左表的一条记录代表一本书,多个出版社不能出版同一本书 ✘

# 步骤二:后确定关系
# 多对一
只有"分析1"成立,那么可以确定两张表的关系是:左表(app01_book)多对一右表(app01_publish),
关联字段应该创建在左表(app01_book)中,然后foreign key 右表(app01_publish)的id字段

 

 

sql语句

# 1、由于foreign key的影响,必须先创建被关联表
CREATE TABLE app01_publish (
    id INT PRIMARY KEY auto_increment,
    name VARCHAR (20)
);

# 2、才能创建出关联表
CREATE TABLE app01_book (
    id INT PRIMARY KEY auto_increment,
    title VARCHAR (20),
    price DECIMAL (8, 2),
    pub_date DATE,
    publish_id INT, # 新增关联字段
    FOREIGN KEY (publish_id) REFERENCES app01_publish (id) 
    ON UPDATE CASCADE ON DELETE CASCADE
);

 

 

例2、app01_author与app01_authordetail
找关系

左表(app01_author)<------------------------------->右表(app01_authordetail)

一个作者唯一对应一条自己的详情信息,反之亦然,所以两张表是一对一的关系。在左表中新增关联字段并添加unique约束,然后foreign key右表
sql语句

# 1、由于foreign key的影响,必须先创建被关联表
CREATE TABLE app01_authordetail (
    id INT PRIMARY KEY auto_increment,
    tel VARCHAR (20)
);

# 2、才能创建出关联表
CREATE TABLE app01_author (
    id INT PRIMARY KEY auto_increment,
    name VARCHAR (20),
    age INT,
    authordetail_id INT UNIQUE, # 新增关联字段,并添加唯一性约束unique
    FOREIGN KEY (authordetail_id) REFERENCES app01_authordetail (id) 
    ON UPDATE CASCADE ON DELETE CASCADE
);

 

 

例3、app01_book与app01_author
找关系

左表(app01_book)<------------------------------->右表(app01_author)

# 步骤一:
#分析1、先站在左表的角度
左表的多条记录代表多版本书籍,右表的一条记录代表一个作者,多本书籍可以由同一个作者编写 ✔️

#分析2、再站在右表的角度去找
右表的多条记录代表多个作者,左表的一条记录代表一本书,多个作者可以合作编写同一本书 ✔️

# 步骤二:后确定关系
# 多对多
"分析1"和"分析2"同时成立,证明这两张表是多对多的关系,需要创建一张单独的新表来专门存放二者的关系,关联字段应该创建在新表中,然后在新表中分别foreign key两张表的id字段
sql语句

# 1、创建被关联表一:app01_book,例1中已创建
# 2、创建被关联表二:app01_author,例2中已创建

# 3、创建新表,存放app01_book于app01_author的关联关系
CREATE TABLE app01_book_authors (
    id INT PRIMARY KEY auto_increment,
    book_id INT, # 新增关联字段,用来关联表app01_book
    author_id INT, # 新增关联字段,用来关联表app01_author
    FOREIGN KEY (book_id) REFERENCES app01_book (id) ON UPDATE CASCADE ON DELETE CASCADE,
    FOREIGN KEY (author_id) REFERENCES app01_author (id) ON UPDATE CASCADE ON DELETE CASCADE
);

 

 

 

创建模型
模型类如下

from django.db import models

# 表app01_publish
class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=20)


# 表app01_book
class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=20)
    price = models.DecimalField(max_digits=8, decimal_places=2)
    pub_date = models.DateField()

    # 表app01_book多对一表app01_publish,参数to指定模型名,参数to_field指定要关联的那个字段
    publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)

    # 我们自己写sql时,针对书籍表与作者表的多对关系,需要自己创建新表,而基于django的orm,下面这一行代码可以帮我们自动创建那张关系表
    authors=models.ManyToManyField(to='Author') 
    # 变量名为authors,则新表名为app01_book_authors,若变量名为xxx,则新表名为app01_book_xxx


# 表app01_author
class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=20)
    age = models.IntegerField()

    # 表app01_author一对一表app01_authordetail
    author_detail = models.OneToOneField(to='AuthorDetail',to_field='nid',unique=True,on_delete=models.CASCADE)


# 表app01_authordetail
class AuthorDetail(models.Model):
    nid = models.AutoField(primary_key=True)
    tel = models.CharField(max_length=20)

 

 

按照上图所示,由于foreign key的关系,我们需要事先往app01_publish与app01_authordetail里插入记录

# 1、需求:通过模型Publish往表app01_publish里插入三家出版社
Publish.objects.create(name='北京出版社')
Publish.objects.create(name='长春出版社')
Publish.objects.create(name='大连出版社')

# 2、需求:通过模型AuthorDetail往表app01_authordetail里插入三条作者详情
AuthorDetail.objects.create(tel='18611312331')
AuthorDetail.objects.create(tel='15033413881')
AuthorDetail.objects.create(tel='13011453220')
按照上图所示,插入时会涉及到多张表,我们同样分三种情况来介绍

1、多对一:app01_book与app01_publish

# 需求:书籍(葵花宝典、菊花宝典、桃花宝典)都是在北京出版社出版的
# 1、先通过模型Publish从出版社表app01_publish查出北京出版社
publish_obj=Publish.objects.filter(name='北京出版社').first()
# 上述代码也可以简写为:publish_obj=Publish.objects.get(name='北京出版社')

# 2、再通过模型Book往书籍表app01_book里插入三本书籍与出版社的对应关系
# 方式一:使用publish参数指定关联
book_obj1=Book.objects.create(title='葵花宝典',price=2000,pub_date='1985-3-11',publish=publish_obj)

book_obj2=Book.objects.create(title='菊花宝典',price=3000,pub_date='1990-1-21',publish=publish_obj)

book_obj3=Book.objects.create(title='桃花宝典',price=4000,pub_date='1991-1-23',publish=publish_obj)

# 方式二:使用publish_id参数指定关联
book_obj1=Book.objects.create(title='葵花宝典',price=2000,pub_date='1985-3-11',publish_id=publish_obj.nid)

book_obj2=Book.objects.create(title='菊花宝典',price=3000,pub_date='1990-1-21',publish_id=1) # 在已经出版社id的情况下,可以直接指定

book_obj3=Book.objects.create(title='桃花宝典',price=4000,pub_date='1991-1-23',publish_id=1)

# 注意:无论方式一还是方式二得到的书籍对象book_obj1、book_obj2、book_obj3
#      都可以调用publish字段来访问关联的那一个出版社对象
#      都可以调用publish_id来访问关联的那一个出版社对象的nid
print(book_obj1.publish,book_obj1.publish_id) 
print(book_obj2.publish,book_obj2.publish_id) 
print(book_obj3.publish,book_obj3.publish_id)
# 三本书关联的是同一个出版社,所以输出结果均相同
参照上述步骤,把剩余三本书与出版社的对应关系也插入

book_obj1 = Book.objects.create(title='玉女心经', price=5000, pub_date='1988-3-24', publish_id=2)

book_obj2 = Book.objects.create(title='玉男心经', price=3000, pub_date='1985-6-17', publish_id=2)

book_obj3 = Book.objects.create(title='九阴真经', price=6000, pub_date='1983-8-17', publish_id=3)
2、一对一:app01_author与app01_authordetail

# 需求:插入三个作者,并与作者详情表一一对应
# 由于作者详情表我们已经事先创建好记录,所以只需要往作者表插入记录即可
# 方式一:需要事先过滤出作者详情的对象,然后通过模型Author的字段author来指定要关联的作者详情对象(略)

# 方式二:确定作者详情对象的id,然后通过模型Author通过字段author_id来指定关联关系,
Author.objects.create(name='egon',age=18,author_detail_id=1)
Author.objects.create(name='kevin',age=38,author_detail_id=2)
Author.objects.create(name='rose',age=28,author_detail_id=3)
3、多对多:app01_book与app01_author

# 我们参照物理表app01_book_authors制定需求,需要创建如下关系
# 1、葵花宝典的作者为:egon、kevin
# 2、菊花宝典的作者为:egon、kevin、rose
# 3、桃花宝典的作者为:egon、kevin
# 4、玉女心经的作者为:kevin、rose
# 5、玉男心经的作者为:kevin
# 6、九阴真经的作者为:egon、rose

# 需要创建出上述关系,具体做法如下
# 1、先获取书籍对象
book_obj1=Book.objects.get(title='葵花宝典')
book_obj2=Book.objects.get(title='菊花宝典')
book_obj3=Book.objects.get(title='桃花宝典')
book_obj4=Book.objects.get(title='玉女心经')
book_obj5=Book.objects.get(title='玉男心经')
book_obj6=Book.objects.get(title='九阴真经')

# 2、然后获取作者对象
egon=Author.objects.get(name='egon')
kevin=Author.objects.get(name='kevin')
rose=Author.objects.get(name='rose')

# 3、最后依次创建上述关系:在原生SQL中多对多关系涉及到操作第三张关系表,但是在ORM中我们只需要操作模型类Book下的字段author即可
book_obj1.authors.add(egon,kevin)
book_obj2.authors.add(egon,kevin,rose)
book_obj3.authors.add(egon,kevin)
book_obj4.authors.add(kevin,rose)
book_obj5.authors.add(kevin)
book_obj6.authors.add(egon,rose)
可以通过书籍对象下的authors字段获取其所关联的所有作者对象

book_obj1.authors.all() # 返回一个存有多个作者的queryset

 

 

 

删除、修改记录

# 1、book_obj.authors.remove() :将某个特定的对象从被关联对象集合中去除
# 从菊花宝典的作者集合中去掉作者rose
rose = Author.objects.get(name='rose')
book_obj2 = Book.objects.get(title='菊花宝典')
book_obj2.authors.remove(rose)

# 2、book_obj.authors.clear():清空被关联对象集合
# 清空菊花宝典所关联的所有作者
book_obj2 = Book.objects.get(title='菊花宝典')
book_obj2.authors.clear()

# 3、book_obj.authors.set():先清空再重新设置 
# 玉男心经的作者原来为kevin,要求设置为egon、rose
egon=Author.objects.get(name='egon')
rose=Author.objects.get(name='rose')

book_obj5 = Book.objects.get(title='玉男心经')

book_obj5.authors.set([egon,rose]) # 多个作者对象放到列表里

 

 

查询记录

数据库操作最常用的还是查询操作,在介绍ORM下多表关联查询时,需要事先记住关于ORM模型的一个非常重要的概念:在使用模型类进行多表关联查询时,如果确定两张表存在关联关系,那么在选取一个表作为起始(为了后续描述方便,我们将其简称为"基表")后,可以跨表引用来自另外一张中的字段值,这存在正向与反向之分

如果关联字段存在于基表中,称之为正向查询,否则,称之为反向查询

例如表模Book与Publish,关联字段存在于Book中

# 当以Book为基表时,称之为正向查询
Book(基表)-------正向---------->Publish

# 当以Publish为基表时,称之为反向查询
Book<-------反向----------Publish(基表)
使用原生sql进行多表关联查询时无非两种方式:子查询、join连表查询,ORM里同样有两种查询方式(严格依赖正向、反向的概念)

 

标签:Book,顺序,objects,新建,数据库,publish,book,app01,id
From: https://www.cnblogs.com/97zs/p/18059475

相关文章

  • 实体类与数据库的直接交互问题,DTO,AutoMapper的使用
    实体类、DTO与数据库交互的最佳实践实体类与数据库的直接交互问题在软件开发中,实体类通常被设计为反映业务域的数据模型。这些实体类可能包含以下元素:特性(Attributes):用于定义实体属性的额外信息,比如数据验证规则或ORM(对象关系映射)框架的映射信息。继承关系:实体之间可能存......
  • 关于安卓开发远程连接mysql数据库2
    安卓开发远程连接数据库方式2:通过发送请求到web中间层实现对数据库的增删改查操作。第一步需要给安卓程序添加上网络权限,在安卓项目中的配置文件中加上代码<uses-permission android:name="android.permission.INTERNET"/>语句用于获得访问网络的权限第二步添加Retrofit+GSON......
  • Vue+Axios的方法异步回调顺序问题
    一、问题阐述有的时候我们需要控制异步函数的执行顺序,比如a方法中如果要用到异步函数b方法的请求结果,就需要进行顺序控制,否则a函数先执行就会导致找不到数据直接报错。二、方法1.异步控制1.1.async,await等做异步控制1.2修改函数放置位置达到异步控制效果(我遇到的情况无效,但......
  • 数据库第1章 绪论
    数据库知识总结第1章绪论课本知识:1.数据库系统是由数据库、数据库管理系统、应用程序和数据库管理员组成的存储、管理、处理和维护数据的系统。2.数据模型通常由数据结构、数据操作和数据的完整性约束条件三部分组成。3.数据库领域中主要的逻辑数据模型:层次模型、网状......
  • Python中怎么使用Spark的spark.read.format()函数读取MySQL数据库中的数据
    1.准备工作:安装pyspark库(pipinstallpyspark)2.代码:#导入模块frompyspark.sqlimportSparkSession#创建Spark会话对象spark=SparkSession.builder\.appName("ReadMySQL")\.getOrCreate()#或者写成一行spark=SparkSession.builder.appName("ReadMySQL&qu......
  • c# 文件转为byte 存储到SQL Server数据库,数据库读取byte字段下载到本地
    //fileLocal为文件路径 System.IO.FileStreamfs=newSystem.IO.FileStream(fileLocal,FileMode.Open);        BinaryReaderbr=newBinaryReader(fs);        byte[]fileData=br.ReadBytes(Convert.ToInt32(fs.Length));    ......
  • Oracle数据库Date类型查询结果多出“.0“的解决方法
    ​ oracle设置数据库某张表的字段类型为date,数据库存值为 2019-11-2518:51:47格式,但是从数据库查询出来之后格式为  StringstopTime=map.get("stopTime").toString;2019-11-2518:51:47.0,多了个零,不知是毫秒还是纳秒,目前还不知为何,解决办法为转换时间类型或者前端分......
  • 如何新建逻辑卷及磁盘挂载,逻辑卷扩容
    一、创建逻辑卷;pvcreate/dev/sdb;#在块设备 /dev/sdb 上创建一个物理卷。vgcreatevg_data/dev/sdb;#使用物理卷 /dev/sdb 创建一个名为 vg_data 的卷组。lvcreate-l100%VG-nlv_datavg_data;#在卷组 vg_data 中创建一个名为 lv_data 的逻辑卷,占用卷组中所有可用空......
  • Java连接PostgreSQL数据库测试
    importjava.sql.DriverManager;importjava.sql.Connection;importjava.sql.SQLException;importjava.sql.ResultSet;importjava.sql.Statement;publicclassPG{publicstaticvoidmain(String[]args){System.out.println("PostgreSQLJDBC......
  • Presto适配高斯数据库
    Presto是什么Presto是一个分布式SQL查询引擎,旨在查询大型数据集分布在一个或多个异构数据源上。笔者所参与的项目主要使用Presto做数据探查和数据分析。Presto架构Presto查询引擎是一个Master-Slave的架构,由一个Coordinator节点,一个DiscoveryServer节点,多个Worker节点组......