2011-01-21 528 views
38

我正在開發基於存在數據庫的Pylons應用程序,所以我正在使用反射。我有一個SQL文件,其中包含我用來創建測試數據庫的模式。這就是爲什麼我不能簡單地使用drop_allcreate_allSQLAlchemy,清除數據庫內容但不刪除模式

我想寫一些單元測試,我面臨每次測試後清除數據庫內容的問題。我只是想刪除所有的數據,但保持表格不變。這可能嗎?

該應用程序使用Postgres,這也是必須使用的測試。

+0

您應該使用事務。 http://docs.sqlalchemy.org/en/rel_0_7/orm/session.html#joining-a-session-into-an-external-transaction – charlax 2012-09-12 09:35:54

回答

40

我在SQLAlchemy的Google小組上詢問過同樣的事情,並且我看到了一個看起來很好的配方(我所有的表都被清空了)。請參閱the thread以供參考。

我的代碼(節選)看起來是這樣的:

import contextlib 
from sqlalchemy import MetaData 

meta = MetaData() 

with contextlib.closing(engine.connect()) as con: 
    trans = con.begin() 
    for table in reversed(meta.sorted_tables): 
     con.execute(table.delete()) 
    trans.commit() 

編輯:我修改了代碼,刪除以相反的順序表;據說這應該確保孩子在父母面前被刪除。

0

如何使用截斷:

TRUNCATE [TABLE]名[,...]

http://www.postgresql.org/docs/8.4/static/sql-truncate.html

這將刪除所有表中的記錄,但離開架構中圓通。

+1

這將是好的,但我怎麼能在SQLAlchemy中使用它?對於meta.Base.metadata.tables.keys()中的表:meta.Session.execute('truncate%s'%table); meta.Session.commit()`導致這樣的錯誤消息:「InternalError:(InternalError)當前事務中止,命令被忽略,直到事務塊結束 'truncate data.subkeywords'{}」 – 2011-01-21 21:32:46

+1

我通過執行`truncate% s級聯「,但它很痛苦地緩慢。每個單元測試後運行速度太慢... – 2011-01-21 22:03:44

+2

問題是要求sqlalchemy,而不是sql。 – lnhubbell 2015-11-24 18:56:35

7

對於PostgreSQL使用TRUNCATE

with contextlib.closing(engine.connect()) as con: 
    trans = con.begin() 
    con.execute('TRUNCATE {} RESTART IDENTITY;'.format(
     ','.join(table.name 
       for table in reversed(Base.metadata.sorted_tables)))) 
    trans.commit() 

注:RESTART IDENTITY;確保所有的序列被複位爲好。不過,這比@ aknuds1的DELETE配方慢50%。

另一個方法是首先刪除所有表,然後重新創建它們。這比另一個50%慢:

Base.metadata.drop_all(bind=engine) 
Base.metadata.create_all(bind=engine)