python操作关系型数据库 --sqlalchemy(一)

最近看了很多这类型的文章,想要自己总结下,顺便补下数据库的知识..数据库学的太烂了。


1.创建数据库和表


1.第一种方式

# 同时,创建数据库和表
engine = create_engine('sqlite:///test.db', echo=True)

metadata = MetaData(engine)
Base = declarative_base()


# 第一种方式:使用类来创建一个表
# 同时,创建数据库和表,echo显示sql语句
engine = create_engine('sqlite:///test.db', echo=True)

metadata = MetaData(engine)
Base = declarative_base()


# 第一种方式:使用类来创建一个表
class User(Base):
    # 表的名称
    __tablename__ = 'users'
    id = Column(Integer(), primary_key=True)
    username = Column(String(20), nullable=True, index=True)
    password = Column(String(20), nullable=True)


# 创建
Base.metadata.create_all(engine)

第二方式,使用Table

engine = create_engine('sqlite:///test.db', echo=True)

metadata = MetaData(engine)
# 第二种方式
article_table = Table('article', metadata,
                      Column('title', String(30), primary_key=True),
                      Column('content', Text),
                      )
# 创建
metadata.create_all()

创建一个会话


from sqlalchemy.orm import sessionmaker
Sessoin = sessionmaker(bind=engine)
sessoin = Sessoin()

添加操作


添加一条数据,提交

user_1 = User(username='user_1', password='user_1')
# sessoin.add(user_1)

添加多条数据,提交

user_2 = User(username='user_2', password='user_2')
user_3 = User(username='user_3', password='user_3')
# sessoin.add_all([user_2, user_3])
# sessoin.commit()

2.查找操作


查找某个表中的全部数据

select_all = sessoin.query(User).all()
print(select_all)

查找某个表中的第一条数据,某一列

# 查找表中的第一条数据
select_first = sessoin.query(User).first()
# 查找第一条数据的username那一列
select_first_username=sessoin.query(User.username).first()
print(select_first)

使用filter,filter_by查找的时候筛选数据

# 查找的时候筛选数据,配合all 或者 first
select_filterby = sessoin.query(User.password).filter_by(username='user_1').all()
# print(select_filterby)
# filter和filter_by很像,前者用于简单查询,注意到使用filter查询时,需要添加对象名,要不然会报错,
# 后者用于复杂查询
# equals
select_filter_eq = sessoin.query(User).filter(User.username == 'user_1').all()
# not equals
select_filter_nq = sessoin.query(User).filter(User.username != 'user_1')
# more than
select_filter_gt = sessoin.query(User).filter(User.id > 5).all()
# less than
select_filter_lt = sessoin.query(User).filter(User.id < 5).all()
# like
select_filter_like = sessoin.query(User).filter(User.username.like('u%'))
# in
select_filter_in = sessoin.query(User).filter(User.username.in_(['user_1', 'user_2']))
print(select_filter_in)
# not in
 select_filter_not_in = sessoin.query(User).filter(~User.id.in_([2, 3]))
print(select_filter_not_in)
# print(select_filter_eq)
# is null
select_filter_null = sessoin.query(User).filter(User.username._is_(None))
# and
from sqlalchemy import and_

sessoin.query(User).filter(and_(User.id == 1, User.username == 'user_1'))
sessoin.query(User).filter(User.id == 1).filter(User.username == 'user_1')

# or
from sqlalchemy import or_

sessoin.query(User).filter(or_(User.id == 1, User.username == 'user_1'))
# match
sessoin.query(User).filter(User.username.match('user_1'))

使用text,配合filter,filter_by

 # 使用text,配合filter,filter_by
from sqlalchemy import text
 sessoin.query(User).filter(text("id>2")).order_by(text('id')).all()
# 使用params,添加参数
 sessoin.query(User).filter(text('id >2 and  name=:name').params(name='user_1'))

使用 statement,配合text执行原生的sql语句

# 使用from_statement执行原生的sql语句
sessoin.query(User).from_statement(text("select * from users"))
# 同样使用params,添加参数
sessoin.query(User).from_statement(text("select * from users where name=:name").params(name='user_1'))

使用count统计数量

# 统计username='user_1'的数量
b = sessoin.query(User).filter(User.username == 'user_1').count()
print(b)
# 统计某些组的个数,使用func.count()
# [(1, 'Brian Johnson'), (1, 'Charles Barber'), (1, 'Kathryn Walker'), (1, 'Margaret
# Fox'), (1, 'Marie Reyes'), (1, 'Michael Nichols'), (1, 'Mrs. Karen Delacruz'), (1, 'Randy Wallace'), (1,
# 'Teresa Cochran'), (1, 'Tyler Smith'), (2, 'user_1'), (3, 'user_2'), (4, 'user_3')]
from sqlalchemy import func
print(sessoin.query(func.count(User.username), User.username).group_by(User.username).all())
# 如果统计有多少行,需要用select_from 选定一个表
d = sessoin.query(func.count('*')).select_from(User).scalar()
# d ==19
print(d)
# 统计某一列的数量,则不需要
print(sessoin.query(func.count(User.username)).scalar())

