# Create a Table with SQLModel - Use the Engine Now let's get to the code. 👩💻 Make sure you are inside of your project directory and with your virtual environment activated as [explained in the previous chapter](index.md){.internal-link target=_blank}. We will: * Define a table with **SQLModel** * Create the same SQLite database and table with **SQLModel** * Use **DB Browser for SQLite** to confirm the operations Here's a reminder of the table structure we want:
| id | name | secret_name | age |
|---|---|---|---|
| 1 | Deadpond | Dive Wilson | null |
| 2 | Spider-Boy | Pedro Parqueador | null |
| 3 | Rusty-Man | Tommy Sharp | 48 |
Now, because we are taking the place of the default value with our `Field()` function, we set **the actual default value** of `id` to `None` with the argument `default=None` in `Field()`:
```Python
Field(default=None)
```
If we didn't set the `default` value, whenever we use this model later to do data validation (powered by Pydantic) it would *accept* a value of `None` apart from an `int`, but it would still **require** passing that `None` value. And it would be confusing for whoever is using this model later (probably us), so **better set the default value here**.
## Create the Engine
Now we need to create the SQLAlchemy **Engine**.
It is an object that handles the communication with the database.
If you have a server database (for example PostgreSQL or MySQL), the **engine** will hold the **network connections** to that database.
Creating the **engine** is very simple, just call `create_engine()` with a URL for the database to use:
{* ./docs_src/tutorial/create_db_and_table/tutorial001_py310.py ln[1:16] hl[1,14] *}
You should normally have a single **engine** object for your whole application and re-use it everywhere.
/// tip
There's another related thing called a **Session** that normally should *not* be a single object per application.
But we will talk about it later.
///
### Engine Database URL
Each supported database has its own URL type. For example, for **SQLite** it is `sqlite:///` followed by the file path. For example:
* `sqlite:///database.db`
* `sqlite:///databases/local/application.db`
* `sqlite:///db.sqlite`
SQLite supports a special database that lives all *in memory*. Hence, it's very fast, but be careful, the database gets deleted after the program terminates. You can specify this in-memory database by using just two slash characters (`//`) and no file name:
* `sqlite://`
{* ./docs_src/tutorial/create_db_and_table/tutorial001_py310.py ln[1:16] hl[11:12,14] *}
You can read a lot more about all the databases supported by **SQLAlchemy** (and that way supported by **SQLModel**) in the SQLAlchemy documentation.
### Engine Echo
In this example, we are also using the argument `echo=True`.
It will make the engine print all the SQL statements it executes, which can help you understand what's happening.
It is particularly useful for **learning** and **debugging**:
{* ./docs_src/tutorial/create_db_and_table/tutorial001_py310.py ln[1:16] hl[14] *}
But in production, you would probably want to remove `echo=True`:
```Python
engine = create_engine(sqlite_url)
```
### Engine Technical Details
/// tip
If you didn't know about SQLAlchemy before and are just learning **SQLModel**, you can probably skip this section, scroll below.
///
You can read a lot more about the engine in the SQLAlchemy documentation.
**SQLModel** defines its own `create_engine()` function. It is the same as SQLAlchemy's `create_engine()`, but with the difference that it defaults to use `future=True` (which means that it uses the style of the latest SQLAlchemy, 1.4, and the future 2.0).
And SQLModel's version of `create_engine()` is type annotated internally, so your editor will be able to help you with autocompletion and inline errors.
## Create the Database and Table
Now everything is in place to finally create the database and table:
{* ./docs_src/tutorial/create_db_and_table/tutorial001_py310.py hl[16] *}
/// tip
Creating the engine doesn't create the `database.db` file.
But once we run `SQLModel.metadata.create_all(engine)`, it creates the `database.db` file **and** creates the `hero` table in that database.
Both things are done in this single step.
///
Let's unwrap that:
```Python
SQLModel.metadata.create_all(engine)
```
### SQLModel MetaData
The `SQLModel` class has a `metadata` attribute. It is an instance of a class `MetaData`.
Whenever you create a class that inherits from `SQLModel` **and is configured with `table = True`**, it is registered in this `metadata` attribute.
So, by the last line, `SQLModel.metadata` already has the `Hero` registered.
### Calling `create_all()`
This `MetaData` object at `SQLModel.metadata` has a `create_all()` method.
It takes an **engine** and uses it to create the database and all the tables registered in this `MetaData` object.
### SQLModel MetaData Order Matters
This also means that you have to call `SQLModel.metadata.create_all()` *after* the code that creates new model classes inheriting from `SQLModel`.
For example, let's imagine you do this:
* Create the models in one Python file `models.py`.
* Create the engine object in a file `db.py`.
* Create your main app and call `SQLModel.metadata.create_all()` in `app.py`.
If you only imported `SQLModel` and tried to call `SQLModel.metadata.create_all()` in `app.py`, it would not create your tables:
```Python
# This wouldn't work! 🚨
from sqlmodel import SQLModel
from .db import engine
SQLModel.metadata.create_all(engine)
```
It wouldn't work because when you import `SQLModel` alone, Python doesn't execute all the code creating the classes inheriting from it (in our example, the class `Hero`), so `SQLModel.metadata` is still empty.
But if you import the models *before* calling `SQLModel.metadata.create_all()`, it will work:
```Python
from sqlmodel import SQLModel
from . import models
from .db import engine
SQLModel.metadata.create_all(engine)
```
This would work because by importing the models, Python executes all the code creating the classes inheriting from `SQLModel` and registering them in the `SQLModel.metadata`.
As an alternative, you could import `SQLModel` and your models inside of `db.py`:
```Python
# db.py
from sqlmodel import SQLModel, create_engine
from . import models
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url)
```
And then import `SQLModel` *from* `db.py` in `app.py`, and there call `SQLModel.metadata.create_all()`:
```Python
# app.py
from .db import engine, SQLModel
SQLModel.metadata.create_all(engine)
```
The import of `SQLModel` from `db.py` would work because `SQLModel` is also imported in `db.py`.
And this trick would work correctly and create the tables in the database because by importing `SQLModel` from `db.py`, Python executes all the code creating the classes that inherit from `SQLModel` in that `db.py` file, for example, the class `Hero`.
## Migrations
For this simple example, and for most of the **Tutorial - User Guide**, using `SQLModel.metadata.create_all()` is enough.
But for a production system you would probably want to use a system to migrate the database.
This would be useful and important, for example, whenever you add or remove a column, add a new table, change a type, etc.
But you will learn about migrations later in the Advanced User Guide.
## Run The Program
Let's run the program to see it all working.
Put the code it in a file `app.py` if you haven't already.
{* ./docs_src/tutorial/create_db_and_table/tutorial001_py310.py *}
/// tip
Remember to [activate the virtual environment](./index.md#create-a-python-virtual-environment){.internal-link target=_blank} before running it.
///
Now run the program with Python:
## Refactor Data Creation
Now let's restructure the code a bit to make it easier to **reuse**, **share**, and **test** later.
Let's move the code that has the main **side effects**, that changes data (creates a file with a database and a table) to a function.
In this example it's just the `SQLModel.metadata.create_all(engine)`.
Let's put it in a function `create_db_and_tables()`:
{* ./docs_src/tutorial/create_db_and_table/tutorial002_py310.py ln[1:18] hl[17:18] *}
If `SQLModel.metadata.create_all(engine)` was not in a function and we tried to import something from this module (from this file) in another, it would try to create the database and table **every time** we executed that other file that imported this module.
We don't want that to happen like that, only when we **intend** it to happen, that's why we put it in a function, because we can make sure that the tables are created only when we call that function, and not when this module is imported somewhere else.
Now we would be able to, for example, import the `Hero` class in some other file without having those **side effects**.
/// tip
😅 **Spoiler alert**: The function is called `create_db_and_tables()` because we will have more **tables** in the future with other classes apart from `Hero`. 🚀
///
### Create Data as a Script
We prevented the side effects when importing something from your `app.py` file.
But we still want it to **create the database and table** when we call it with Python directly as an independent script from the terminal, just as above.
/// tip
Think of the word **script** and **program** as interchangeable.
The word **script** often implies that the code could be run independently and easily. Or in some cases it refers to a relatively simple program.
///
For that we can use the special variable `__name__` in an `if` block:
{* ./docs_src/tutorial/create_db_and_table/tutorial002_py310.py hl[21:22] *}
### About `__name__ == "__main__"`
The main purpose of the `__name__ == "__main__"` is to have some code that is executed when your file is called with: