Sqlalchemy if table does not exist

Question:

I wrote a module which is to create an empty database file

def create_database():
    engine = create_engine("sqlite:///myexample.db", echo=True)
    metadata = MetaData(engine)
    metadata.create_all()

But in another function, I want to open myexample.db database, and create tables to it if it doesn’t already have that table.

EG of the first, subsequent table I would create would be:

Table(Variable_TableName, metadata,
       Column('Id', Integer, primary_key=True, nullable=False),
       Column('Date', Date),
       Column('Volume', Float))

(Since it is initially an empty database, it will have no tables in it, but subsequently, I can add more tables to it. Thats what i’m trying to say.)

Any suggestions?

Asked By: jake wong

||

Answers:

I’ve managed to figure out what I intended to do. I used engine.dialect.has_table(engine, Variable_tableName) to check if the database has the table inside. IF it doesn’t, then it will proceed to create a table in the database.

Sample code:

engine = create_engine("sqlite:///myexample.db")  # Access the DB Engine
if not engine.dialect.has_table(engine, Variable_tableName):  # If table don't exist, Create.
    metadata = MetaData(engine)
    # Create a table with the appropriate Columns
    Table(Variable_tableName, metadata,
          Column('Id', Integer, primary_key=True, nullable=False), 
          Column('Date', Date), Column('Country', String),
          Column('Brand', String), Column('Price', Float),
    # Implement the creation
    metadata.create_all()

This seems to be giving me what i’m looking for.

Answered By: jake wong

Note that in ‘Base.metadata’ documentation it states about create_all:

Conditional by default, will not attempt to recreate tables already
present in the target database.

And if you can see that create_all takes these arguments: create_all(self, bind=None, tables=None, checkfirst=True), and according to documentation:

Defaults to True, don’t issue CREATEs for tables already present in
the target database.

So if I understand your question correctly, you can just skip the condition.

Answered By: Belle05

For those who define the table first in some models.table file, among other tables.
This is a code snippet for finding the class that represents the table we want to create ( so later we can use the same code to just query it )

But together with the if written above, I still run the code with checkfirst=True

ORMTable.__table__.create(bind=engine, checkfirst=True)

models.table

class TableA(Base):
class TableB(Base):
class NewTableC(Base):

   id = Column('id', Text)
   name = Column('name', Text)

form

Then in the form action file:

engine = create_engine("sqlite:///myexample.db")
if not engine.dialect.has_table(engine, table_name):
   # Added to models.tables the new table I needed ( format Table as written above )
   table_models = importlib.import_module('models.tables')

   # Grab the class that represents the new table
   # table_name = 'NewTableC'
   ORMTable = getattr(table_models, table_name)            

   # checkfirst=True to make sure it doesn't exists
   ORMTable.__table__.create(bind=engine, checkfirst=True)
Answered By: Ricky Levi

engine.dialect.has_table does not work for me on cx_oracle.
I am getting AttributeError: 'OracleDialect_cx_oracle' object has no attribute 'default_schema_name'

I wrote a workaround function:

from sqlalchemy.engine.base import Engine  
def orcl_tab_or_view_exists(in_engine: Engine, in_object: str,  in_object_name: str,)-> bool:
    """Checks if Oracle table exists in current in_engine connection

    in_object: 'table' | 'view'

    in_object_name: table_name | view_name
      """
    obj_query = """SELECT {o}_name FROM all_{o}s WHERE owner = SYS_CONTEXT ('userenv', 'current_schema') AND {o}_name = '{on}'
    """.format(o=in_object, on=in_object_name.upper())
    with in_engine.connect() as connection:
        result = connection.execute(obj_query)
    return len(list(result)) > 0
Answered By: Pavlo

The accepted answer prints a warning that engine.dialect.has_table() is only for internal use and not part of the public API. The message suggests this as an alternative, which works for me:

import os
import sqlalchemy

# Set up a connection to a SQLite3 DB
test_db = os.getcwd() + "/test.sqlite"
db_connection_string = "sqlite:///" + test_db
engine = create_engine(db_connection_string)

# The recommended way to check for existence
sqlalchemy.inspect(engine).has_table("BOOKS")

See also the SQL Alchemy docs.

Answered By: FiddleStix

This is the code working for me to create all tables of all model classes defined with Base class

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base

class YourTable(Base):
    __tablename__ = 'your_table'
    id            = Column(Integer, primary_key = True)

DB_URL="mysql+mysqldb://<user>:<password>@<host>:<port>/<db_name>"
scoped_engine = create_engine(DB_URL)
Base = declarative_base()
Base.metadata.create_all(scoped_engine)
Answered By: Nam G VU
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.