关联查询,join

# 关联查询
# User 和article是一对多的关系
# 这里是差找每一个user所拥有的article
for u, a in sessoin.query(User, Article).filter(User.id == Article.user_id).all():
print(u, a.title)
# 也可以使用join
sessoin.query(User).join(Article).filter(User.id == Article.user_id).all()
# 搜索有发表article的user。
sessoin.query(User).join(Article, Article.user_id == User.id).all()

3.删除操作


# 删除数据前,先找到具体要删除的数据
delete_data = sessoin.query(User).filter_by(username='user_1').first()
sessoin.delete(delete_data)
#sessoin.commit()

4.修改数据


# 需要数据一般是把数据找出来,在修改字段提交
select_filterby = sessoin.query(User).filter_by(username='user_1').first()
select_filterby.password = '123'
sessoin.commit()

完整代码

from sqlalchemy import create_engine, Text, ForeignKey, Column, String, Integer, Table, MetaData
from faker import Factory
# 连接,创建

# sqlite3
from sqlalchemy.orm import relationship, sessionmaker

engine = create_engine('sqlite:///data.sqlite')
print(engine)

# 使用orm
from sqlalchemy.ext.declarative import declarative_base

"""
 ----1---- 
"""
# 基类
Base = declarative_base()


# 设计表的结构
class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    username = Column(String(64), nullable=False)
    password = Column(String(64), nullable=False, index=True)
    articles = relationship('Article', backref='author')
    # 一对一关系,加上userlist=False
    userinfo = relationship('UserInfo', backref='user', uselist=False)

    def __repr__(self):
        return f'{self.username}'


class UserInfo(Base):
    __tablename__ = 'userinfos'
    id = Column(Integer, primary_key=True)
    name = Column(String(64))
    qq = Column(String(11))
    phone = Column(String(11))
    link = Column(String(64))
    user_id = Column(Integer, ForeignKey('users.id'))


class Article(Base):
    __tablename__ = 'articles'

    id = Column(Integer, primary_key=True)
    title = Column(String(255), nullable=False, index=True)
    content = Column(Text)
    user_id = Column(Integer, ForeignKey('users.id'))
    tags = relationship('Tag', secondary='article_tag', backref='articles')

    # author = relationship('User')

    def __repr__(self):
        return '%s' % self.__class__.__name__


class Tag(Base):
    __tablename__ = 'tags'

    id = Column(Integer, primary_key=True)
    name = Column(String(64), nullable=False, index=True)

    def __repr__(self):
        return self.__class__.__name__


# 多对多关系,需要分解成两个一对多关系。
article_tag = Table(
    'article_tag', Base.metadata,
    Column('article_id', Integer, ForeignKey('articles.id')),
    Column('tag_id', Integer, ForeignKey('tags.id'))
)

"""
----2----
"""

# 绑定引擎
# metadata = MetaData(engine)
# 删除表
# metadata.drop_all()
# 设置表的结构
"""
user_table = Table('users', metadata,
                   Column('id', Integer, primary_key=True),
                   Column('username', String(64), nullable=False),
                   Column('password', String(64), nullable=False, index=True),
                   )
articles = relationship('article_table')
article_table = Table('articles', metadata,
                      Column('title', String(255), primary_key=True),
                      Column("content", Text),
                      Column('user_id', Integer, ForeignKey('users.id')),
                      )
author = relationship('user_table')
"""

# 创建表
# metadata.create_all()

# 连接表
# autoload_with:指定引擎
# u = Table('user', metadata, autoload=True)
# print(dir(u))


if __name__ == '__main__':
    # 创建表
    # Base.metadata.create_all(engine)
    # 创建一个会话
    # faker = Factory.create()
    Sessoin = sessionmaker(bind=engine)
    sessoin = Sessoin()
    # faker_users = [
    #    User(username=faker.name(),
    #         password=faker.word(),
    #         ) for i in range(10)]
    # sessoin.add_all(faker_users)

    # faker_tags = [Tag(name=faker.word()) for i in range(5)]
    # sessoin.add_all(faker_tags)

    # for i in range(100):
    #    article = Article(
    #        title=faker.sentence(),
    #        content=faker.sentence(),
    #        author=random.choice(faker_users)
    #    )
    #    for tag in random.sample(faker_tags, random.randint(2, 5)):
    #        article.tags.append(tag)
    #    sessoin.add(article)
    # sessoin.commit()

    # 添加一条操作
    # user_1 = User(username='user_1', password='user_1')
    # sessoin.add(user_1)
    # 添加多条数据
    # user_2 = User(username='user_2', password='user_2')
    # user_3 = User(username='user_3', password='user_3')
    # sessoin.add_all([user_2, user_3])
    # sessoin.commit()
    # 查找某个表中的全部数据
    select_all = sessoin.query(User).all()
    # print(select_all)
    # 查找表中的一条数据
    select_first = sessoin.query(User).first()
    # print(select_first)
    # 查找的时候筛选数据,配合all 或者 first
    select_filterby = sessoin.query(User.password).filter_by(username='user_1')
    # print(select_filterby)
    # filter和filter_by很像,前者用于简单查询,注意到使用filter查询时,需要添加对象名,要不然会报错,
    # 后者用于复杂查询
    # equals
    select_filter_eq = sessoin.query(User).filter(User.username == 'user_1')
    # not equals
    select_filter_nq = sessoin.query(User).filter(User.username != 'user_1')
    # more than
    select_filter_gt = sessoin.query(User).filter(User.id > 5).all()
    # less than
    select_filter_lt = sessoin.query(User).filter(User.id < 5).all()
    # like
    select_filter_like = sessoin.query(User).filter(User.username.like('u%'))
    # in
    select_filter_in = sessoin.query(User).filter(User.username.in_(['user_1', 'user_2']))
    # not in
    select_filter_not_in = sessoin.query(User).filter(~User.id.in_([2, 3]))
    from sqlalchemy.orm.exc import MultipleResultsFound
    # print(sessoin.query(User.id).filter(User.username == 'user_1').order_by(User.id).one())

    # print(select_filter_eq)
    # and
    from sqlalchemy import and_

    sessoin.query(User).filter(and_(User.id == 1, User.username == 'user_1'))
    sessoin.query(User).filter(User.id == 1).filter(User.username == 'user_1')

    # or
    from sqlalchemy import or_

    sessoin.query(User).filter(or_(User.id == 1, User.username == 'user_1'))
    # match
    sessoin.query(User).filter(User.username.match('user_1'))

    # 使用text,配合filter,filter_by
    from sqlalchemy import text

    sessoin.query(User).filter(text("id>2")).order_by(text('id')).all()
    # 使用params,添加参数
    sessoin.query(User).filter(text('id >2 and  name=:name').params(name='user_1'))
    # 使用from_statement执行原生的sql语句
    sessoin.query(User).from_statement(text("select * from users"))
    # 同样使用params,添加参数
    sessoin.query(User).from_statement(text("select * from users where name=:name").params(name='user_1'))

    # 统计username='user_1'的数量
    b = sessoin.query(User).filter(User.username == 'user_1').count()
    print(b)
    # 统计某些组的个数,使用func.count()
    # [(1, 'Brian Johnson'), (1, 'Charles Barber'), (1, 'Kathryn Walker'), (1, 'Margaret
    # Fox'), (1, 'Marie Reyes'), (1, 'Michael Nichols'), (1, 'Mrs. Karen Delacruz'), (1, 'Randy Wallace'), (1,
    # 'Teresa Cochran'), (1, 'Tyler Smith'), (2, 'user_1'), (3, 'user_2'), (4, 'user_3')]
    from sqlalchemy import func

    print(sessoin.query(func.count(User.username), User.username).group_by(User.username).all())
    # 如果统计有多少行,需要用select_from 选定一个表
    d = sessoin.query(func.count('*')).select_from(User).scalar()
    # d ==19
    print(d)
    # 统计某一列的数量,则不需要
    print(sessoin.query(func.count(User.username)).scalar())

    # 关联查询
    # User 和article是一对多的关系
    # 这里是差找每一个user所拥有的article
    for u, a in sessoin.query(User, Article).filter(User.id == Article.user_id).all():
        print(u, a.title)
    # 也可以使用join
    sessoin.query(User).join(Article).filter(User.id == Article.user_id).all()
    # 搜索有发表article的user。
    sessoin.query(User).join(Article, Article.user_id == User.id).all()
    # 删除数据前,先找到具体要删除的数据
    # delete_data = sessoin.query(User).filter_by(username='user_1').first()
    # sessoin.delete(delete_data)
    # sessoin.commit()

    # 需要数据一般是把数据找出来,在修改字段提交
    # select_filterby = sessoin.query(User).filter_by(username='user_1').first()
    # select_filterby.password = '123'
    # sessoin.commit()
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容