Python3-ORM-Sqlalchemy

目錄:html

 

  1. ORM介紹
  2. sqlalchemy安裝
  3. sqlalchemy基本使用
  4. 多外鍵關聯
  5. 多對多關係
  6. 表結構設計做業

 

1. ORM介紹

  orm英文全稱object relational mapping,就是對象映射關係程序,簡單來講咱們相似python這種面向對象的程序來講一切皆對象,可是咱們使用的數據庫卻都是關係型的,python

爲了保證一致的使用習慣,經過orm將編程語言的對象模型和數據庫的關係模型創建映射關係,這樣咱們在使用編程語言對數據庫進行操做的時候能夠直接使用編程語言的對象模型進行操做就能夠了,mysql

而不用直接使用sql語言。sql

 

                                              

 

orm的優勢:數據庫

  1. 隱藏了數據訪問細節,「封閉」的通用數據庫交互,ORM的核心。他使得咱們的通用數據庫交互變得簡單易行,而且徹底不用考慮該死的SQL語句。快速開發,由此而來。
  2. ORM使咱們構造固化數據結構變得簡單易行。

缺點:express

  1. 無可避免的,自動化意味着映射和關聯管理,代價是犧牲性能(早期,這是全部不喜歡ORM人的共同點)。
  2. 如今的各類ORM框架都在嘗試使用各類方法來減輕這塊(LazyLoad,Cache),效果仍是很顯著的。

 

2. sqlalchemy安裝

  在Python中,最有名的ORM框架是SQLAlchemy。用戶包括openstack\Dropbox等知名公司或應用,主要用戶列表http://www.sqlalchemy.org/organizations.html#openstack編程

                             

 

Dialect用於和數據API進行交流,根據配置文件的不一樣調用不一樣的數據庫API,從而實現對數據庫的操做,如:session

MySQL-Python
    mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
   
pymysql
    mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
   
MySQL-Connector
    mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
   
cx_Oracle
    oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
   
更多詳見:http://docs.sqlalchemy.org/en/latest/dialects/index.html

 

 

安裝sqlalchemy數據結構

 

pip install SQLAlchemy<br><br>pip install pymysql  #因爲mysqldb依然不支持py3,因此這裏咱們用pymysql與sqlalchemy交互

 

 

 3.sqlalchemy基本使用oracle

sql原生語句建立表:

 

CREATE TABLE user ( id INTEGER NOT NULL AUTO_INCREMENT, name VARCHAR(32), password VARCHAR(64), PRIMARY KEY (id) )

 

 orm,實現上面一樣的功能,代碼以下:

第1種建立表結構的方法:

table_structure.py

#Author:Yun
import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String  engine = create_engine("mysql+pymysql://root:yun258762@localhost/test_db", encoding='utf-8', echo=True) Base = declarative_base()  # 生成orm基類


class User(Base): __tablename__ = 'user'  # 表名
    id = Column(Integer, primary_key=True) name = Column(String(32)) password = Column(String(64)) Base.metadata.create_all(engine) # 建立表結構

 

 懶惰鏈接
當create_engine()第一次返回時,引擎實際上尚未嘗試鏈接到數據庫; 只有在第一次要求它對數據庫執行任務時纔會發生這種狀況。

 

第2種建立表結構的方法:

#Author:Yun
from sqlalchemy import Table, MetaData, Column, Integer, String, ForeignKey from sqlalchemy.orm import mapper from sqlalchemy import create_engine metadata = MetaData()#生成metadata類 #建立user表,繼承metadata類 
#Engine使用Schama Type建立一個特定的結構對象
user
= Table('new_user', metadata, Column('id', Integer, primary_key=True), Column('name', String(50)), Column('fullname', String(50)), Column('password', String(12)) ) class User(object): def __init__(self, name, fullname, password): self.name = name self.fullname = fullname self.password = password #表元數據是使用Table構造單首創建的,而後經過mapper()函數與User類相關聯 mapper(User, user) # 經過ConnectionPooling 鏈接數據庫 engine = create_engine("mysql+pymysql://root:yun258762@localhost/test_db?charset=utf8", max_overflow=5, echo=True) # 經過Dialect執行SQL metadata.create_all(engine) #建立表結構

 

 事實上,咱們用第1種方式建立的表就是基於第2種方式的再封裝。

 表已經建立好了開始數據操做:

