python与数据库的交互-sqlalchemy

导读:
orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的,为了保证一致的使用习惯,通过orm将编程语言的对象模型和数据库的关系模型建立映射关系,这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型进行操作就可以了,而不用直接使用sql语言。
2.ORM的优点和缺点
orm的优点:
隐藏了数据访问细节,“封闭”的通用数据库交互,ORM的核心。他使得我们的通用数据库交互变得简单易行,并且完全不用考虑该死的SQL语句。快速开发,由此而来。
ORM使我们构造固化数据结构变得简单易行。
缺点:
无可避免的,自动化意味着映射和关联管理,代价是牺牲性能(早期,这是所有不喜欢ORM人的共同点)。现在的各种ORM框架都在尝试使用各种方法来减轻这块(LazyLoad,Cache),效果还是很显著的。
<在python中最著名的ORM是SQLAlchemy>
------------------------------------------------常用代码------------------------

from sqlalchemy import Column, String, create_engine,Integer,func ,ForeignKey,DATE,Table
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from  sqlalchemy .orm import  sessionmaker   #创建绘画
from  sqlalchemy .orm import  relationship   #实现反向查找

# 初始化数据库连接:
engine = create_engine('mysql+pymysql://root:123456@localhost:3308/szldb?charset=utf8',encoding='utf-8') # echo=True 打印所有信息
# 创建DBSession
DBSession = sessionmaker(bind=engine) 
Base=declarative_base()  #创建基类
Session_class= sessionmaker(bind=engine)  #创建于数据库的会话sessionclass
Session=Session_class()   #生成session实例 cursor

(一)数据库的连接
连接mysql
'mysql+pymysql://root:123456@localhost:3308/szldb?charset=utf8',encoding='utf-8',echo=True
连接oracle
oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
(数据库类型+基础包+账号+密码+主机+端口+编码方式,字符编码方式,是否显示创建细节)
(一)数据库的连接创建表的结构

from sqlalchemy import  create_engine,Table, String,ForeignKey,Integer,DATE
from sqlalchemy.ext.declarative import declarative_base
#①基本表的创建方式一
engine = create_engine('mysql+pymysql://root:123456@localhost:3308/szldb?charset=utf8',encoding='utf-8') # echo=True 打印所有信息
DBSession = sessionmaker(bind=engine)
Base=declarative_base()  #创建基类
class User(Base):
    __tablename__ = 'user'  # 表名
    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    password = Column(String(64))
    def __repr__(self): #返回打印显示的列
        return "<%s name: %s>" % (self.id,self.name)
#②基本表的创建方式二
from sqlalchemy import Table, MetaData, Column, Integer, String, ForeignKey
from sqlalchemy.orm import mapper
 
metadata = MetaData()
 #设置表结构
user = Table('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
mapper(User, user) 

③插入数据

Session_class = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
Session = Session_class() #生成session实例

user_obj = User(name="alex",password="alex3714") #生成你要创建的数据对象
#print(user_obj.name,user_obj.id)  #此时还没创建对象呢,不信你打印一下id发现还是None
 
Session.add(user_obj) #把要创建的数据对象添加到这个session里, 一会统一创建
#print(user_obj.name,user_obj.id) #此时也依然还没创建
 Session.commit() #现此才统一提交,创建数据

④查询数据-基本查询

data=Session.query(User).filter_by(name='alex').all() #把所有数据取成列表
data=Session.query(User).filter_by(name='alex').first() #取首行数据
    #条件查询
data=Session.query(User).filter(User.id==2).all() #条件等于
data=Session.query(User).filter(User.id>2).all() #条件大于
    #多条件查询
data=Session.query(User).filter(User.id>2).filter(User.id<4).all() #条件大于
data=Session.query(User).filter(User.id>2).filter(User.id<4).first() #
data.name="zhangsan"
data.password="123"
   #统计和分组
data=Session.query(User).filter(User.name.like("al%")).count() #对符合条件的记录进行计数
print(data)
print(Session.query(func.count(User.name),User.name).group_by(User.name).all() ) #对数据进行分组
    #数据的修改1
data=Session.query(User).filter(User.id>2).filter(User.id<4).first()
print("change",data) #打印修改后的数据
Session.rollback() #回滚操作
print("rollback",data) #打印修改后的数据
Session.commit()

⑤查询数据-联表查询

ret=Session.query(User,Student).filter(User.name==Student.name).all()
ret=Session.query(User).join(Student).all()  #两个表有外键关联的时候才能采用
print(ret)

⑥外键和反向查询

#创建Student表
class Student(Base):
    __tablename__ = 'Student'  # 表名
    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    register_date=Column(DATE,nullable=False)
    def __repr__(self):
        return "<%s age: %s>" % (self.name,self.register_date)
#创建StudyRecord表
class StudyRecord(Base):
    __tablename__ = 'StudyRecord'  # 表名
    id = Column(Integer, primary_key=True)
    day = Column(Integer,nullable=False)
    status = Column(String(64),nullable=False)
    stu_id=Column(Integer,ForeignKey('Student.id'))
    # student=query(Student).filter(Student.id==stu_obj.stuid).first()
    student=relationship("Student",backref="mystudy_record") #这nb允许两张表相互调用反向查找,存在于内存对象中
    def __repr__(self):
        return "<day:%s status: %s>" % (self.day,self.status)

⑦数据表的一对多(一个客户有不同账单地址和收货地址)

class Customer(Base):
    __tablename__ = 'customer'
    id = Column(Integer, primary_key=True)
    name = Column(String(64))
    billing_address_id = Column(Integer, ForeignKey("address.id"))
    shipping_address_id = Column(Integer, ForeignKey("address.id"))
    billing_address = relationship("Address", foreign_keys=[billing_address_id])#用不同的关联名称
    shipping_address = relationship("Address", foreign_keys=[shipping_address_id])#创建的关系只存在于内存对象不会写入数据库
class Address(Base):
    __tablename__ = 'address'
    id = Column(Integer, primary_key=True)
    street = Column(String(64))
    city = Column(String(64))
    state = Column(String(64))
    def __repr__(self):
        return "<street:%s" % (self.street)

⑧多对多

book_m2m_author = Table('book_m2m_author', Base.metadata,
                        Column('book_id',Integer,ForeignKey('books.id')),
                        Column('author_id',Integer,ForeignKey('authors.id')),
                        )
class Author(Base):
    __tablename__ = 'author'
    id = Column(Integer, primary_key=True)
    name = Column(String(40))
    def __repr__(self):
        return self.name

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

推荐阅读更多精彩内容