163

I couldn't find any information about this in the documentation, but how can I get a list of tables created in SQLAlchemy?

I used the class method to create the tables.

Brian Burns
  • 20,575
  • 8
  • 83
  • 77
sidewinder
  • 3,013
  • 6
  • 24
  • 33

17 Answers17

154

All of the tables are collected in the tables attribute of the SQLAlchemy MetaData object. To get a list of the names of those tables:

>>> metadata.tables.keys()
['posts', 'comments', 'users']

If you're using the declarative extension, then you probably aren't managing the metadata yourself. Fortunately, the metadata is still present on the baseclass,

>>> Base = sqlalchemy.ext.declarative.declarative_base()
>>> Base.metadata
MetaData(None)

If you are trying to figure out what tables are present in your database, even among the ones you haven't even told SQLAlchemy about yet, then you can use table reflection. SQLAlchemy will then inspect the database and update the metadata with all of the missing tables.

>>> metadata.reflect(engine)

For Postgres, if you have multiple schemas, you'll need to loop thru all the schemas in the engine:

from sqlalchemy import inspect
inspector = inspect(engine)
schemas = inspector.get_schema_names()

for schema in schemas:
    print("schema: %s" % schema)
    for table_name in inspector.get_table_names(schema=schema):
        for column in inspector.get_columns(table_name, schema=schema):
            print("Column: %s" % column)