增長數據:

 

#Author:Yun
import table_structure#導入表結構模塊
from  sqlalchemy.orm import sessionmaker

Session_class = sessionmaker(bind=table_structure.engine)  # 建立與數據庫的會話session class ,注意,這裏返回給session的是個class,不是實例
Session = Session_class()  # 生成session實例#cursor

user_obj = table_structure.User(name="王昭君", password="123456")  # 生成你要建立的數據對象
user_obj2 = table_structure.User(name="韓信", password="123456")  # 生成你要建立的數據對象
#print(user_obj.name, user_obj.id)  # 此時還沒建立對象呢,不信你打印一下id發現仍是None

#print(user_obj.name, user_obj.id)  # 此時也依然還沒建立
Session.add(user_obj)  # 把要建立的數據對象添加到這個session裏, 一會統一建立
Session.add(user_obj2)  # 把要建立的數據對象添加到這個session裏, 一會統一建立
Session.commit()  # 現此才統一提交,建立數據
View Code

效果:

mysql> select * from  user;
+----+-------------+----------+
| id | name        | password |
+----+-------------+----------+
| 1 | 王昭君      | 123456   |
| 2 | 韓信        | 123456   |
+----+-------------+----------+
2 rows in set (0.00 sec)
View Code

 

 查找數據:

 

#Author:Yun
import table_structure#導入表結構模塊
from  sqlalchemy.orm import sessionmaker

Session_class = sessionmaker(bind=table_structure.engine)  # 建立與數據庫的會話session class ,注意,這裏返回給session的是個class,不是實例
Session = Session_class()  # 生成session實例#cursor
#查找全部數據
data1 = Session.query(table_structure.User).filter_by().all()
#查找第一個數據
data2 = Session.query(table_structure.User).filter_by().first()
#查找id=1的數據
data3= Session.query(table_structure.User).filter_by(id=1).all()
#查找id=2的數據
data4 = Session.query(table_structure.User).filter(table_structure.User.id ==2).all()
#查找id>1的全部數據
data5 = Session.query(table_structure.User).filter(table_structure.User.id>1).all()
#多條件查詢,id>0&id<2的數據
data6 = Session.query(table_structure.User).filter(table_structure.User.id>0).filter(table_structure.User.id<2).all()

print('data1:',data1)
print('data2:',data2)
print('data3:',data3)

print('data4:',data4)
print('data5:',data5)
print('data6:',data6)
View Code

效果:

data1: [<1 name:王昭君>, <2 name:韓信>]
data2: <1 name:王昭君>
data3: [<1 name:王昭君>]
data4: [<2 name:韓信>]
data5: [<2 name:韓信>]
data6: [<1 name:王昭君>]
View Code

 

 修改數據:

 

#Author:Yun
#修改數據
import table_structure#導入表結構模塊
from  sqlalchemy.orm import sessionmaker

Session_class = sessionmaker(bind=table_structure.engine)  # 建立與數據庫的會話session class ,注意,這裏返回給session的是個class,不是實例
Session = Session_class()  # 生成session實例#cursor

data = Session.query(table_structure.User).filter_by(name="王昭君").first()#修改數據

data.name = "妲己"#將王昭君修改成妲己
data.password = '654321'
Session.commit()
View Code

 效果:

mysql> select * from  user;
+----+-------------+----------+
| id | name        | password |
+----+-------------+----------+
| 1 | 妲己        | 654321   |
| 2 | 韓信        | 123456   |
+----+-------------+----------+
2 rows in set (0.00 sec)
View Code

 

 回滾:

 

#Author:Yun
#回滾,相似於事物
import table_structure#導入表結構模塊
from  sqlalchemy.orm import sessionmaker

Session_class = sessionmaker(bind=table_structure.engine)  # 建立與數據庫的會話session class ,注意,這裏返回給session的是個class,不是實例
Session = Session_class()  # 生成session實例#cursor

