sqlachamel

数据库

ORM

ORM全称 Object Relational Mapping对象关系映射

通过 ORM 可以不用关心后台是使用的哪种数据库,只需要按照 ORM 所提供的语法规则去书写相应的代码, ORM 就会自动的转换成对应对应数据库的 SQL 语句

SQLAlchemy

安装: mysql

安装python包: pymysql、sqlalchemy

pip install -i https://pypi.douban.com/simple pymysql

pip install -i https://pypi.douban.com/simple sqlalchemy

1 连接数据库(connect.py)


from sqlalchemy import create_engine  # 连接数据库的方法

HOSTNAME = '127.0.0.1' 

PORT = '3306' 

DATABASE = 'mydb' 

USERNAME = 'admin' 

PASSWORD = 'Root110qwe'

Db_Uri = 'mysql+pymysql://{}:{}@{}/{}?charset=utf8'.format(

USERNAME,PASSWORD,HOSTNAME,DATABASE)  # 连接数据库的uri

# mysql+pymysql://{用户名}:{密码}@{host}:{port}/{数据库}?charset=utf8

engine = create_engine(Db_Uri)  # 连接数据库



if __name__=='__main__': 

connection = engine.connect() # 类似与pymysql中的定义游标

result = connection.execute('select 1') print(result.fetchone())

```

2 数据库建模<br>

对象关系型映射,数据库中的表与python中的类相对应<br>

在connect.py生成一个基类

```python

"""

在connet.py文件里面

"""

from sqlalchemy.ext.declarative import declarative_base 

Base = declarative_base(engine)  # 生成Base类 用于建模

```

建模(modules.py)

```python

from connect import Base

from sqlalchemy import Column, Integer, String, DateTime

# __tablename__ 表名

# Column 创建字段

# Interger  数据库中的int

# String  字符串类型

# DateTime 时间类型

# Boolean 布尔型

calss User(Base):

    """

    建立表模型,相当于在数据库中建立一张表

    注意:必须继承在connet.py文件里面生成的Base类



    字段名 = Column(数据类型, 约束条件)

    """

    __tablename__ = "user"  

    id = Column(Interger, primary_key=True, autoincrement=True)

    username = Column(String(10))

    password = Column(String(20))



    def __repr__(self):

        result = "<User(id={id}, username={username}, password={password})>".format(id=self.id, username=self.username, password=self.password)

if __name__ = "__nmain__"

    Base.metadata.create_all()  # 创建表

```

3 sqlalchemy对数据库的增删查改<br>

在connect.py文件里添加以下代码

```python

from sqlalchemy.orm import sessionmaker

Session = sessionmaker(engine)

session = Session()  # 生成会话类,用于操纵数据

```

数据增删改查(test_user.py)

```python

from connect import session

from modules import User

def add_user():

    """

    添加数据 add()  add_all([])

    默认开启事务



    session.add(要添加的数据)  # 添加一条数据

    session.commit()  # 提交事务

    session.add_all(要添加数据的列表)

    session.commit()

    """

    person = User(username='XXX', password='****') 

    session.add(person)  # 添加一条数据

    session.add_all(

    [

        User(username='XXX', password='***'),

        User(username='XXX', password='***'),

    ]) # 添加多条数据

    session.commit()  # 提交事务



def query_user():

    """

    查看数据query()

    session.query(表模型)

    """

    result = session.query(User).all()  # 查看所有数据,

    # 返回的是对象,重写User的__repr__方法重构输出内容

    print(result)

    result = session.query(User).first()  # 查看第一条数据

def update_user():

    """

    更新数据 update({})

    filter(条件) 返回一个序列类型对象。本身为原生sql语句



    session.query(表模型).filter(条件).update(修改数据[字典格式])

    session.commit()

    """

    session.query(User).filter(User.username=="XXX").update({User.username: 'xxx'})

    session.commit()

def delete_user():

    """

    删除数据 delete()

    result = session.query(表模型).fiter(条件)[第几条数据]

    session.delete(result)

    session.commit()

    """

    result = session.query(User).filter(User.username=="XXX").first()

    session.delete(result)

    session.commit()

if __name__ == "__main__":

    add_user()

```

## 查询精讲

1 结果查询<br>

[1] 整表查询<br>

i) 查看所有数据<br>

```python

session.query(表模型).all()

```

ii) 查看第一条数据<br>

```python

1. session.query(表模型).first()

2. session.query(表模型)[0] 

```

iii) 两种方式可以取到具体的数据值

```python

1. getattr(rs[第几条数据], 'username')

2. rs[第几条数据].username 

```

[2] 查询某个表的字段<br>

i) 查看所有数据<br>

```python

session.query(表模型.字段).all()

```

ii) 查看第一条数据<br>

```python

1. session.query(表模型.字段).first()

2. session.query(表模型.字段)[0]

```

2 条件查询

[1] 过滤函数 <br>

i) filter 

```python

session.query(表模型).filter(条件1, 条件2)

session.query(User).filter(User.username=='budong').all()

```

filter 是一个过滤函数,过滤条件都可以书写在此函数中,不同的条件之间用 逗号 分隔

ii) filter_by <br>

```python

session.query(表模型).filter_by(条件)

# 例如:session.query(User).filter_by(username='budong').all()

```

filter 和 filter_by 过滤函数,但是使用有如下差别:

1. filter 中需要添加 类对象,filter_by不需要

2. filter_by 中只能添加等于的条件,不能添加 不等于、大于小于等条件,filter没有这个限制

[2] 模糊查询 [在filter里面使用] <br>

i) like 和 notlike <br>

例如:<br>

```python

session.query(User).filter(User.username.like('杜%'))

