Drizzle lets you define a schema in TypeScript with various models and properties supported by the underlying database.
When you define your schema, it serves as the source of truth for future modifications in queries (using Drizzle-ORM)
and migrations (using Drizzle-Kit).
If you are using Drizzle-Kit for the migration process, make sure to export all the models defined in your schema files so that Drizzle-Kit can import them and use them in the migration diff process.
Organize your schema files
You can declare your SQL schema directly in TypeScript either in a single schema.ts file,
or you can spread them around — whichever you prefer, all the freedom!
Schema in 1 file
The most common way to declare your schema with Drizzle is to put all your tables into one schema.ts file.
Note: You can name your schema file whatever you like. For example, it could be models.ts, or something else.
This approach works well if you don’t have too many table models defined, or if you’re okay with keeping them all in one file
Example:
In the drizzle.config.ts file, you need to specify the path to your schema file. With this configuration, Drizzle will
read from the schema.ts file and use this information during the migration generation process. For more information
about the drizzle.config.ts file and migrations with Drizzle, please check: link
Schema in multiple files
You can place your Drizzle models — such as tables, enums, sequences, etc. — not only in one file but in any file you prefer.
The only thing you must ensure is that you export all the models from those files so that the Drizzle kit can import
them and use them in migrations.
One use case would be to separate each table into its own file.
In the drizzle.config.ts file, you need to specify the path to your schema folder. With this configuration, Drizzle will
read from the schema folder and find all the files recursively and get all the drizzle tables from there. For more information
about the drizzle.config.ts file and migrations with Drizzle, please check: link
You can also group them in any way you like, such as creating groups for user-related tables, messaging-related tables, product-related tables, etc.
In the drizzle.config.ts file, you need to specify the path to your schema file. With this configuration, Drizzle will
read from the schema.ts file and use this information during the migration generation process. For more information
about the drizzle.config.ts file and migrations with Drizzle, please check: link
Shape your data schema
Drizzle schema consists of several model types from database you are using. With drizzle you can specify:
Tables with columns, constraints, etc.
Schemas(PostgreSQL only)
Enums
Sequences(PostgreSQL only)
Views
Materialized Views
etc.
Let’s go one by one and check how the schema should be defined with drizzle
Tables and columns declaration
A table in Drizzle should be defined with at least 1 column, the same as it should be done in database. There is one important thing to know,
there is no such thing as a common table object in drizzle. You need to choose a dialect you are using, PostgreSQL, MySQL or SQLite
PostgreSQL Table
MySQL Table
SQLite Table
By default, Drizzle will use the TypeScript key names for columns in database queries.
Therefore, the schema and query from the example will generate the SQL query shown below
This example uses a db object, whose initialization is not covered in this part of the documentation. To learn how to connect to the database, please refer to the Connections Docs
TypeScript key = database key
If you want to use different names in your TypeScript code and in the database, you can use column aliases
Camel and Snake casing
Database model names often use snake_case conventions, while in TypeScript, it is common to use camelCase for naming models.
This can lead to a lot of alias definitions in the schema. To address this, Drizzle provides a way to automatically
map camelCase from TypeScript to snake_case in the database by including one optional parameter during Drizzle database initialization
For such mapping, you can use the casing option in the Drizzle DB declaration. This parameter will
help you specify the database model naming convention and will attempt to map all JavaScript keys accordingly
Advanced
There are a few tricks you can use with Drizzle ORM. As long as Drizzle is entirely in TypeScript files,
you can essentially do anything you would in a simple TypeScript project with your code.
One common feature is to separate columns into different places and then reuse them.
For example, consider the updated_at, created_at, and deleted_at columns. Many tables/models may need these
three fields to track and analyze the creation, deletion, and updates of entities in a system
We can define those columns in a separate file and then import and spread them across all the table objects you have
Schemas
PostgreSQL
MySQL
SQLite
In PostgreSQL, there is an entity called a schema (which we believe should be called folders). This creates a structure in PostgreSQL:
You can manage your PostgreSQL schemas with pgSchema and place any other models inside it.
Define the schema you want to manage using Drizzle
Then place the table inside the schema object
In MySQL, there is an entity called Schema, but in MySQL terms, this is equivalent to a Database.
You can define them with drizzle-orm and use them in queries, but they won’t be detected by drizzle-kit or included in the migration flow
Define the schema you want to manage using Drizzle
Then place the table inside the schema object
In SQLite, there is no concept of a schema, so you can only define tables within a single SQLite file context
Example
Once you know the basics, let’s define a schema example for a real project to get a better view and understanding
All examples will use generateUniqueString. The implementation for it will be provided after all the schema examples