user_obj = table_structure.User(name="老夫子", password="123456")  # 生成你要建立的數據對象
user_obj2 = table_structure.User(name="雅典娜", password="123456")  # 生成你要建立的數據對象

Session.add(user_obj)  # 把要建立的數據對象添加到這個session裏, 一會統一建立
Session.add(user_obj2)  # 把要建立的數據對象添加到這個session裏, 一會統一建立
print(Session.query(table_structure.User.name).filter(table_structure.User.name.in_(['老夫子','雅典娜'])).all())
print('--------------after  rollback---------------:')
Session.rollback()
print(Session.query(table_structure.User.name).filter(table_structure.User.name.in_(['老夫子','雅典娜'])).all())

Session.commit()#如今才統一提交修改數據
View Code

 

 效果:
[('老夫子',), ('雅典娜',)]
--------------after  rollback---------------:
[]
View Code

 

 
刪除數據:
 
#Author:Yun
#刪除數據
import table_structure#導入表結構模塊
from  sqlalchemy.orm import sessionmaker

Session_class = sessionmaker(bind=table_structure.engine)  # 建立與數據庫的會話session class ,注意,這裏返回給session的是個class,不是實例
Session = Session_class()  # 生成session實例#cursor

data = Session.query(table_structure.User).filter_by(name="妲己").first()#獲取數據
Session.delete(data)#刪除數據

Session.commit()
View Code

 

  效果:
mysql> select * from  user;
+----+-------------+----------+
| id | name        | password |
+----+-------------+----------+
| 2 | 韓信        | 123456   |
+----+-------------+----------+
1 rows in set (0.00 sec)
View Code

 

 
 
統計和分組:
 
#Author:Yun
import table_structure#導入表結構模塊
from  sqlalchemy.orm import sessionmaker

Session_class = sessionmaker(bind=table_structure.engine)  # 建立與數據庫的會話session class ,注意,這裏返回給session的是個class,不是實例
Session = Session_class()  # 生成session實例#cursor

print(Session.query(table_structure.User).filter(table_structure.User.name.in_(['韓信'])).count())#mysql 默認大小寫是同樣的,如 'hello'=='HELLO'
Session.commit()#如今才統一提交修改數據
統計

 

 效果:
1
View Code

 

分組:
#Author:Yun
#統計
import table_structure#導入表結構模塊
from  sqlalchemy.orm import sessionmaker

Session_class = sessionmaker(bind=table_structure.engine)  # 建立與數據庫的會話session class ,注意,這裏返回給session的是個class,不是實例
Session = Session_class()  # 生成session實例#cursor
from  sqlalchemy  import func
print(Session.query(table_structure.User.name,func.count(table_structure.User.name)).group_by(table_structure.User.name).all())
Session.commit()#如今才統一提交修改數據
View Code

 效果:

 

[('韓信', 1)]
View Code

 

 
外鍵關聯:
咱們建立兩個表,student2study_record
table_struct.py
#Author:Yun
#連表操做
import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String,DATE,ForeignKey
from  sqlalchemy.orm import sessionmaker,relationship
engine = create_engine("mysql+pymysql://root:yun258762@localhost/test_db",
                       encoding='utf-8')

Base = declarative_base()  # 生成orm基類
class Student(Base):
    __tablename__ = 'student2'  # 表名
    id = Column(Integer, primary_key=True)
    name = Column(String(32),nullable=False)

    register_date = Column(DATE,nullable=False)

    def __repr__(self):
        return  "<%s name:%s>" % (self.id,self.name)


class  stu_record(Base):

    __tablename__ = 'study_record'
    id = Column(Integer,primary_key=True)
    day = Column(Integer,nullable=False)
    status = Column(String(32),nullable=False)
    stu_id = Column(Integer,ForeignKey('student2.id'))
    # stu_obj = query(id=1)
    # student = query(Student).filter(Student.id == stu_obj.stu_id).first()
    #只是在內存中創建關聯關係
    #容許在stu_record表中用字段self.student.name查詢Student表中的數據
    #stu_obj2 = Session.query(Student).filter(Student.name == 'luban1').first()
    #容許在Student表中用字段stu_obj2.my_study_record查詢stu_record表中的數據

    student = relationship('Student',backref='my_study_record')
    def __repr__(self):
        return  "<%s day:%s status:%s>" % (self.student.name,self.day,self.status)