SingleNegationElimination
  • 151,563
  • 33
  • 264
  • 304
  • 10
    Deprecated since version 0.8: Please use the sqlalchemy.schema.MetaData.reflect() method. And notice, use `engine = sqlalchemy.create_engine('mysql://user:password@host/db_name')` rather than `"mysql://user:password@host"` and `engine.execute("use db_name")`. – JavaNoScript Mar 21 '13 at 03:54
  • @XuJiawan: I'm not sure which thing is deprecated here, I'm not sure which method im suggesting if it's not `sqlalchemy.MetaData.reflect()`? – SingleNegationElimination May 21 '14 at 14:05
  • @IfLoop: I found it from [the sqlalchemy document](http://docs.sqlalchemy.org/en/rel_0_9/core/metadata.html#sqlalchemy.schema.MetaData.params.reflect). – JavaNoScript May 22 '14 at 14:25
  • 1
    @XuJiawan: The link suggests that the `reflect` *argument* to `MetaData.__init__`, a boolean flag, is deprecated *in favor* of using `MetaData.reflect()`, exactly as I have shown in my answer. – SingleNegationElimination May 22 '14 at 15:14
  • 2
    @IfLoop: Very sorry about my poor English. Your answer is exactly right and I've upped it. I added that comment just to let people notice that if they use version<0.8, they may not use `MetaData.reflect()` method in this way. And also comment it for someone else who may have the same problem caused by the engine declaration. – JavaNoScript May 28 '14 at 04:07
  • 1
    `metadata.tables.keys()`, what is `metadata` ? Where's it imported from? – baxx Mar 17 '23 at 18:11
105

There is a method in engine object to fetch the list of tables name. engine.table_names()

Zubair Alam
  • 8,739
  • 3
  • 26
  • 25
  • 1
    i get `Traceback (most recent call last): File "dedup_jobs.py", line 31, in print(engine.table_names()) File "/Users/darshanchoudhary/.virtualenvs/services/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 2128, in table_names return self.dialect.get_table_names(conn, schema) value = value.replace(self.escape_quote, self.escape_to_quote) AttributeError: 'NoneType' object has no attribute 'replace'` (stack truncated) – Darshan Chaudhary Jul 26 '17 at 11:14
  • 1
    This works also with *Flask-SQLAlchemy*, since there is [direct access to the engine](https://flask-sqlalchemy.palletsprojects.com/en/master/api/#flask_sqlalchemy.SQLAlchemy.engine) via e.g. `DB.engine.table_names()` or whatever the name of the database variable is. – colidyre Mar 23 '20 at 13:59
  • 11
    this is deprecated and you now must use ``` from sqlalchemy import create_engine engine = create_engine(self.__connection_string) insp = inspect(engine) return insp.get_table_names() ``` – Erik Oct 22 '21 at 20:59
68
from sqlalchemy import create_engine
engine = create_engine('postgresql://use:pass@localhost/DBname')
print (engine.table_names())
Maeda
  • 1,291
  • 15
  • 16
  • 4
    This is the correct answer that works as of November 2018. – Austin Mackillop Nov 11 '18 at 22:06
  • 1
    If it doesn't work then it's most likely because the engine can't connect correctly (so a problem in line 2) but you won't get the error message until you run `engine.table_names()` – grofte Jan 16 '19 at 12:32
  • 1
    Use this answer people. – Umar.H Jul 01 '19 at 14:35
  • 6
    this is deprecated and you must use ``` from sqlalchemy import create_engine engine = create_engine(self.__connection_string) insp = inspect(engine) return insp.get_table_names() ``` – Erik Oct 22 '21 at 21:00
37
  • To get a list of all existing tables in DB:

As of SQLAlchemy 1.4: https://docs.sqlalchemy.org/en/14/core/reflection.html#fine-grained-reflection-with-inspector

from sqlalchemy import create_engine
from sqlalchemy import inspect
engine = create_engine('...')
insp = inspect(engine)
print(insp.get_table_names())

Older methods (engine.table_names()) yield:

SADeprecationWarning: The from_engine() method on Inspector is deprecated and will be removed in a future release. Please use the sqlalchemy.inspect() function on an Engine or Connection in order to acquire an Inspector. (deprecated since: 1.4)

  • To get a list of declared tables, use accepted answer: metadata.tables.keys()
Jean Monet
  • 2,075
  • 15
  • 25
  • In the case of using sqlite follow the instructions: from sqlalchemy import create_engine from sqlalchemy import inspect engine = create_engine('sqlite:///your_path_name/data_base_name.db') insp = inspect(engine) tables = insp.get_table_names() print(tables) – Ramiro Apr 02 '22 at 00:38
  • If you have multiple databases/schemas, make sure to include the schema= parameter in the call to get_table_names. Otherwise, you get the names from the 'default' schema. (at least that's what I'm finding in MySQL 8) – Ben Dec 26 '22 at 22:03
14

Within the python interpreter use db.engine.table_names()

$ python
>>> from myapp import db
>>> db.engine.table_names()
Timothy
  • 4,198
  • 6
  • 49
  • 59
  • 3
    Note: This does not work for SQLAlchemy 2.0 – James Mishra Apr 10 '21 at 10:34
  • as James say, you must switch to Inspector, as per docs ``` from sqlalchemy import create_engine engine = create_engine(self.__connection_string) insp = inspect(engine) return insp.get_table_names() ``` – Erik Oct 22 '21 at 21:00
10

I was looking for something like this:

from sqlalchemy import create_engine
eng = create_engine('mysql+pymysql://root:password@localhost:3306', pool_recycle=3600)
q = eng.execute('SHOW TABLES')

available_tables = q.fetchall()

It does an execute and returns all of the tables.

update:

Postgres:

eng = create_engine('postgresql+psycopg2://root:password@localhost/
q = eng.execute('SELECT * FROM pg_catalog.pg_tables')
Brian Burns
  • 20,575
  • 8
  • 83
  • 77
jmunsch
  • 22,771
  • 11
  • 93
  • 114
8

I personally do this and it works:

from sqlalchemy import inspect
inspector = inspect(engine)
inspector.get_table_names()

It gives me all the names in my db.

Anurag A S
  • 725
  • 10
  • 23
Aymen Azoui
  • 369
  • 2
  • 4
7

I'm solving same problem and found this post. After some try run, I would suggest use below to list all tables: (mentioned by zerocog)

metadata = MetaData()
metadata.reflect(bind=engine)
for table in metadata.sorted_tables:
    print(table)

This is useful for direct table handling and I feel is recommended.

And use below code to get table names:

for table_name in engine.table_names():
    print(table_name)

"metadata.tables" provides a Dict for table name and Table object. which would also be useful for quick query.

user2189731
  • 558
  • 8
  • 15
7

Just this simple:

engine.table_names()

Also, to test whether a table exists:

engine.has_table(table_name)
Han Zhang
  • 352
  • 2
  • 6
7

The metadata object that you created the tables with has that in a dictionary.

metadata.tables.keys()
Keith
  • 42,110
  • 11
  • 57
  • 76
4

The best way is to use inspect:

  1. Create the inspector and connect it to the engine
  2. Collect the names of tables within the database
  3. Collect Table columns names
from sqlalchemy import create_engine, inspect

engine = create_engine("sqlite:///../Resources/dow.sqlite")
conn = engine.connect()
inspector = inspect(conn)
inspector.get_table_names() #returns "dow"

columns = inspector.get_columns('dow')

for column in columns:
    print(column["name"], column["type"])
RyanAbnavi
  • 358
  • 4
  • 6
4

This is what I'm using as of 2021-10-22:

import sqlalchemy as sql

engine = sql.create_engine("connection_string")

sql.inspect(engine).get_table_names()
Matt Dancho
  • 6,840
  • 3
  • 35
  • 26
3

Reflecting All Tables at Once allows you to retrieve hidden table names too. I created some temporary tables and they showed up with

meta = MetaData()
meta.reflect(bind=myengine)
for table in reversed(meta.sorted_tables):
    print table

Reference http://docs.sqlalchemy.org/en/latest/core/reflection.html

zerocog
  • 1,703
  • 21
  • 32
3

If you are using Flask-SQLAlchemy, you can get them from your db instance

[...]
db = SQLAlchemy(app)
db.engine.table_names() # you'll get a list of all the table names in your database
Nasser Abdou
  • 188
  • 2
  • 7
3

I use a List Comprehension to extract table names, it works for me

# Import necessary module
from sqlalchemy import create_engine
from sqlalchemy import MetaData

# Create engine: engine
engine = create_engine('sqlite:///database.sqlite')

metadata = MetaData()
metadata.reflect(bind=engine)

table_names = [table.name for table in metadata.tables.values()]

print(table_names)
Mike_C
  • 31
  • 2
1

Complete example of displaying all column information. Assumes variable df contains a dataframe to be written to the SQL database.

from sqlalchemy import create_engine, inspect
from sqlalchemy_utils.functions import database_exists, create_database

engine = create_engine('sqlite:///mydb.sqlite', echo=True)

if not database_exists(engine.url):
    create_database(engine.url)
else:
    engine.connect()

df.to_sql('MyTable', con=engine, if_exists='replace', index=False) # index=False avoids auto-creation of level_0 (name tiebreaker)

inspector = inspect(engine)
table_names = inspector.get_table_names()
for table_name in table_names:
    print(f"Table:{table_name}")
    column_items = inspector.get_columns(table_name)
    print('\t'.join(n for n in column_items[0]))
    for c in column_items:
        assert len(c) == len(column_items[0])
        print('\t'.join(str(c[n]) for n in c))
BSalita
  • 8,420
  • 10
  • 51
  • 68
0

A one liner:

sqlalchemy.inspect(my_connection.engine).get_table_names()

Where:

my_engine = sqlalchemy.create_engine(f"{dialect}+{driver}://{login}:{password}@{host}/{db_name}")

my_connection = my_engine.connect().execution_options(schema_translate_map={None: schema})
mirekphd
  • 4,799
  • 3
  • 38
  • 59