71

我想使用 SQLAlchemy 删除一个表。

由于我一遍又一遍地测试,我想删除该表my_users,以便我每次都可以从头开始。

到目前为止,我正在使用 SQLAlchemy 通过engine.execute()方法执行原始 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()可以使用,但是从我开始拥有多个桌子并且我想保留其他桌子的那一刻起,它就不方便了。

4

5 回答 5

69

只需调用drop()table 对象。从文档

使用给定的 Connectable 为该表发出 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)
于 2016-03-10T14:06:54.400 回答
28

替代 call cls.__table__.drop(your_engine),你可以试试这个:

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

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

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

于 2018-04-04T06:20:46.283 回答
16

对于您无权访问表类并且只需要按表名删除表的特殊情况,然后使用此代码

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')
于 2019-02-23T15:38:59.537 回答
8

下面是您可以在 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 Alchemy)。

于 2017-07-04T16:44:57.147 回答
6

这是@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)andcls.__table__.create(engine)来代替,例如

User.__table__.drop(engine)
User.__table__.create(engine)
于 2021-02-25T21:17:23.990 回答