Base.metadata.create_all(engine)  # 建立表結構
View Code

 

爲表添加數據:

 

#Author:Yun
import table_struct#導入剛剛建立的表結構
from  sqlalchemy.orm import sessionmaker
Session_class = sessionmaker(bind=table_struct.engine)  # 建立與數據庫的會話session class ,注意,這裏返回給session的是個class,不是實例
Session = Session_class()  #生成session實例#cursor
s1 = table_struct.Student(name='學員A',register_date='2015-11-29')
s2 = table_struct.Student(name='學員B',register_date='2016-11-29')
s3 = table_struct.Student(name='學員C',register_date='2017-11-29')
s4 = table_struct.Student(name='學員D',register_date='2018-11-29')

stu_obj1 = table_struct.stu_record(day=1,status='Yes',stu_id=5)
stu_obj2 = table_struct.stu_record(day=2,status='Yes',stu_id=5)
stu_obj3 = table_struct.stu_record(day=2,status='Yes',stu_id=6)
stu_obj4 = table_struct.stu_record(day=3,status='No',stu_id=6)


Session.add_all([s1,s2,s3,s4,stu_obj1,stu_obj2,stu_obj3,stu_obj4])

Session.commit()#如今才統一提交修改數據
View Code

 

 

 

 跨表查詢:
#Author:Yun
#連表
import table_struct#導入剛剛建立的表結構
from  sqlalchemy.orm import sessionmaker
Session_class = sessionmaker(bind=table_struct.engine)  # 建立與數據庫的會話session class ,注意,這裏返回給session的是個class,不是實例
Session = Session_class()#生成session實例#cursor
#跨表查詢
stu_obj = Session.query(table_struct.Student).filter(table_struct.Student.name=='學員A').first()
print(stu_obj.my_study_record)
Session.commit()#如今才統一提交修改數據
View Code

 

 效果:
 
[<學員A day:1 status:Yes>, <學員A day:2 status:Yes>]
View Code

 

 經常使用查詢語法:
 
常見的過濾器操做符
如下是filter()中使用的一些最多見運算符的概述
 
  • equals:

         query.filter(User.name == 'ed')
    
  • not equals:

         query.filter(User.name != 'ed')
    
  • LIKE:

    query.filter(User.name.like('%ed%'))

  • IN:

  • NOT IN:
    query.filter(~User.name.in_(['ed', 'wendy', 'jack']))

  • IS NULL:

  • IS NOT NULL:

  • AND:
    2.1. ObjectRelationalTutorial 17

 
query.filter(User.name.in_(['ed', 'wendy', 'jack']))
# works with query objects too:

query.filter(User.name.in_( session.query(User.name).filter(User.name.like('%ed%'))

))

query.filter(User.name == None)
# alternatively, if pep8/linters are a concern
query.filter(User.name.is_(None))
query.filter(User.name != None)
# alternatively, if pep8/linters are a concern
query.filter(User.name.isnot(None))

SQLAlchemy Documentation, Release 1.1.0b1

# use and_()

from sqlalchemy import and_
query.filter(and_(User.name == 'ed', User.fullname == 'Ed Jones'))

# or send multiple expressions to .filter()
query.filter(User.name == 'ed', User.fullname == 'Ed Jones')
# or chain multiple filter()/filter_by() calls
query.filter(User.name == 'ed').filter(User.fullname == 'Ed Jones')

Note: Makesureyouuseand_()andnotthePythonandoperator! • OR:

Note: Makesureyouuseor_()andnotthePythonoroperator! • MATCH:

query.filter(User.name.match('wendy'))
Note: match() uses a database-specific MATCH or CONTAINS f 

 

4.多外鍵關聯

  處理的最多見狀況之一是兩個表之間有多個外鍵路徑。考慮一個Customer類,它包含Address類的兩個外鍵:
 
下表中,Customer表有2個字段都關聯了Address表
#Author:Yun
import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String,DATE,ForeignKey
from  sqlalchemy.orm import relationship
engine = create_engine("mysql+pymysql://root:yun258762@192.168.176.139/test_db",
                       encoding='utf-8')

