Insert query builder
The insert query builder allows you to insert new rows into the database. You must use the select query builder for selecting, deleting or updating rows.
You can get access to the insert query builder as shown in the following example:
import db from '@adonisjs/lucid/services/db'
db.insertQuery()
// selecting table also returns an instance of the query builder
db.table('users')
Methods/Properties
Following is the list of methods and properties available on the Insert query builder class.
insert
The insert method accepts an object of key-value pair to insert.
The return value of the insert query is highly dependent on the underlying driver.
- MySQL returns the id of the last inserted row.
- SQLite returns the id of the last inserted row.
- For PostgreSQL, MSSQL, and Oracle, you must use the
returningmethod to fetch the value of the id.
db
.table('users')
.returning('id')
.insert({
username: 'virk',
email: 'virk@adonisjs.com',
password: 'secret',
})
multiInsert
The multiInsert method accepts an array of objects and inserts multiple rows at once.
db
.table('users')
.multiInsert([
{
username: 'virk',
email: 'virk@adonisjs.com',
password: 'secret',
},
{
username: 'romain',
email: 'romain@adonisjs.com',
password: 'secret',
}
])
/**
INSERT INTO "users"
("email", "password", "username")
values
('virk@adonisjs.com', 'secret', 'virk'),
('romain@adonisjs.com', 'secret', 'romain')
*/
returning
You can use the returning method with PostgreSQL, MSSQL, and Oracle databases to retrieve one or more columns' values.
const rows = db
.table('users')
.returning(['id', 'username'])
.insert({
username: 'virk',
email: 'virk@adonisjs.com',
password: 'secret',
})
console.log(rows[0].id, rows[0].username)
onConflict
The onConflict method allows you to specify an alternative behavior when a unique constraint violation occurs during an insert. It is supported in PostgreSQL, MySQL, and SQLite3 databases. You can chain it with ignore to silently discard the conflicting row, or merge to perform an upsert.
You can call onConflict without arguments, with a single column, or with an array of columns.
onConflict().ignore()
Ignore the insert when a conflict occurs. This adds an ON CONFLICT ... DO NOTHING clause (or the equivalent for your database).
db
.table('users')
.insert({ username: 'virk', email: 'virk@adonisjs.com' })
.onConflict('username')
.ignore()
/**
INSERT INTO "users" ("email", "username")
VALUES ('virk@adonisjs.com', 'virk')
ON CONFLICT ("username") DO NOTHING
*/
You can also specify multiple columns:
db
.table('users')
.insert({ username: 'virk', email: 'virk@adonisjs.com' })
.onConflict(['username', 'email'])
.ignore()
Or call onConflict without arguments to handle any conflict:
db
.table('users')
.insert({ username: 'virk', email: 'virk@adonisjs.com' })
.onConflict()
.ignore()
onConflict().merge()
Merge the conflicting row with the new values (upsert). This adds an ON CONFLICT ... DO UPDATE SET clause.
When called without arguments, all inserted columns are updated:
db
.table('users')
.insert({ username: 'virk', email: 'virk@adonisjs.com' })
.onConflict('username')
.merge()
/**
INSERT INTO "users" ("email", "username")
VALUES ('virk@adonisjs.com', 'virk')
ON CONFLICT ("username")
DO UPDATE SET "email" = EXCLUDED."email", "username" = EXCLUDED."username"
*/
You can specify a subset of columns to update on conflict:
db
.table('users')
.insert({ username: 'virk', email: 'virk@adonisjs.com' })
.onConflict('username')
.merge(['email'])
Or provide an object of key-value pairs to set specific values on conflict:
db
.table('users')
.insert({ username: 'virk', email: 'virk@adonisjs.com' })
.onConflict('username')
.merge({ email: 'updated@adonisjs.com' })
with
The with method allows you to use CTE (Common table expression) with insert queries in PostgreSQL, Oracle, SQLite3 and the MSSQL databases.
import db from '@adonisjs/lucid/services/db'
db
.table('users')
.with('active_users', db.raw('select * from users where is_active = ?', [true]))
.insert({ username: 'virk' })
withMaterialized/withNotMaterialized
The withMaterialized and the withNotMaterialized methods allow you to use CTE (Common table expression) as materialized views with insert queries in PostgreSQL and SQLite3 databases.
db
.table('users')
.withMaterialized('active_users', db.raw('select * from users where is_active = 1'))
.insert({ username: 'virk' })
withRecursive
The withRecursive method creates a recursive CTE (Common table expression) for insert queries in PostgreSQL, Oracle, SQLite3 and the MSSQL databases.
db
.table('users')
.withRecursive('tree', db.raw('select * from categories'))
.insert({ username: 'virk' })
comment
The comment method adds an SQL comment to the query. This can be helpful for identifying queries in database logs and monitoring tools.
db
.table('users')
.comment('bulk user insert')
.insert({ username: 'virk', email: 'virk@adonisjs.com' })
/**
/* bulk user insert */ INSERT INTO "users" ("email", "username")
VALUES ('virk@adonisjs.com', 'virk')
*/
debug
The debug method allows enabling or disabling debugging at an individual query level. Here's a complete guide on debugging queries.
const rows = db
.table('users')
.debug(true)
.insert({
username: 'virk',
email: 'virk@adonisjs.com',
password: 'secret',
})
timeout
Define the timeout for the query. An exception is raised after the timeout has been exceeded.
The value of timeout is always in milliseconds.
db
.table('users')
.timeout(2000)
.insert({
username: 'virk',
email: 'virk@adonisjs.com',
password: 'secret',
})
You can also cancel the query when using timeouts with MySQL and PostgreSQL.
db
.table('users')
.timeout(2000, { cancel: true })
.insert({
username: 'virk',
email: 'virk@adonisjs.com',
password: 'secret',
})
toSQL
The toSQL method returns the query SQL and bindings as an object.
const output = db
.table('users')
.insert({
username: 'virk',
email: 'virk@adonisjs.com',
password: 'secret',
})
.toSQL()
console.log(output)
The toSQL object also has the toNative method to format the SQL query as per the database dialect in use.
const output = db
.table('users')
.insert({
username: 'virk',
email: 'virk@adonisjs.com',
password: 'secret',
})
.toSQL()
.toNative()
console.log(output)
toQuery
Returns the SQL query as a string with bindings applied to the placeholders.
const output = db
.table('users')
.insert({
username: 'virk',
email: 'virk@adonisjs.com',
password: 'secret',
})
.toQuery()
console.log(output)
/**
INSERT INTO "users"
("email", "password", "username")
values
('virk@adonisjs.com', 'secret', 'virk')
*/
Helpful properties and methods
Following is the list of properties and methods you may occasionally need when building something on top of the query builder.
client
Reference to the instance of the underlying database query client.
const query = db.insertQuery()
console.log(query.client)
knexQuery
Reference to the instance of the underlying KnexJS query.
const query = db.insertQuery()
console.log(query.knexQuery)
reporterData
The query builder emits the db:query event and reports the query's execution time with the framework profiler.
Using the reporterData method, you can pass additional details to the event and the profiler.
const query = db.table('users')
await query
.reporterData({ userId: auth.user.id })
.insert({
username: 'virk',
email: 'virk@adonisjs.com',
password: 'secret',
})
Within the db:query event, you can access the value of userId as follows.
import emitter from '@adonisjs/lucid/services/emitter'
emitter.on('db:query', (query) => {
console.log(query.userId)
})