如何在 SQLAlchemy 中删除表?

我想使用 SQLAlchemy 删除一个表。

因为我一遍又一遍地测试,所以我想删除表 my_users,这样每次都可以从头开始。

到目前为止,我使用 SQLAlchemy 通过 Engine Exec()方法执行原始 SQL:

sql = text('DROP TABLE IF EXISTS my_users;')
result = engine.execute(sql)

然而,我想知道是否有一些标准的方法来做到这一点。我能找到的唯一一个是 drop_all(),但它删除了所有的结构,而不仅仅是一个特定的表:

Base.metadata.drop_all(engine)   # all tables are deleted

例如,给出这个非常基本的例子。它包含一个 SQLite 基础结构,只有一个表 my_users,我在其中添加了一些内容。

from sqlalchemy import create_engine, Column, Integer, String, text
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base


engine = create_engine('sqlite://', echo=False)
Base = declarative_base()


class User(Base):
__tablename__ = "my_users"


id = Column(Integer, primary_key=True)
name = Column(String)


def __init__(self, name):
self.name = name


# Create all the tables in the database which are
# defined by Base's subclasses such as User
Base.metadata.create_all(engine)


# Construct a sessionmaker factory object
session = sessionmaker()


# Bind the sessionmaker to engine
session.configure(bind=engine)


# Generate a session to work with
s = session()


# Add some content
s.add(User('myname'))
s.commit()


# Fetch the data
print(s.query(User).filter(User.name == 'myname').one().name)

对于这个特定的情况,drop_all()可以工作,但是从我开始拥有不止一张桌子并且我想保留其他桌子的那一刻起,drop_all()就不方便了。

122475 次浏览

只需对表对象调用 drop()。 来自 那些文件:

使用给定的连接表为此 Table 发出 DROP 语句。

对你来说,应该是:

User.__table__.drop()

如果你遇到例外,比如:

sqlalchemy.exc.UnboundExecutionError: Table object 'my_users' is not bound to an Engine or Connection. Execution can not proceed without a database to execute against

你需要通过引擎:

User.__table__.drop(engine)

下面是您可以在 iPython 中执行的示例代码,用于测试 Postgres 上表的创建和删除

from sqlalchemy import * # imports all needed modules from sqlalchemy


engine = create_engine('postgresql://python:python@127.0.0.1/production') # connection properties stored


metadata = MetaData() # stores the 'production' database's metadata


users = Table('users', metadata,
Column('user_id', Integer),
Column('first_name', String(150)),
Column('last_name', String(150)),
Column('email', String(255)),
schema='python') # defines the 'users' table structure in the 'python' schema of our connection to the 'production' db


users.create(engine) # creates the users table


users.drop(engine) # drops the users table

你也可以用同样的例子和截图来预览我在 Wordpress 上的文章: oscarvalles.Wordpress.com (搜索 SQL 炼金术)。

除了调用 cls.__table__.drop(your_engine)之外,您还可以尝试这样做:

Base.metadata.drop_all(bind=your_engine, tables=[User.__table__])

这个方法和 create_all()方法都接受一个可选参数 tables,它采用 sqlalchemy.sql.schema.Table实例的迭代器。

您可以通过这种方式控制要创建或删除哪些表。

对于不能访问表类的特殊情况,只需按表名删除表,然后使用下面的代码

import logging
from sqlalchemy import MetaData
from sqlalchemy import create_engine
from sqlalchemy.engine.url import URL
from sqlalchemy.ext.declarative import declarative_base


DATABASE = {
'drivername': 'sqlite',
# 'host': 'localhost',
# 'port': '5432',
# 'username': 'YOUR_USERNAME',
# 'password': 'YOUR_PASSWORD',
'database': '/path/to/your_db.sqlite'
}


def drop_table(table_name):
engine = create_engine(URL(**DATABASE))
base = declarative_base()
metadata = MetaData(engine, reflect=True)
table = metadata.tables.get(table_name)
if table is not None:
logging.info(f'Deleting {table_name} table')
base.metadata.drop_all(engine, [table], checkfirst=True)


drop_table('users')

如何按名称删除表

下面是@Levon 的回答的更新,因为 MetaData(engine, reflect=True)现在已被废弃。如果您没有访问表类的权限,或者希望根据表名删除表,那么这种方法非常有用。

from sqlalchemy import MetaData
from sqlalchemy import create_engine
from sqlalchemy.engine.url import URL
from sqlalchemy.ext.declarative import declarative_base


DATABASE = {
'drivername': 'sqlite',
# 'host': 'localhost',
# 'port': '5432',
# 'username': 'YOUR_USERNAME',
# 'password': 'YOUR_PASSWORD',
'database': '/path/to/your_db.sqlite'
}


engine = create_engine(URL(**DATABASE))


def drop_table(table_name, engine=engine):
Base = declarative_base()
metadata = MetaData()
metadata.reflect(bind=engine)
table = metadata.tables[table_name]
if table is not None:
Base.metadata.drop_all(engine, [table], checkfirst=True)


drop_table('users')

如何使用表类删除表(首选)

否则,您可能更喜欢使用 cls.__table__.drop(engine)cls.__table__.create(engine),例如。

User.__table__.drop(engine)
User.__table__.create(engine)