Base = declarative_base()  # 生成orm基類
class Customer(Base):
    __tablename__ = 'customer'  # 表名
    id = Column(Integer, primary_key=True)
    name = Column(String(32),nullable=False)

    builling_address_id = Column(Integer,ForeignKey('address.id'))

    shipping_address_id = Column(Integer,ForeignKey('address.id'))

    builling_address = relationship("Address",foreign_keys=[builling_address_id])
    shipping_address = relationship("Address",foreign_keys=[shipping_address_id])
    def __repr__(self):
        return  "<%s name:%s>" % (self.id,self.name)


class  Address(Base):

    __tablename__ = 'address'
    id = Column(Integer,primary_key=True)
    street = Column(String(64),nullable=False)
    city = Column(String(64),nullable=False)
    state = Column(String(64),nullable=False)


    def __repr__(self):

        return self.street
Base.metadata.create_all(engine)  # 建立表結構
View Code

 

 添加數據,並跨表查詢
#Author:Yun
#同一張表裏關聯另外一個表裏的兩個地址
import  orm_fk

from sqlalchemy.orm import  sessionmaker

Session_class = sessionmaker(bind=orm_fk.engine)#建立於數據

session = Session_class()#生成session實例  #cursor

add1  = orm_fk.Address(street='中路',city='艾歐尼亞',state='召喚師峽谷' )
add2  = orm_fk.Address(street='上路',city='艾歐尼亞',state='召喚師峽谷' )
add3  = orm_fk.Address(street='下路',city='艾歐尼亞',state='召喚師峽谷' )

session.add_all([add1,add2,add3])

c1 = orm_fk.Customer(name='魯班',builling_address=add1,shipping_address=add1)
c2 = orm_fk.Customer(name='卡莎',builling_address=add1,shipping_address=add2)
c3 = orm_fk.Customer(name='妖姬',builling_address=add2,shipping_address=add3)
#爲表添加數據
#session.add_all([c1,c2,c3])
obj = session.query(orm_fk.Customer).filter(orm_fk.Customer.name=='妖姬').first()
print(obj.name,obj.builling_address,obj.shipping_address)
session.commit()
View Code

 

效果:
妖姬 上路 下路
View Code

5.多對多關係

如今來設計一個能描述「圖書」與「做者」的關係的表結構,需求是

  1. 一本書能夠有好幾個做者一塊兒出版
  2. 一個做者能夠寫好幾本書
思惟構圖:

一本書----》多個做者;一個做者-----》多本書

 

 

 

 

這樣就至關於經過book_m2m_author表完成了book表和author表以前的多對多關聯

用orm如何表示呢?
#Author:Yun
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 engine = create_engine("mysql+pymysql://root:yun258762@localhost/test_db?charset=utf8", ) Base = declarative_base() #通orm自動維護這表,因此不須要用類方法建立,映射
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)) pub_date = Column(DATE) authors = relationship('Author',secondary=book_m2m_author,backref='books') def __repr__(self): return "<book_name:%s date:%s>" % (self.name,self.pub_date) class Author(Base): __tablename__ = 'authors' id = Column(Integer, primary_key=True) name = Column(String(32)) def __repr__(self): return "<author:%s>" %self.name Base.metadata.create_all(engine) # 建立表結構

 

 
 接下來建立幾本書和做者:
import orm_fk from sqlalchemy.orm  import sessionmaker Session_class = sessionmaker(bind=orm_fk.engine)#建立於數據
 session = Session_class() b1 = orm_fk.Book(name='消費者行爲學',pub_date='2018-11-29') b2 = orm_fk.Book(name='活着',pub_date='2018-11-29') b3 = orm_fk.Book(name='盲井',pub_date='2018-11-29') a1 = orm_fk.Author(name='魯班') a2 = orm_fk.Author(name='妖姬') a3 = orm_fk.Author(name='妲己') a4 = orm_fk.Author(name='提莫') b1.authors = [a1,a3] b2.authors = [a2,a4] b3.authors = [a1,a2,a3] session.add_all([b1,b2,b3,a1,a2,a3]) session.commit()

 

 
  效果:
