Je veux supprimer une table en utilisant SQLAlchemy.
Comme je teste encore et encore, je veux supprimer la table my_users
Pour pouvoir recommencer à zéro à chaque fois.
Jusqu'ici, j'utilise SQLAlchemy pour exécuter du SQL brut via la méthode engine.execute () :
sql = text('DROP TABLE IF EXISTS my_users;')
result = engine.execute(sql)
Cependant, je me demande s’il existe une façon standard de le faire. Le seul que j'ai pu trouver est drop_all()
, mais il supprime toute la structure, pas seulement une table spécifique:
Base.metadata.drop_all(engine) # all tables are deleted
Par exemple, étant donné cet exemple très basique. Cela consiste en une infrastructure SQLite avec une seule table my_users
Dans laquelle j'ajoute du contenu.
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)
Pour ce cas particulier, drop_all()
fonctionnerait, mais cela ne serait pas pratique à partir du moment où je commence à avoir plus d'une table et que je souhaite conserver les autres.
Appelez simplement drop()
contre l'objet table. De les docs :
Émettez une instruction DROP pour cette table, en utilisant Connectable pour la connectivité.
Dans votre cas, cela devrait être:
User.__table__.drop()
Si vous obtenez une exception comme:
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
Vous devez passer le moteur:
User.__table__.drop(engine)
Alternative à l'appel de cls.__table__.drop(your_engine)
, vous pouvez essayer ceci:
Base.metadata.drop_all(bind=your_engine, tables=[User.__table__])
Cette méthode, ainsi que la méthode create_all()
, accepte un argument facultatif tables
, qui prend un itérateur d'instances sqlalchemy.sql.schema.Table
.
Vous pouvez contrôler les tables à créer ou à supprimer de cette manière.
Vous trouverez ci-dessous un exemple de code que vous pouvez exécuter dans iPython pour tester la création et la suppression d'une table sur Postgres.
from sqlalchemy import * # imports all needed modules from sqlalchemy
engine = create_engine('postgresql://python:[email protected]/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
Vous pouvez également prévisualiser mon article sur Wordpress avec le même exemple et des captures d'écran: oscarvalles.wordpress.com (recherche de SQL Alchemy).
Pour le cas particulier où vous n'avez pas accès à la classe de table et devez simplement supprimer la table par nom de table, vous pouvez utiliser ce code
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')