我正在启动一个新的应用程序,并考虑使用对象关系映射--特别是SQLAlchemy。
假设我的数据库中有一列'foo‘,我想要递增它。在简单的sqlite中,这很简单:
db = sqlite3.connect('mydata.sqlitedb')
cur = db.cursor()
cur.execute('update table stuff set foo = foo + 1')
我想出了SQL构建器的等价物:
engine = sqlalchemy.create_engine('sqlite:///mydata.sqlitedb')
md = sqlalchemy.MetaData(engine)
table = sqlalchemy.Table('stuff', md, autoload=True)
upd = table.update(values={table.c.foo:table.c.foo+1})
engine.execute(upd)
这稍微慢了一点,但里面的内容不多。
以下是我对SQLAlchemy对象关系管理方法的最佳猜测:
# snip definition of Stuff class made using declarative_base
# snip creation of session object
for c in session.query(Stuff):
c.foo = c.foo + 1
session.flush()
session.commit()
这样做是正确的,但它所需的时间不到其他两种方法的50倍。我认为这是因为它必须将所有数据放入内存中,然后才能使用它。
有没有办法使用SQLAlchemy的ORM生成高效的SQL?或者使用任何其他的python ORM?或者,我应该继续手工编写SQL吗?
发布于 2008-11-10 17:40:43
SQLAlchemy的ORM旨在与SQL层一起使用,而不是隐藏它。但在同一事务中使用ORM和纯SQL时,您必须牢记一两件事。基本上,从一方面来说,ORM数据修改仅在您从会话中刷新更改时才会影响数据库。另一方面,SQL数据操作语句不会影响会话中的对象。
所以如果你说
for c in session.query(Stuff).all():
c.foo = c.foo+1
session.commit()
它将照它说的做,从数据库中获取所有对象,修改所有对象,然后在刷新数据库更改时,逐个更新行。
相反,您应该这样做:
session.execute(update(stuff_table, values={stuff_table.c.foo: stuff_table.c.foo + 1}))
session.commit()
正如您所期望的那样,这将作为一个查询执行,并且因为至少默认会话配置在提交时会使会话中的所有数据过期,所以您不会有任何陈旧数据问题。
在即将发布的0.5系列中,您也可以使用此方法进行更新:
session.query(Stuff).update({Stuff.foo: Stuff.foo + 1})
session.commit()
这基本上会运行与前面代码片段相同的SQL语句,但也会选择更改过的行,并使会话中的所有陈旧数据失效。如果您知道在更新之后没有使用任何会话数据,那么还可以将synchronize_session=False
添加到update语句中,并去掉那个select语句。
发布于 2010-12-28 00:28:03
session.query(Clients).filter(Clients.id == client_id_list).update({'status': status})
session.commit()
试试这个=)
发布于 2015-11-11 03:53:27
有多种使用sqlalchemy进行更新的方法
1) for c in session.query(Stuff).all():
c.foo += 1
session.commit()
2) session.query(Stuff).update({"foo": Stuff.foo + 1})
session.commit()
3) conn = engine.connect()
table = Stuff.__table__
stmt = table.update().values({'foo': Stuff.foo + 'a'})
conn.execute(stmt)
conn.commit()
https://stackoverflow.com/questions/270879
复制相似问题