I am giving Pylons a try with SQLAlchemy, and I love it, there is just one thing, is it possible to print out the raw SQL CREATE TABLE
data generated from Table().create()
before it's executed?

- 4,559
- 5
- 36
- 48

- 825
- 1
- 6
- 8
6 Answers
from sqlalchemy.schema import CreateTable
print(CreateTable(table))
If you are using declarative syntax:
print(CreateTable(Model.__table__))
Update:
Since I have the accepted answer and there is important information in klenwell answer, I'll also add it here.
You can get the SQL for your specific database (MySQL, Postgresql, etc.) by compiling with your engine.
print(CreateTable(Model.__table__).compile(engine))
Update 2:
@jackotonye Added in the comments a way to do it without an engine.
print(CreateTable(Model.__table__).compile(dialect=postgresql.dialect()))

- 3,913
- 2
- 28
- 38

- 17,540
- 3
- 26
- 18
-
This works for the models, but with many-to-many relationships, how do I print out the associative tables, since they are also needed in order for the entire system to work? – tchen Jun 12 '14 at 18:18
-
You have to declare them as well. Look at the doc http://docs.sqlalchemy.org/en/rel_0_9/orm/relationships.html#self-referential-many-to-many-relationship. In the example of the doc, `node_to_node` would be `table` of my first example. – Antoine Leclair Jun 13 '14 at 11:12
-
1Great, this works for me! Howerver, I still can't see indices defined at declarative syntax `__table_args__` member. Any ideas? – Pehat Jul 05 '16 at 14:13
-
5This can also be done without an engine `print(CreateTable(Model.__table__).compile(dialect=postgresql.dialect()))` – jackotonye Apr 20 '17 at 00:06
-
1Exemple with mysqlconnector : ```from sqlalchemy.dialects.mysql import mysqlconnector print(CreateTable(AttribResults.__table__).compile(dialect=mysqlconnector.dialect())) ``` – glefait Mar 12 '19 at 11:35
-
Where is the `Model` coming from? Is it sqlalchemy? I can't figure out where to import it from – Guus Mar 14 '19 at 17:42
-
1@Guus, it's one of the class that you write that inherits from a `declarative_base`. E.g. `class User(Base):` (`User` is `Model` in that example). – Antoine Leclair Mar 14 '19 at 21:39
You can set up you engine to dump the metadata creation sequence, using the following:
def metadata_dump(sql, *multiparams, **params):
# print or write to log or file etc
print(sql.compile(dialect=engine.dialect))
engine = create_engine(myDatabaseURL, strategy='mock', executor=metadata_dump)
metadata.create_all(engine)
One advantage of this approach is that enums and indexes are included in the printout. Using CreateTable
leaves this out.
Another advantage is that the order of the schema definitions is correct and (almost) usable as a script.

- 1,006
- 1
- 9
- 29
-
2If you're using an RDBMS that requires semicolons, replace the body of the function with this `print(str(sql.compile(dialect=engine.dialect)) + ";")` to get the semicolons in the output. – Tim Coker Mar 04 '19 at 17:53
-
With the new Version (1.4), it looks a bit different: `engine = create_mock_engine("postgresql://", metadata_dump)` and `metadata.create_all(engine, checkfirst=False)` – Alexander Mar 15 '22 at 17:41
-
Interesting approach. So you are pulling out the query from the engine object. – justdan23 Jul 12 '23 at 16:48
I needed to get the raw table sql in order to setup tests for some existing models. Here's a successful unit test that I created for SQLAlchemy 0.7.4 based on Antoine's answer as proof of concept:
from sqlalchemy import create_engine
from sqlalchemy.schema import CreateTable
from model import Foo
sql_url = "sqlite:///:memory:"
db_engine = create_engine(sql_url)
table_sql = CreateTable(Foo.table).compile(db_engine)
self.assertTrue("CREATE TABLE foos" in str(table_sql))
Something like this? (from the SQLA FAQ)
http://docs.sqlalchemy.org/en/latest/faq/sqlexpressions.html