session.query(User).filter(User.username.notlike('杜%'))

```

ii) is_ 和 isnot <br>

例如:<br>

```python

session.query(User).filter(User.username.is_(None))<br>

session.query(User).filter(User.username.isnot(None))

```

iii) in_  和 notin

例如:<br>

```python

session.query(User).filter(User.username.in_(['XXX', 'xxx']))<br>

session.query(User).filter(User.username.notin(['XXX', 'xxx']))

```

[3] 查询结果数<br>

i) 限制查看几条数据 limit<br>

```python

session.query(表模型).limit(限制查看数)

```

ii) 偏移几条数据查看 offset<br>

```python

session.query(表模型).offset(偏移量)

```

iii) 从左下标开始查看(右下标-左下标)个数据 slice<br>

```python

session.query(表模型).slice(左下标, 右下标)

```

iv) 查一条数据 one<br>

```python

session.query(表模型).filter(条件).one()

# <br>注意: 只能查看一条数据,如果有多条数据,报错

```

[4] 排序 order_by<br>

```python

session.query(表模型).order_by(用于排序的字段)

# 例如

session.query(User).order_by(User.id)

'''注意: order_by默认排序为顺序排列'''

# 倒序排列:

from sqlalchemy import desc<br>

session.query(User).order_by(desc(User.id)).all() <br>

"""注意:倒序排列时要导入 desc 才能使用"""

```

[5] 函数<br>

==**注意:**== 使用函数是必须先导入函数

```python

from sqlalchemy import func

```

i) func.count()  统计相同值出现的次数<br> group_by() 分组 <br> having()

```python

session.query(表模型.字段名,func.count(表模型.被统计字段)).group_by(表模型.字段名).all()

"""

注意:

如果查询的什么字段,那么分组的也必须为被查询字段

"""

session.query(表模型.字段名,func.count(表模型.被统计字段)).group_by(表模型.字段).having(条件).all()

```

ii) func.min() 求最小值<br>

```python

session.query(User.password, func.min(User.id)).group_by(User.password).all()

"""

查询usr表里面的password并按照password分组,在找出每个分组中id的最小值

"""

```

iii) func.max() 求最大值<br>

```python

session.query(User.password, func.max(User.id)).group_by(User.password).all()

"""

查询usr表里面的password并按照password分组,在找出每个分组中id的最大值

"""

```

iv) func.sum() 求和 <br>

```python

session.query(User.password, func.sum(User.id)).group_by(User.password).all()

"""

查询usr表里面的password并按照password分组,再对每个分组中的id求和

"""

```

v) extract 提取<br> label 取别名

```python

from sqlalchemy import extract  # 注意使用时要导入

session.query(extract('minute',User.creatime).label('minute'), func.count(User.id)).group_by('minute').all()

```

[6] 选择条件<br>

```python

from sqlalchemy import or_ 

session.query(User.username).filter(or_(User.username.isnot(None), User.password=='qwe123')).all()

"""

查询出user表中username不为空的或者password为‘qwe123’的数据

"""

```

[7] 多表查询

i) 笛卡尔链接(cross join)<br>

例如:

```python

session.query(UserDetails, User).filter(UserDetails.id==User.id).all()

"""

查询出user_details表与user表中id相等的数据

"""

```

ii) 内连接(inner join)<br>

例如:

```python

session.query(User.username, UserDetails.lost_login).join(UserDetails,UserDetails.id==User.id)

```

iii) 外连接(outerjoin)<br>

```python

session.query(User.username,UserDetails.lost_login).outerjoin(UserDetails,UserDetails.id==User.id)

# 通过上面打印的  SQL 来看, 上面这种方式采用的是left join

```

iv) union

```python

q1 = session.query(User.id)

q2 = session.query(UserDetails.id)

q1.union(q2).all()

"""

去重

"""

```

iv) 子查询

```python

sql_0 = session.query(UserDetails).subquery() # subquery 声明子表

session.query(User, sql_0.c.lost_login).all()

```

3 表关系<br>

i) 一对一<br>

relationship("被关联的表模型", backref="在被关联表中添加一个属性", uselist="默认一对多[True] 一对一[False]", cascade='自动处理关系[常用"all"]')

在user_modules中进行如下修改<br>

```python

# 导入

from sqlalchemy.orm import relationship

# 在 UserDetails 中添加如下代码:

userdetail = relationship('User',backref='details',uselist=False,cascade='all')

```

查询

```python

from connect import session

from user_modules import User

from user_modules import UserDetails

rs = session.query(UserDetails).get(2)

print(rs)

print(rs.userdetail)

rs = session.query(User).get(2)

print(rs)

print(rs.details)

```

ii) 多对多<br>

relationship('表模型', backref='在被关联表模型中添加属性', secondary=中间表表名)

创建中间表

```python

# 首先导入Table用于创建中间表

from sqlalchemy import Table

# 中间表

user_article = Table('user_article', Base.metadata, 

                    Column('user_id', Integer, ForeignKey('user.id'), primary_key=True),

                    Column('article_id', Integer, ForeignKey('article.id'), primary_key=True)  # 联合主键

                    )

class Article(Base):

    __tablename__ = 'article'

    id = Column(Integer, primary_key=True, autoincrement=True)

    content = Column(String(500), nullable=True)

    create_time = Column(DateTime, default=datetime.now)



    article_user = relationship('User', backref='article', secondary=user_article)  # 表关系 多对多



    def __repr__(self):

        return 'Article(id=%s, content=%s, creat_time=%s)' % (self.id,

                                                              self.content,

                                                              self.create_time

                                                              )

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

推荐阅读更多精彩内容