mysql> select * from  authors;
+----+--------+
| id | name   |
+----+--------+
|  1 | 魯班   |
|  2 | 妖姬   |
|  3 | 提莫   |
|  4 | 妲己   |
+----+--------+
4 rows in set (0.00 sec)

mysql> select * from  books;
+----+--------------------+------------+
| id | name               | pub_date   |
+----+--------------------+------------+
|  1 | 消費者行爲學       | 2018-11-29 |
|  2 | 盲井               | 2018-11-29 |
|  3 | 活着               | 2018-11-29 |
+----+--------------------+------------+
3 rows in set (0.00 sec)

mysql> select * from  book_m2m_author;
+---------+-----------+
| book_id | author_id |
+---------+-----------+
|       1 |         1 |
|       1 |         4 |
|       2 |         1 |
|       2 |         2 |
|       2 |         4 |
|       3 |         2 |
|       3 |         3 |
+---------+-----------+
7 rows in set (0.00 sec)

 

 
 此時,咱們去用orm查一下數據
 
import orm_fk from sqlalchemy.orm  import sessionmaker Session_class = sessionmaker(bind=orm_fk.engine)#建立於數據
 session = Session_class() print('----經過做者表查關聯的書-------') author_obj = session.query(orm_fk.Author).filter(orm_fk.Author.name=='魯班').first() print(author_obj.books) print('----經過書表查看關聯的做者-------') book_obj = session.query(orm_fk.Book).filter(orm_fk.Book.id==1).first() print(book_obj.authors) session.commit()

 效果:

 

----經過做者表查關聯的書-------
[<book_name:消費者行爲學 date:2018-11-29>, <book_name:盲井 date:2018-11-29>]
----經過書表查看關聯的做者-------
[<author:魯班>, <author:妲己>]

 

多對多刪除

刪除數據時不用管boo_m2m_authors , sqlalchemy會自動幫你把對應的數據刪除

經過書刪除做者

#Author:Yun
import orm_fk from sqlalchemy.orm  import sessionmaker Session_class = sessionmaker(bind=orm_fk.engine)#建立於數據
 session = Session_class() author_obj = session.query(orm_fk.Author).filter_by(name="魯班").first() book_obj = session.query(orm_fk.Book).filter_by(name="盲井").first() book_obj.authors.remove(author_obj) # 從一本書裏刪除一個做者
session.commit()

 

 
 效果:
刪除以前: mysql> select * from book_m2m_author; +---------+-----------+
| book_id | author_id |
+---------+-----------+
|       1 |         1 |
|       1 |         4 |
|       2 |         1 |
|       2 |         2 |
|       2 |         4 |
|       3 |         2 |
|       3 |         3 |
+---------+-----------+
7 rows in set (0.00 sec) 刪除以後: mysql> select * from book_m2m_author; +---------+-----------+
| book_id | author_id |
+---------+-----------+
|       1 |         1 |
|       1 |         4 |
|       2 |         2 |
|       2 |         4 |
|       3 |         2 |
|       3 |         3 |
+---------+-----------+
6 rows in set (0.00 sec)

 

 

直接刪除做者 

刪除做者時,會把這個做者跟全部書的關聯關係數據也自動刪除

 

#Author:Yun
import orm_fk from sqlalchemy.orm  import sessionmaker Session_class = sessionmaker(bind=orm_fk.engine)#建立於數據
 session = Session_class() author_obj =session.query(orm_fk.Author).filter_by(name="魯班").first() print(author_obj.name , author_obj.books) session.delete(author_obj) session.commit()

 

 

 

效果:

mysql> select * from  book_m2m_author;
+---------+-----------+
| book_id | author_id |
+---------+-----------+
|       1 |         1 |
|       1 |         4 |
|       2 |         2 |
|       2 |         4 |
|       3 |         2 |
|       3 |         3 |
+---------+-----------+
6 rows in set (0.00 sec)

mysql> select * from  book_m2m_author;
+---------+-----------+
| book_id | author_id |
+---------+-----------+
|       1 |         4 |
|       2 |         2 |
|       2 |         4 |
|       3 |         2 |
|       3 |         3 |
+---------+-----------+
5 rows in set (0.00 sec)
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息