sqlalchemy学习总结

1.
   from sqlalchemy import create_engine
  engine = create_engine('sqlite:///:memory:', echo=True)
链接mysql:   mysql_engine = create_engine('mysql://root:123456@localhost:3306/test?charset=utf8',encoding = "utf-8",echo =True)
      create_engine( ‘ 数据库 : //用户名 :  密码(没有密码则为空)@主机名: 端口/数据库名 ' , echo =True)


 engine.execute("select 1")    执行连接数据库,并显示sql操作语言
2.
  SQL操作
    from sqlalchemy import *
  定义表结构
   >>> users = Table('users', metadata,
...     Column('id', Integer, primary_key=True),  #主键
...     Column('name', String(50)),
... )


>>> addresses = Table('addresses', metadata,
...   Column('id', Integer, primary_key=True),
...   Column('user_id', None, ForeignKey('users.id')),   #外键
...   Column('email_address', String(50), nullable=False)
...  )
   metadata.create_all(engine)   #建表
3.
   插入数据  注意此时并没有执行插入数据
   ins = users.insert()    可以直接按顺序写('jim', '123')
    可以用values()来限制插入数据  ins = users.insert().values(name='jim')
   ins.compile().params   返回插入的值为字典形式{'name': 'jim'},只有用values()插入数据时,才可这样查询
4.
   执行
   conn = engine.connect()
   result = conn.execute(ins)   #此时才真向数据库中插入数据
  或者可以直接这样,不用values()
 ins = users.insert()
  conn.execute(ins, name='wendy')
下面这样,可以一次性的插入多条数据
>>> conn.execute(addresses.insert(), [
...    {'user_id': 1, 'email_address' : 'jack@yahoo.com'},
...    {'user_id': 2, 'email_address' : 'wendy@aol.com'},
... ])
5.
  查询
 s = select([users])   # users为Table()对象
result = conn.execute(s)
for row in result:
    print  row
row = result.fetchone()   迭代生成元组  注意不要和上面的连用,上面已经迭代完成,这里再用会报错
result.close() 关闭迭代
局部查询
s = select( [ users.c.name ,] )
result = conn.execute(s)   结果是只包含此列值的元组
条件查询
ins = select([users1]).where(users1.c.id==1)   注意后面是'=='双等号,且可以多重where选择
s = select([users, addresses]).where(users.c.id == addresses.c.user_id)
排序
stmt = select([users.c.name]).order_by(users.c.name)
conn.execute(stmt).fetchall()  列出全部,格式为字典,每行为一个元组
6.
修改数据
>>> stmt = users.update().values(name='aa')   将整列的数据改为‘aa’
stmt = users.update().\
...             where(users.c.name == 'jack').\
...             values(name='ed')    按条件查找后修改符合条件的数据
>>> conn.execute(stmt)
当要同时插入或修改多条数据时,用bindparam()来给类名起个key名,然后再每行对应的插入字典
>>> stmt = users.update().\
...             where(users.c.name == bindparam('oldname')).\
...             values(name=bindparam('newname'))
>>> conn.execute(stmt, [
...     {'oldname':'jack', 'newname':'ed'},
...     {'oldname':'wendy', 'newname':'mary'},
...     {'oldname':'jim', 'newname':'jake'},
...     ])
7.
  删除数据
conn.execute(addresses.delete())   清空表addresses
result = conn.execute(users.delete().where(users.c.name > 'm'))  删除满足条件的数据   注意先delete后where
8.
result.rowcount  得到操作影响的行数
2.
  >>> from sqlalchemy.ext.declarative import declarative_base
>>> Base = declarative_base()   建立基类
>>> from sqlalchemy import Column, Integer, String
>>> class User(Base):
...     __tablename__ = 'users'
...
...     id = Column(Integer, primary_key=True)
...     name = Column(String)       #此处是sqlite所以不用写数,mysql要写Column(String(50))
...     fullname = Column(String)
...     password = Column(String)
...
...     def __init__(self, name, fullname, password):    #__init__可以不定义,Base会自动执行,但传值时要用参数传值
...         self.name = name
...         self.fullname = fullname
...         self.password = password
...
...     def __repr__(self):                           #写不写无所谓
...        return "<User('%s','%s', '%s')>" % (self.name, self.fullname, self.password)
 Base.metadata.create_all(engine)  #建表


>>> ed_user = User('ed', 'Ed Jones', 'edspassword')  #实例化并传入值,注意此时User不自定义__init__也可执行,但要用参数传值(name='ed', fullname='Ed Jones', pa....),达到同样效果
>>> ed_user.name
'ed'
>>> ed_user.password
'edspassword'
>>> str(ed_user.id)    #因并没有将数据插入到数据库中,故id值为空
'None'
3.
a.
   >>> from sqlalchemy.orm import sessionmaker
>>> Session = sessionmaker(bind=engine)
创建Session并bind定engine
b.
session = Session()
c.
>>> ed_user = User('ed', 'Ed Jones', 'edspassword')
>>> session.add(ed_user)
d,
 our_user = session.query(User).filter_by(name='ed').first() #或者' .all() '在数据库中插入数据并查询出来,结果就是ed_user
4.
>>> session.add_all([
...     User('wendy', 'Wendy Williams', 'foobar'),
...     User('mary', 'Mary Contrary', 'xxg527'),
...     User('fred', 'Fred Flinstone', 'blah')])
同时加入多个值
ed_user.password = 'f8s7ccs' 改已经加如到session中的数据的值的话
session.dirty   会保存,更改的数据
session.new    会保存,新加入的数据
 session.commit()  执行所有更改
5.
  MySQL的session.rollback()貌似不管用
6.
session.query(User)可用以下三种方式访问
方式一for循环遍历,注意其本身可能是生成器但 不能用next() 等方法得到值。
        for instance in session.query(User).order_by(User.id):      当然也可以不接order_by等    order_by(desc(User.id))  倒序排列
                print instance.name
            for name, fullname in session.query(User.name, User.fullname):   也可以直接先制定列
                      print name, fullname
            for instance in session.query(User).filter_by(name='alen'):    按条件查找,
            for name, in session.query(User).filter(User.name=='Ed Jones').filter(User.fullname=='aa')  注意与filter_by区别,要加对象User.name, 是双等号'==',
            filter_by与filter都可以连着用,且可以混合使用
@@@filter很重要,有多个参数可选,查手册
        还可以直接用字符串:
              for user in session.query(User).\
...             filter("id<224").\
...             order_by("id").all():             order_by也可直接接受字符串,   order_by(desc('id'))   倒序排列
             session.query(User).filter("id<:value and name=:name").\          注意当时等于时,只有一个等号,而不是双等号,SQL语句中应该没有双等号
...     params(value=224, name='fred').order_by(User.id).one()    通过params来传入参数,动态控制筛选,之前的变量用‘ : key ’代替而不是‘%s’
         session.query(User).from_statement(             此函数可以直接接受SQL语句来查询
...                     "SELECT * FROM users where name=:name").\
...                     params(name='ed').all()
[<User('ed','Ed Jones', 'f8s7ccs')>]
方式二  session.query(User)[0].name
方式三jack = session.query(User).get(5)       get()中的值时primary_key既id的值,如果没有对象:不会报错
方式四session.query(User).all()    .one()   all得到的是个列表,one得到的是一个对象,并且如果多了或者没有会报错
7.
   qq = session.query(User).filter()      在filter里不写条件则筛选出所有的值的:一个对象
   qq.all()  返回一个列表,里面是所有删选出的对象
   qq.one() 返回对象必须是单一的,否则报错
   qq.first()  返回一个对象,且是列表的第一个值     可以用于查找是否存在,如果存在可直接用。如果不存在也不会报错
8.
    session.query(User).filter(User.name.like('%ed')).count()       count()方法返回行数
9.
    session.query(User).group_by(User.sex).all()   去除重复值,只返回无重复的第一次出现的数据对象
10.
    表间关系:
>>> from sqlalchemy import ForeignKey
>>> from sqlalchemy.orm import relationship, backref
    OneToMany和ManyToOne      :    ForeignKey在Many方,relationship在主表当中,如果加上backref=‘users’参数,可实现两表正反都有关系,一般要加。如果在从表中写relationship时要用 backref=backref('addresses', order_by=id)
    OneToOne :在relationship中加个参数uselist=False实现
    ManyToMany  要单独建一个表,来储存两个id。本笔记最后详细记载步骤
  手册:http://docs.sqlalchemy.org/en/rel_0_8/orm/relationships.html#relationship-patterns
11.
插入数据
a.
>>> jack = User('jack', 'Jack Bean', 'gjffdd')
>>> jack.addresses
[]                       一开始为空
b.
>>> jack.addresses = [
...                 Address(email_address='jack@google.com'),
...                 Address(email_address='j25@yahoo.com')]
赋值
当主表为One时,此属性为列表,向上述一样赋值
当主表为Many是,此属性为一个对象    jack.addresses = Address(.....)  直接赋值,不是列表
c.
>>> session.add(jack)
>>> session.commit()       此时不仅users表插入数据,address表也插入了数据
12.
表间查询
>>> jack = session.query(User).\
... filter_by(name='jack').one()
jack.address为列表  可以随意查询 jack.address[0].email
jack.address.append( Address('11') )   #用append来添加对象
逆向查询时,如果address为一个数据对象,address.user 可查到user的单一数据对象
13.
session.query(User, Address).\
...                     filter(User.id==Address.user_id).\
...                     filter(Address.email_address=='jack@google.com').\
...                     all():
可以用join来简单的实现
>>> session.query(User).join(Address).\
...         filter(Address.email_address=='jack@google.com').\
...         all()
14
func.count()   查询数量的函数
15.
http://docs.sqlalchemy.org/en/rel_0_8/orm/tutorial.html#common-relationship-operators
16.
session.delete(jack)   删除数据,但此时从表的数据不会被删除
addresses = relationship("Address", backref='user', cascade="all, delete, delete-orphan")   设置表间关系时,加上cascade参数,后从表数据会随着主表数据删除而删除
del jack.addresses[1]    这样也能从主表删除从表数据了
17.
实现ManyToMany
a.
>>> from sqlalchemy import Table, Text
>>> # association table
>>> post_keywords = Table('post_keywords', Base.metadata,
...     Column('post_id', Integer, ForeignKey('posts.id')),
...     Column('keyword_id', Integer, ForeignKey('keywords.id'))
... )                    #建一张表用来储存两表关系
b.
keywords = relationship('Keyword', secondary=post_keywords, backref='posts')       relationship加个参数secondary
c.
>>> post = BlogPost("Wendy's Blog Post", "This is a test")   主表数据
>>> session.add(post)   加入session
d.
>>> post . keywords . append( Keyword('wendy') )             从主表索引然后添加从表数据
e.
session.query(BlogPost).\
...             filter(BlogPost.keywords.any(keyword='firstpost')).\
...             all()            执行插入数据,并查询
18.
   当session.query(User).get(1)时出现了异常时 TypeError: 'str' object is not callable
    很可能是__repr__函数里出错
19.
  加参数cascade实现级联删除时,如果relationship在Many一方时,还要加参数single_parent=True
   ArgumentError: On Reply.user, delete-orphan cascade is not supported on a many-to-many or many-to-one relationship when single_parent is not set.   Set single_parent=True on the relationship().
20.
    reply = relationship('Reply', backref='note', cascade='all, delete, dele    te-orphan', order_by=desc('id'))     在relationship中也有参数order_by,加上desc后可实现倒序排列。当然在 backref=backref('note',  order_by='')  中也有order_by
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值