- 15,882
- 11
- 61
- 59

- 111
- 2
-
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/low-quality-posts/34909884) – EsmaeelE Aug 28 '23 at 13:53
It turns out this is straight-forward:
from sqlalchemy.dialects import postgresql
from sqlalchemy.schema import CreateTable
from sqlalchemy import Table, Column, String, MetaData
metadata = MetaData()
users = Table('users', metadata,
Column('username', String)
)
statement = CreateTable(users)
print(statement.compile(dialect=postgresql.dialect()))
Outputs this:
CREATE TABLE users (
username VARCHAR
)
Going further, it can even support bound parameters in prepared statements.
Reference
How do I render SQL expressions as strings, possibly with bound parameters inlined?
...
or without an Engine:
from sqlalchemy.dialects import postgresql print(statement.compile(dialect=postgresql.dialect()))
SOURCE: http://docs.sqlalchemy.org/en/latest/faq/sqlexpressions.html#faq-sql-expression-string
Example: Using SQL Alchemy to generate a user rename script
#!/usr/bin/env python
import csv
from sqlalchemy.dialects import postgresql
from sqlalchemy import bindparam, Table, Column, String, MetaData
metadata = MetaData()
users = Table('users', metadata,
Column('username', String)
)
renames = []
with open('users.csv') as csvfile:
for row in csv.DictReader(csvfile):
renames.append({
'from': row['sAMAccountName'],
'to': row['mail']
})
for rename in renames:
stmt = (users.update()
.where(users.c.username == rename['from'])
.values(username=rename['to']))
print(str(stmt.compile(dialect=postgresql.dialect(),
compile_kwargs={"literal_binds": True})) + ';')
When processing this users.csv:
sAMAccountName,mail
bmcboatface,boaty.mcboatface@example.com
ndhyani,naina.dhyani@contoso.com
Gives output like this:
UPDATE users SET username='boaty.mcboatface@example.com' WHERE users.username = 'bmcboatface';
UPDATE users SET username='naina.dhyani@contoso.com' WHERE users.username = 'ndhyani';users.username = 'ndhyani';
Why a research vessel has an email address is yet to be determined. I have been in touch with Example Inc's IT team and have had no response.

- 21,033
- 1
- 58
- 84
-
1
-
My pleasure, @Devy. Thank you for independently confirming it works :) – Alain O'Dea Oct 18 '19 at 22:25
May be you mean echo
parameter of sqlalchemy.create_engine?
/tmp$ cat test_s.py
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Department(Base):
__tablename__ = "departments"
department_id = sa.Column(sa.types.Integer, primary_key=True)
name = sa.Column(sa.types.Unicode(100), unique=True)
chief_id = sa.Column(sa.types.Integer)
parent_department_id = sa.Column(sa.types.Integer,
sa.ForeignKey("departments.department_id"))
parent_department = sa.orm.relation("Department")
engine = sa.create_engine("sqlite:///:memory:", echo=True)
Base.metadata.create_all(bind=engine)
/tmp$ python test_s.py
2011-03-24 15:09:58,311 INFO sqlalchemy.engine.base.Engine.0x...42cc PRAGMA table_info("departments")
2011-03-24 15:09:58,312 INFO sqlalchemy.engine.base.Engine.0x...42cc ()
2011-03-24 15:09:58,312 INFO sqlalchemy.engine.base.Engine.0x...42cc
CREATE TABLE departments (
department_id INTEGER NOT NULL,
name VARCHAR(100),
chief_id INTEGER,
parent_department_id INTEGER,
PRIMARY KEY (department_id),
UNIQUE (name),
FOREIGN KEY(parent_department_id) REFERENCES departments (department_id)
)
2011-03-24 15:09:58,312 INFO sqlalchemy.engine.base.Engine.0x...42cc ()
2011-03-24 15:09:58,312 INFO sqlalchemy.engine.base.Engine.0x...42cc COMMIT

- 1,995
- 1
- 11
- 2