SQL Insert
Drizzle ORM provides you the most SQL-like way to insert rows into the database tables.
Insert one row
Inserting data with Drizzle is extremely straightforward and sql-like. See for yourself:
If you need insert type for a particular table you can use typeof usersTable.$inferInsert
syntax.
Insert returning
You can insert a row and get it back in PostgreSQL and SQLite like such:
Insert $returningId
MySQL itself doesn’t have native support for RETURNING
after using INSERT
. There is only one way to do it for primary keys
with autoincrement
(or serial
) types, where you can access insertId
and affectedRows
fields. We’ve prepared an automatic way for you to handle such cases with Drizzle and automatically receive all inserted IDs as separate objects
Also with Drizzle, you can specify a primary key
with $default
function that will generate custom primary keys at runtime. We will also return those generated keys for you in the $returningId()
call
If there is no primary keys -> type will be
{}[]
for such queries
Insert multiple rows
Upserts and conflicts
Drizzle ORM provides simple interfaces for handling upserts and conflicts.
On conflict do nothing
onConflictDoNothing
will cancel the insert if there’s a conflict:
On conflict do update
onConflictDoUpdate
will update the row if there’s a conflict:
where
clauses
on conflict do update
can have a where
clause in two different places -
as part of the conflict target (i.e. for partial indexes) or as part of the update
clause:
To specify these conditions in Drizzle, you can use setWhere
and targetWhere
clauses:
Upsert with composite indexes, or composite primary keys for onConflictDoUpdate
:
On duplicate key update
MySQL supports ON DUPLICATE KEY UPDATE
instead of ON CONFLICT
clauses. MySQL will automatically determine the conflict target based on the primary key and unique indexes, and will update the row if any unique index conflicts.
Drizzle supports this through the onDuplicateKeyUpdate
method:
While MySQL does not directly support doing nothing on conflict, you can perform a no-op by setting any column’s value to itself and achieve the same effect:
with insert
clause
Using the with
clause can help you simplify complex queries by splitting them into smaller subqueries called common table expressions (CTEs):
Insert into … select
As the SQLite documentation mentions:
The second form of the INSERT statement contains a SELECT statement instead of a VALUES clause. A new entry is inserted into the table for each row of data returned by executing the SELECT statement. If a column-list is specified, the number of columns in the result of the SELECT must be the same as the number of items in the column-list. Otherwise, if no column-list is specified, the number of columns in the result of the SELECT must be the same as the number of columns in the table. Any SELECT statement, including compound SELECTs and SELECT statements with ORDER BY and/or LIMIT clauses, may be used in an INSERT statement of this form.
To avoid a parsing ambiguity, the SELECT statement should always contain a WHERE clause, even if that clause is simply “WHERE true”, if the upsert-clause is present. Without the WHERE clause, the parser does not know if the token “ON” is part of a join constraint on the SELECT, or the beginning of the upsert-clause.
As the PostgreSQL documentation mentions:
A query (SELECT statement) that supplies the rows to be inserted
And as the MySQL documentation mentions:
With INSERT … SELECT, you can quickly insert many rows into a table from the result of a SELECT statement, which can select from one or many tables
Drizzle supports the current syntax for all dialects, and all of them share the same syntax. Let’s review some common scenarios and API usage. There are several ways to use select inside insert statements, allowing you to choose your preferred approach:
- You can pass a query builder inside the select function.
- You can use a query builder inside a callback.
- You can pass an SQL template tag with any custom select query you want to use