聚合查詢
- 聚合查詢是指對一個數(shù)據(jù)表中的一個字段的數(shù)據(jù)進(jìn)行部分或全部進(jìn)行統(tǒng)計(jì)查詢,查bookstore_book數(shù)據(jù)表中的全部書的平均價(jià)格,查詢所有書的總個數(shù)等,都要使用聚合查詢
-
不帶分組聚合
不帶分組的聚合查詢是指導(dǎo)將全部數(shù)據(jù)進(jìn)行集中統(tǒng)計(jì)查詢
-
聚合函數(shù):
- 定義模塊:
django.db.models
- 用法:
from django.db.models import *
- 聚合函數(shù):
- Sum, Avg, Count, Max, Min
- 定義模塊:
-
語法:
- MyModel.objects.aggregate(結(jié)果變量名=聚合函數(shù)('列'))
-
返回結(jié)果:
- 由 結(jié)果變量名和值組成的字典
- 格式為:
{"結(jié)果變量名": 值}
-
示例:
# 得到所有書的平均價(jià)格 from bookstore import models from django.db.models import Count result = models.Book.objects.aggregate(myAvg=Avg('price')) print("平均價(jià)格是:", result['myAvg']) print("result=", result) # {"myAvg": 58.2} # 得到數(shù)據(jù)表里有多少本書 from django.db.models import Count result = models.Book.objects.aggregate(mycnt=Count('title')) print("數(shù)據(jù)記錄總個數(shù)是:", result['mycnt']) print("result=", result) # {"mycnt": 10}
-
分組聚合
分組聚合是指通過計(jì)算查詢結(jié)果中每一個對象所關(guān)聯(lián)的對象集合,從而得出總計(jì)值(也可以是平均值或總和),即為查詢集的每一項(xiàng)生成聚合。
-
語法:
- QuerySet.annotate(結(jié)果變量名=聚合函數(shù)('列'))
-
用法步驟:
-
通過先用查詢結(jié)果MyModel.objects.value. 查找查詢要分組聚合的列
MyModel.objects.value('列1', '列2')
-
如:
pub_set = models.Book.objects.values('pub') print(books) # <QuerySet [{'pub': '清華大學(xué)出版社'}, {'pub': '清華大學(xué)出版社'}, {'pub_hou {'pub': '機(jī)械工業(yè)出版社'}, {'pub': '清華大學(xué)出版社'}]>
-
通過返回結(jié)果的 QuerySet.annotate 方法分組聚合得到分組結(jié)果
QuerySet.annotate(名=聚合函數(shù)('列'))
返回 QuerySet 結(jié)果集,內(nèi)部存儲結(jié)果的字典
-
如:
pub_count_set = pub_set.annotate(myCount=Count('pub')) print(pub_count_set) # <QuerySet [{'pub': '清華大學(xué)出版社', 'myCount': 7}, {'pub': '機(jī)械工業(yè)出版社', 'myCount': 3}]>
- .values('查詢列名')
-
-
示例:
- 得到哪兒個出版社共出版多少本書
def test_annotate(request): - from django.db.models import Count from . import models # 得到所有出版社的查詢集合QuerySet pub_set = models.Book.objects.values('pub') # 根據(jù)出版社查詢分組,出版社和Count的分組聚合查詢集合 pub_count_set = pub_set.annotate(myCount=Count('pub')) # 返回查詢集合 for item in pub_count_set: print("出版社:", item['pub'], "圖書有:", item['myCount']) return HttpResponse('請查看服務(wù)器端控制臺獲取結(jié)果')
F對象
- 一個F對象代表數(shù)據(jù)庫中某個字段的信息
- F對象通常是對數(shù)據(jù)庫中的字段值在不加載到內(nèi)存中的情況下直接在數(shù)據(jù)庫服務(wù)器端進(jìn)行操作
- F對象在 數(shù)據(jù)包 django.db.models 中.使用時需要通過如下語句進(jìn)行加載
from django.db.models import F
-
作用:
- 用于類屬性(字段)之間的比較。
- 當(dāng)同時對數(shù)據(jù)庫中兩個字段的值進(jìn)行比較獲取 QuerySet 數(shù)據(jù)集時,可以便用F對象
-
說明:
- 一個 F() 對象代表了一個model的字段的值
使用它就可以直接參考model的field和執(zhí)行數(shù)據(jù)庫操作而不用再把它們(model field)查詢出來放到python內(nèi)存中。
-
語法:
from django.db.models import F F('列名')
-
示例1
- 更新Book實(shí)例中所有的零售價(jià)漲10元
models.Book.objects.all().update(market_price=F('market_price')+10) # 以下做法好于如下代碼 books = models.Book.objects.all() for book in books: book.update(market_price=book.marget_price+10) book.save()
-
示例2
- 對數(shù)據(jù)庫中兩個字段的值進(jìn)行比較,列出哪兒些書的零售價(jià)高于定價(jià)?
from django.db.models import F from bookstore import models books = models.Book.objects.filter(market_price__gt=F('price')) for book in books: print(book.title, '定價(jià):', book.price, '現(xiàn)價(jià):', book.market_price)
Q對象 - Q()
當(dāng)在獲取查詢結(jié)果集 使用復(fù)雜的邏輯或
|
、 邏輯非~
等操作時可以借助于 Q對象進(jìn)行操作-
如: 想找出定價(jià)低于20元 或 清華大學(xué)出版社的全部書,可以寫成
models.Book.objects.filter(Q(price__lt=20)|Q(pub="清華大學(xué)出版社"))
-
Q對象在 數(shù)據(jù)包 django.db.models 中。需要先導(dǎo)入再使用
from django.db.models import Q
-
作用
- 在條件中用來實(shí)現(xiàn)除 and(&) 以外的 or(|) 或 not(~) 操作
-
運(yùn)算符:
- & 與操作
- | 或操作
- ? 非操作
-
語法
from django.db.models import Q Q(條件1)|Q(條件2) # 條件1成立或條件2成立 Q(條件1)&Q(條件2) # 條件1和條件2同時成立 Q(條件1)&~Q(條件2) # 條件1成立且條件2不成立 ...
-
示例
from django.db.models import Q # 查找清華大學(xué)出版社的書或價(jià)格低于50的書 models.Book.objects.filter(Q(market_price__lt=50) | Q(pub_house='清華大學(xué)出版社')) # 查找不是機(jī)械工業(yè)出版社的書且價(jià)格低于50的書 models.Book.objects.filter(Q(market_price__lt=50) & ~Q(pub_house='機(jī)械工業(yè)出版社'))
原生的數(shù)據(jù)庫操作方法
使用MyModel.objects.raw()進(jìn)行 數(shù)據(jù)庫查詢操作查詢
- 在django中,可以使用模型管理器的raw方法來執(zhí)行select語句進(jìn)行數(shù)據(jù)查詢
-
語法:
MyModel.objects.raw(sql語句)
-
用法
MyModel.objects.raw('sql語句')
-
返回值:
- QuerySet 集合對象
-
示例
books = models.Book.objects.raw('select * from bookstore_book') for book in books: print(book)
使用django中的游標(biāo)cursor對數(shù)據(jù)庫進(jìn)行 增刪改操作
在Django中可以使用 如UPDATE,DELETE等SQL語句對數(shù)據(jù)庫進(jìn)行操作。
在DJaogo中使用上述非查詢語句必須使用游標(biāo)進(jìn)行操作
-
使用步驟:
- 導(dǎo)入cursor所在的包
- Django中的游標(biāo)cursor定義在 django.db.connection包中,使用前需要先導(dǎo)入
- 如:
from django.db import connection
- 用創(chuàng)建cursor類的構(gòu)造函數(shù)創(chuàng)建cursor對象,再使用cursor對象,為保證在出現(xiàn)異常時能釋放cursor資源,通常使用with語句進(jìn)行創(chuàng)建操作
-
如:
from django.db import connection with connection.cursor() as cur: cur.execute('執(zhí)行SQL語句')
-
-
示例
# 用SQL語句將id 為 10的 書的出版社改為 "XXX出版社" from django.db import connection with connection.cursor() as cur: cur.execute('update bookstore_book set pub_house="XXX出版社" where id=10;') with connection.cursor() as cur: # 刪除 id為1的一條記錄 cur.execute('delete from bookstore_book where id=10;')
- 導(dǎo)入cursor所在的包
admin 后臺數(shù)據(jù)庫管理
- django 提供了比較完善的后臺管理數(shù)據(jù)庫的接口,可供開發(fā)過程中調(diào)用和測試使用
- django 會搜集所有已注冊的模型類,為這些模型類提拱數(shù)據(jù)管理界面,供開發(fā)者使用
- 使用步驟:
-
創(chuàng)建后臺管理帳號:
-
后臺管理--創(chuàng)建管理員帳號
$ python3 manage.py createsuperuser
- 根據(jù)提示完成注冊,參考如下:
$ python3 manage.py createsuperuser Username (leave blank to use 'tarena'): tarena # 此處輸入用戶名 Email address: weimz@tedu.cn # 此處輸入郵箱 Password: # 此處輸入密碼(密碼要復(fù)雜些,否則會提示密碼太簡單) Password (again): # 再次輸入重復(fù)密碼 Superuser created successfully. $
-
-
用注冊的帳號登陸后臺管理界面
- 后臺管理的登錄地址:
-
自定義后臺管理數(shù)據(jù)表
- 若要自己定義的模型類也能在
/admin
后臺管理界中顯示和管理,需要將自己的類注冊到后臺管理界面 - 添加自己定義模型類的后臺管理數(shù)據(jù)表的,需要用
admin.site.register(自定義模型類)
方法進(jìn)行注冊-
配置步驟如下:
-
在應(yīng)用app中的admin.py中導(dǎo)入注冊要管理的模型models類, 如:
from . import models
-
調(diào)用 admin.site.register 方法進(jìn)行注冊,如:
from django.contrib import admin admin.site.register(自定義模型類)
-
如: 在 bookstore/admin.py 添加如下代碼對Book類進(jìn)行管理
-
示例:
# file: bookstore/admin.py from django.contrib import admin # Register your models here. from . import models ... admin.site.register(models.Book) # 將Book類注冊為可管理頁面
-
修改后臺Models的展現(xiàn)形式
在admin后臺管理數(shù)據(jù)庫中對自定義的數(shù)據(jù)記錄都展示為
XXXX object
類型的記錄,不便于閱讀和判斷-
在用戶自定義的模型類中可以重寫
def __str__(self):
方法解決顯示問題,如:- 在 自定義模型類中重寫 str(self) 方法返回顯示文字內(nèi)容:
class Book(models.Model): ... def __str__(self): return "書名" + self.title
模型管理器類
-
作用:
- 為后臺管理界面添加便于操作的新功能。
-
說明:
- 后臺管理器類須繼承自
django.contrib.admin
里的ModelAdmin
類
- 后臺管理器類須繼承自
-
模型管理器的使用方法:
-
在
<應(yīng)用app>/admin.py
里定義模型管理器類class XXXX_Manager(admin.ModelAdmin): ......
-
注冊管理器與模型類關(guān)聯(lián)
from django.contrib import admin from . import models admin.site.register(models.YYYY, XXXX_Manager) # 注冊models.YYYY 模型類與 管理器類 XXXX_Manager 關(guān)聯(lián)
-
示例:
# file : bookstore/admin.py from django.contrib import admin from . import models class BookAdmin(admin.ModelAdmin): list_display = ['id', 'title', 'price', 'market_price'] admin.site.register(models.Book, BookAdmin)
- 進(jìn)入http://127.0.0.1:8000/admin/bookstore/book/ 查看顯示方式和以前有所不同
-
-
模型管理器類ModelAdmin中實(shí)現(xiàn)的高級管理功能
- list_display 去控制哪些字段會顯示在Admin 的修改列表頁面中。
- list_display_links 可以控制list_display中的字段是否應(yīng)該鏈接到對象的“更改”頁面。
- list_filter 設(shè)置激活A(yù)dmin 修改列表頁面右側(cè)欄中的過濾器
- search_fields 設(shè)置啟用Admin 更改列表頁面上的搜索框。
- list_editable 設(shè)置為模型上的字段名稱列表,這將允許在更改列表頁面上進(jìn)行編輯。
- 其它參見https://docs.djangoproject.com/en/1.11/ref/contrib/admin/
數(shù)據(jù)庫表管理
-
修改模型類字段的顯示名字
模型類各字段的第一個參數(shù)為 verbose_name,此字段顯示的名字會在后臺數(shù)據(jù)庫管理頁面顯示
-
通過 verbose_name 字段選項(xiàng),修改顯示名稱示例如下:
title = models.CharField( max_length = 30, verbose_name='顯示名稱' )
-
通過Meta內(nèi)嵌類 定義模型類的屬性及展現(xiàn)形式
模型類可以通過定義內(nèi)部類class Meta 來重新定義當(dāng)前模型類和數(shù)據(jù)表的一些屬性信息
-
用法格式如下:
class Book(models.Model): title = CharField(....) class Meta: 1. db_table = '數(shù)據(jù)表名' - 該模型所用的數(shù)據(jù)表的名稱。(設(shè)置完成后需要立馬更新同步數(shù)據(jù)庫) 2. verbose_name = '單數(shù)名' - 給模型對象的一個易于理解的名稱(單數(shù)),用于顯示在/admin管理界面中 3. verbose_name_plural = '復(fù)數(shù)名' - 該對象復(fù)數(shù)形式的名稱(復(fù)數(shù)),用于顯示在/admin管理界面中
-
示例:
class Meta: db_table = 'book_table' # 將原數(shù)據(jù)表名"bookstore_book" 換為 "book_table",請查看數(shù)據(jù)表 verbose_name = 'booooook' verbose_name_plural = 'booksssssss' # 去127.0.0.1:8000/admin下看看哪兒變化了?
- 練習(xí):
- 將Book模型類 和 Author 模型類都加入后臺管理
- 制作一個AuthorManager管理器類,讓后臺管理Authors列表中顯示作者的ID、姓名、年齡信息
- 用后臺管理程序 添加三條 Author 記錄
- 修改其中一條記錄的年齡
- 刪除最后一條添加的記錄
- 將bookstore_author 數(shù)名表名稱改為myauthor (需要重新遷移數(shù)據(jù)庫)
數(shù)據(jù)表關(guān)聯(lián)關(guān)系映射 Relationship Map
- 在關(guān)系型數(shù)據(jù)庫中,通常不會把所有數(shù)據(jù)都放在同一張表中,這樣做會額外占用內(nèi)存空間,
- 在關(guān)系列數(shù)據(jù)庫中通常用表關(guān)聯(lián)來解決數(shù)據(jù)庫。
- 常用的表關(guān)聯(lián)方式有三種:
- 一對一映射
- 如: 一個身份證對應(yīng)一個人
- 一對多映射
- 如: 一個班級可以有多個學(xué)生
- 多對多映射
- 如: 一個學(xué)生可以報(bào)多個課程,一個課程可以有多個學(xué)生學(xué)習(xí)
- 一對一映射
一對一映射
- 一對一是表示現(xiàn)實(shí)事物間存在的一對一的對應(yīng)關(guān)系。
- 如:一個家庭只有一個戶主,一個男人有一個妻子,一個人有一個唯一的指紋信息等
-
語法
在關(guān)聯(lián)的兩個類中的任何一個類中: class A(model.Model): ... class B(model.Model): 屬性 = models.OneToOneField(A)
-
用法示例
-
創(chuàng)建作家和作家妻子類
# file : xxxxxxxx/models.py from django.db import models class Author(models.Model): '''作家模型類''' name = models.CharField('作家', max_length=50) class Wife(models.Model): '''作家妻子模型類''' name = models.CharField("妻子", max_length=50) author = models.OneToOneField(Author) # 增加一對一屬性
-
查詢
- 在 Wife 對象中,通過 author 屬性找到對應(yīng)的author對象
- 在 Author 對象中,通過 wife 屬性找到對應(yīng)的wife對象
-
創(chuàng)始一對一的數(shù)據(jù)記錄
from . import models author1 = models.Author.objects.create(name='王老師') wife1 = models.Wife.objects.create(name='王夫人', author=author1) # 關(guān)聯(lián)王老師 author2 = models.Author.objects.create(name='小澤老師') # 一對一可以沒有數(shù)據(jù)對應(yīng)的數(shù)據(jù)
-
一對一數(shù)據(jù)的相互獲取
-
正向查詢
- 直接通過關(guān)聯(lián)屬性查詢即可
# 通過 wife 找 author from . import models wife = models.Wife.objects.get(name='王夫人') print(wife.name, '的老公是', wife.author.name)
-
反向查詢
- 通過反向引用屬性查詢
- 反向引用屬性為
實(shí)例對象.引用類名(小寫)
,如作家的反向引用為作家對象.wife
- 當(dāng)反向引用不存在時,則會觸發(fā)異常
# 通過 author.wife 引用屬性 找 wife,如果沒有對應(yīng)的wife剛觸發(fā)異常 author1 = models.Author.objects.get(name='王老師') print(author1.name, '的妻子是', author1.wife.name) author2 = models.Author.objects.get(name='小澤老師') try: print(author2.name, '的妻子是', author2.wife.name) except: print(author2.name, '還沒有妻子')
-
-
-
作用:
- 主要是解決常用數(shù)據(jù)不常用數(shù)據(jù)的存儲問題,把經(jīng)常加載的一個數(shù)據(jù)放在主表中,不常用數(shù)據(jù)放在另一個副表中,這樣在訪問主表數(shù)據(jù)時不需要加載副表中的數(shù)據(jù)以提高訪問速度提高效率和節(jié)省內(nèi)存空間,如經(jīng)常把書的內(nèi)容和書名建成兩張表,因?yàn)樵诰W(wǎng)站上經(jīng)常訪問書名等信息,但不需要得到書的內(nèi)容。
-
練習(xí):
- 創(chuàng)建一個Wife模型類,屬性如下
- name
- age
- 在Wife類中增加一對一關(guān)聯(lián)關(guān)系,引用 Author
- 同步回?cái)?shù)據(jù)庫并觀察結(jié)果
- 創(chuàng)建一個Wife模型類,屬性如下
一對多映射
- 一對多是表示現(xiàn)實(shí)事物間存在的一對多的對應(yīng)關(guān)系。
- 如:一個學(xué)校有多個班級,一個班級有多個學(xué)生, 一本圖書只能屬于一個出版社,一個出版社允許出版多本圖書
-
用法語法
- 當(dāng)一個A類對象可以關(guān)聯(lián)多個B類對象時
class A(model.Model): ... class B(model.Model): 屬性 = models.ForeignKey(多對一中"一"的模型類, ...)
-
外鍵類ForeignKey
-
構(gòu)造函數(shù):
ForeignKey(to, on_delete, **options)
-
常用參數(shù):
- on_delete
- models.CASCADE 級聯(lián)刪除。 Django模擬SQL約束ON DELETE CASCADE的行為,并刪除包含F(xiàn)oreignKey的對象。
- models.PROTECT 拋出ProtectedError 以阻止被引用對象的刪除;
- SET_NULL 設(shè)置ForeignKey null;只有null是True才有可能。
- SET_DEFAULT 將ForeignKey設(shè)置為其默認(rèn)值;必須設(shè)置ForeignKey的默認(rèn)值。
- ... 其它參請參考文檔 https://docs.djangoproject.com/en/1.11/ref/models/fields/#foreignkey ForeignKey部分
-
**options
可以是常用的字段選項(xiàng)如:- null
- unique等
- ...
- on_delete
-
-
示例
- 有二個出版社對應(yīng)五本書的情況.
-
清華大學(xué)出版社
有書- C++
- Java
- Python
-
北京大學(xué)出版社
有書- 西游記
- 水滸
-
-
定義一對多類
# file: myorm/models.py from django.db import models class Publisher(models.Model): '''出版社''' name = models.CharField('名稱', max_length=50, unique=True) class Book(models.Model): title = models.CharField('書名', max_length=50) publisher = models.ForeignKey(Publisher, null=True)
-
創(chuàng)建一對多的對象
# file: xxxxx/views.py from . import models pub1 = models.Publisher.objects.create(name='清華大學(xué)出版社') models.Book.objects.create(title='C++', publisher=pub1) models.Book.objects.create(title='Java', publisher=pub1) models.Book.objects.create(title='Python', publisher=pub1) pub2 = models.Publisher.objects.create(name='北京大學(xué)出版社') models.Book.objects.create(title='西游記', publisher=pub2) models.Book.objects.create(title='水滸', publisher=pub2)
-
查詢:
- 通過多查一
# 通過一本書找到對應(yīng)的出版社 abook = models.Book.objects.get(id=1) print(abook.title, '的出版社是:', abook.publisher.name)
- 通過一查多
# 通過出版社查詢對應(yīng)的書 pub1 = models.Publisher.objects.get(name='清華大學(xué)出版社') books = pub1.book_set.all() # 通過book_set 獲取pub1對應(yīng)的多個Book數(shù)據(jù)對象 # books = models.Book.objects.filter(publisher=pub1) # 也可以采用此方式獲取 print("清華大學(xué)出版社的書有:") for book in books: print(book.title)
- 有二個出版社對應(yīng)五本書的情況.
- 練習(xí):
- 完成Book 和 Publisher 之間的一對多
- 查看數(shù)據(jù)庫效果
- 登錄到后臺,查看Book實(shí)體
- 數(shù)據(jù)查詢
-
通過 Book 查詢 Publisher
通過 publisher 屬性查詢即可 練習(xí): 查詢 西游記 對應(yīng)的出版社信息,打印在終端上
-
通過 Publisher 查詢 對應(yīng)的所有的 Books
Django會在Publisher中增加一個屬性來表示對對應(yīng)的Book們的查詢引用 屬性:book_set(MyModel.objects)
-
多對多映射
- 多對多表達(dá)對象之間多對多復(fù)雜關(guān)系,如: 每個人都有不同的學(xué)校(小學(xué),初中,高中,...),每個學(xué)校都有不同的學(xué)生...
-
語法
在關(guān)聯(lián)的兩個類中的任意一個類中,增加: 屬性 = models.ManyToManyField(MyModel)
-
示例
一個作者可以出版多本圖書 一本圖書可以被多名作者同時編寫 class Author(models.Model): xxxx xxxx class Book(models.Model): xxxx xxxx authors = models.ManyToManyField(Author)
-
數(shù)據(jù)查詢
-
通過 Book 查詢對應(yīng)的所有的 Authors
可以通過authors表示對應(yīng)所有Author的查詢對象 book.authors.all() -> 獲取 book 對應(yīng)的所有的author的信息 book.authors.filter(age__gt=80) -> 獲取book對應(yīng)的作者中年齡大于80歲的作者的信息
-
通過 Author 查詢對應(yīng)的所有的Books
Django會生成一個屬性 book_set 用于表示對對應(yīng)的book的查詢對象相關(guān)操作? author.book_set.all() author.book_set.filter() author.book_set.create(...) # 創(chuàng)建新書并聯(lián)作用author author.book_set.add(book) # 添加已有的書為當(dāng)前作者author author.book_set.clear() # 刪除author所有并聯(lián)的書 author.book_set.remove() # 刪除所author所有并聯(lián)的書
-
-
示例:
- 多對多模型
class Author(models.Model): '''作家模型類''' name = models.CharField('作家', max_length=50) def __str__(self): return self.name class Book(models.Model): title = models.CharField('書名', max_length=50) author = models.ManyToManyField(Author, null=True) def __str__(self): return self.title
- 多對多視圖操作
from django.http import HttpResponse from . import models def many2many_init(request): # 創(chuàng)建兩人個作者 author1 = models.Author.objects.create(name='呂澤') author2 = models.Author.objects.create(name='魏老師') # 呂擇和魏老師同時寫了一本Python book11 = author1.book_set.create(title="Python") author2.book_set.add(book11) # # 魏老師還寫了兩本書 book21 = author2.book_set.create(title="C") # 創(chuàng)建一本新書"C" book22 = author2.book_set.create(title="C++") # 創(chuàng)建一本新書"C++" return HttpResponse("初始化成功") def show_many2many(request): authors = models.Author.objects.all() for auth in authors: print("作者:", auth.name, '發(fā)出版了', auth.book_set.count(), '本書: ') for book in books: print(' ', book.title) print("----顯示書和作者的關(guān)系----") books = models.Book.objects.all() for book in books: auths = book.author.all() print(book.title, '的作者是:', '、'.join([str(x.name) for x in auths])) return HttpResponse("顯示成功,請查看服務(wù)器端控制臺終端")
- 多對多最終的SQL結(jié)果
mysql> select * from myorm2_author; +----+-----------+ | id | name | +----+-----------+ | 11 | 呂澤 | | 12 | 魏老師 | +----+-----------+ 2 rows in set (0.00 sec) mysql> select * from myorm2_book; +----+--------+ | id | title | +----+--------+ | 13 | Python | | 14 | C | | 15 | C++ | +----+--------+ 3 rows in set (0.00 sec) mysql> select * from myorm2_book_author; +----+---------+-----------+ | id | book_id | author_id | +----+---------+-----------+ | 17 | 13 | 11 | | 20 | 13 | 12 | | 18 | 14 | 12 | | 19 | 15 | 12 | +----+---------+-----------+ 4 rows in set (0.00 sec)
- 示例示意圖 [圖片上傳失敗...(image-ed69a-1563362158182)]