@zhengyuhong
2015-06-05T10:07:15.000000Z
字数 5999
阅读 2702
db MySQL SQLAlchemy
SQLAlchemy的依赖项:MySQLdb(又叫mysql-python)
如果安装过程中出现如下错误
raise EnvironmentError("%s not found" % (mysql_config.path,))
#原因是没有安装:libmysqlclient-devsudo apt-get install libmysqlclient-devsudo updatedblocate mysql_config
from sqlalchemy import create_engineengine = create_engine('mysql://user:passwd@host/db')#passwd是数据库db的授权口令,非用户密码
create_engine使用MySQLdb(mysql-python)作为连接MySQL的默认API,可以指定其他,如MySQL-connector-python(MySQL官方API),OurSQL, 显式指定方式如下:
# defaultengine = create_engine('mysql://user:passwd@host/db')# mysql-pythonengine = create_engine('mysql+mysqldb://user:passwd@host/db')# MySQL-connector-pythonengine = create_engine('mysql+mysqlconnector://user:passwd@host/db')# OurSQLengine = create_engine('mysql+oursql://user:passwd@host/db')
连接上数据库之后,可以使用连接引擎直接用SQL语句操作数据库:
#假如在MySQL中的zhengyuhongDB数据库已有表student,列为id,name,scorecmd = 'SELECT * from student where id = 0'ret = e.execute(cmd)for r in ret:print r ## 输出id为0的行
如果需要执行数据库事务时,如下:
conn = e.connect()conn.begin()# 执行数据库事务try:conn.commit() #except:conn.rollback()
from sqlalchemy import Table, MetaData,Column,Integer,String, textmeta = MetaData(bind=e, reflect=True)#meta是连接的数据库的元信息,print一下就可以看到print meta.tables #可以查看到连接的数据库的表以及表的列属性#使用已有的表student = meta.tables['student'] #或者student = Table('student', metadata, autoload=True)#创建新表teacher = Table('teacher',meta,Column('teacher_id',Integer,primary_key=True),Column('name',String),Column('salary',Integer))
print student.columns ##输出表的列名s = student.select(whereclause=None, **params)s = student.select(student.id == 0)
s = stduent.delete(whereclause=None, **kwargs)
s = student.insert(values=None, inline=False, **kwargs)s = student.insert(('3','Kim','99'))s = student.insert(('3','Kim'))s = student.insert().values(id='3', score='96')
s = student.update(whereclause=None, values=None, inline=False, **kwargs)s = student.update().where(student.c.id==7).values(name='Seven')
s = student.join(right, onclause=None, isouter=False)
s = student.select().having(text('student.c.id > 2')) ##仅仅举例having用法,在SQL在应该与group by 结合,having用在组,where用在行#均是返回一个SQL语句类,括号里面就是语句的参数条件,再执行s.execute(),每一条语句执行一次,再如下就是一个查询例子
for r in student.select(student.id == 0).execute():print r
from sqlalchemy import select,insert,update,delete,and_,or_,not_,in_select(columns=None, whereclause=None, from_obj=None, distinct=False, having=None, correlate=True, prefixes=None, suffixes=None, **kwargs)s = select([student]) ##全部选定s = select([student.c.id, student.c.name],()) ##部分选定s = select([student,teacher]) ##两个表s = select([student.c.id,teacher.c.name]) ## 两个表部分选定,多个表同理s = select([product_a.c.price,product_b.c.price])s = select([tableOne, tableTwo], tableOne.c.id==tableTwo.c.user_id)s = select([users_table], users_table.c.id > 3)s = select(and_(users_table.c.name=="Martha", users_table.c.age < 25))s = select([student]).order_by(student.c.id)
insert(table, values=None, inline=False, bind=None, prefixes=None, returning=None, return_defaults=False, **dialect_kw)
update(table, whereclause=None, values=None, inline=False, bind=None, prefixes=None, returning=None, return_defaults=False, **dialect_kw)s = update(student, student.c.name=='Jim').values(name='Jimmy')
delete(table, whereclause=None, bind=None, returning=None, prefixes=None, **dialect_kw)s = delete(student, student.c.name=='Jimmy')
join(left, right, onclause=None, isouter=False)j = join(user_table, address_table,user_table.c.id == address_table.c.user_id)
数据库最重要就是这四个语句,毕竟在编程层次多数都是对单数据库调用,关于触发器,外键设定等等这些应该是DBA在建表时做好的,编程阶段尽量时应用数据库数据,而非过多涉及数据库细节。上面的方法我个人比较喜欢使用Table类的方法,更具有面向对象,而后部分的更倾向于面向过程。关于Table类可以参考官方Table文档
from sqlalchemy.orm import sessionmaker,mapperDBSession = sessionmaker(autocommit=False, autoflush=False,bind=engine))session = DBSession()
class student_m(object):def __init__(self, id,name,score):self.id = idself.name = nameself.score = scoredef __repr__(self):return '%s(%r,%r,%r)' % (self.__class__.__name__,self.id,self.name,self.score)##还可以定义其他便于编程的方法mapper(student_m, meta.tables['student']) # 将table映射到object
kim = student_mapper('8','kim','93')session.add(kim)
session.flush() ## Flush all the object changes to the database
session.rollback()回滚到上一次的commit之后的状态
session.commit()
session.begin() # begin(subtransactions=False, nested=False)#work work worksession.commit() # Flush pending changes and commit the current transaction.
session.execute(s)这里可以结合上面的Table类面向对象、面向过程方法
session.query()q = session.query(student_m,teacher_m) #student_m teacher_m 是两个mapper 到Table的对象q = session.query(student_m.name,student_m.name) # 类似上面的select,只是不需要加入[]
q.all() #上面只是产生检索语句,还没真正执行,all返回检索全部结果每一行以__repr__中的定义格式返回
q.count() # 返回结果行数
criterion 就是python真值表达式如
student_m.id != '1' and student_m.name != 'Jim'
q = session.query(student_m)ret = q.filter(student_m.id == '1' and ).all()
q.delete() #将检索出来的结果删除session.query(student_m).filter(student_m.id == '1').delete()#在commit之后生效
session.query(student_m).filter(student_m.name== 'Jim').update({'score': '100'}, synchronize_session='evaluate')##values就是一个字典,very pythonic
q = session.query(Address_m).select_from(User_m).join(User_m.addresses).filter(User_m.name == 'ed')
q1 = session.query(school_a_student_m).filter(school_a_student_m.score > 90)q2 = session.query(school_b_student_m).filter(school_b_student_m.score > 90)q3 = q1.union(q2)# union对两张表的操作是合并数据条数,等于是纵向的,就是两个表的列属性必须相同。上面就是合并两校学生分数大于90分的数据
q = session.query(User_m.id).\join(User_m.addresses).\group_by(User_m.id).\having(func.count(Address_m.id) > 2)
限制返回个数
ret = session.query(school_a_student_m).order_by(student_m.score).limit(5).all() ##默认升序ret = session.query(school_a_student_m).order_by(student_m.score.desc()).limit(5).all()
简单说,session.flush之后你才能在这个session中看到效果,而session.commit之后你才能从其它session中看到效果。ps前面的execute会自动commit
flush与commit区别
SQLAlchemy tutorial: how to start
官方文档更靠谱