docs/docs/mutations/postgres/insert.mdx
import GraphiQLIDE from '@site/src/components/GraphiQLIDE';
For example, the auto-generated schema for the insert mutation field for a table article looks like the following:
insert_article (
objects: [article_insert_input!]!
on_conflict: article_on_conflict
): article_mutation_response
# response of any mutation on the table "article"
type article_mutation_response {
# number of affected rows by the mutation
affected_rows: Int!
# data of the affected rows by the mutation
returning: [article!]!
}
# single object insert (supported from v1.2.0)
insert_article_one (
object: article_insert_input!
on_conflict: article_on_conflict
): article
As you can see from the schema:
objects argument is necessary and you can pass multiple objects to the mutation.on_conflict argument to convert the mutation to an
upsert mutation.See the insert mutation API reference for the full specifications.
:::info Note
If a table is not in the public Postgres schema, the insert mutation field will be of the format
insert_<schema_name>_<table_name>.
:::
Example: Insert a new article object and return the inserted article object in the response:
<GraphiQLIDE
query={mutation insert_single_article { insert_article_one( object: { title: "Article 1", content: "Sample article content", author_id: 3 } ) { id title } }}
response={{ "data": { "insert_article_one": { "id": 21, "title": "Article 1" } } }}
/>
Using variables:
<GraphiQLIDE
query={mutation insert_single_article($object: article_insert_input! ) { insert_article_one(object: $object) { id title } }}
response={{ "data": { "insert_article_one": { "id": 21, "title": "Article 1" } } }}
variables={{ "object": { "title": "Article 1", "content": "Sample article content", "author_id": 3 } }}
/>
:::info Note
insert_<object>_one will only be available if you have select permissions on the table, as it returns the inserted
row.
:::
:::tip Supported from
The insert_<object>_one mutation is supported in versions v1.2.0 and above.
:::
Example: Insert 2 new article objects and return both the article objects in the response:
<GraphiQLIDE
query={mutation insert_multiple_articles { insert_article( objects: [ { title: "Article 2", content: "Sample article content", author_id: 4 }, { title: "Article 3", content: "Sample article content", author_id: 5 } ] ) { returning { id title } } }}
response={{ "data": { "insert_article": { "affected_rows": 2, "returning": [ { "id": 22, "title": "Article 2" }, { "id": 23, "title": "Article 3" } ] } } }}
/>
Using variables:
<GraphiQLIDE
query={mutation insert_multiple_articles($objects: [article_insert_input!]! ) { insert_article(objects: $objects) { returning { id title } } }}
response={{ "data": { "insert_article": { "affected_rows": 2, "returning": [ { "id": 22, "title": "Article 2" }, { "id": 23, "title": "Article 3" } ] } } }}
variables={{ "objects": [ { "title": "Article 2", "content": "Sample article content", "author_id": 4 }, { "title": "Article 3", "content": "Sample article content", "author_id": 5 } ] }}
/>
Example: Insert a new article object and return the inserted article object with its author in the response:
<GraphiQLIDE
query={mutation insert_article { insert_article( objects: [ { title: "Article 1", content: "Sample article content", author_id: 3 } ] ) { returning { id title author { id name } } } }}
response={{ "data": { "insert_article": { "affected_rows": 1, "returning": [ { "id": 21, "title": "Article 1", "author": { "id": 3, "name": "Sidney" } } ] } } }}
/>
Let's say an author has an object relationship called address to the addresses table and an array relationship
called articles to the articles table.
Example: Insert an author along with their address and a few articles.
<GraphiQLIDE
query={mutation insertData { insert_authors (objects: [ { name: "John", address: { data: { location: "San Francisco" } }, articles: { data: [ { title: "GraphQL Guide", content: "Let's see what we can do with GraphQL" }, { title: "Authentication Guide", content: "Let's look at best practices for authentication" } ] } } ] ) { affected_rows returning { id name address_id address { id location } articles { id title author_id } } } }}
response={{ "data": { "insert_authors": { "affected_rows": 4, "returning": [ { "id": 26, "name": "John", "address_id": 27, "address": { "id": 27, "location": "San Francisco" }, "articles": [ { "id": 28, "title": "GraphQL Guide", "author_id": 26 }, { "id": 29, "title": "Authentication Guide", "author_id": 26, } ] } ] } } }}
/>
How it works
A nested insert mutation is processed as follows:
The object relationship objects are inserted first, i.e. in this case, the address is inserted and its id is
collected in this step.
The parent object is inserted next. i.e. in this case, the author is now inserted with the address_id being set
to the id of the address that was inserted. Because of this, it is not allowed to pass address_id in the author
object if you are also providing data for the address relationship.
The id of the author is collected in this step.
The array relationship objects are inserted at the end. i.e. in this case, the articles are now inserted with
their author_id set to the author's id collected in the step 2. Hence, it's not possible to specify author_id
in the data for the articles relationship.
:::info Note
The order of object insertion can be controlled using the
insertion_order option while creating a manual relationship.
This is necessary to ensure nested inserts in
one-to-one relationships are possible using either side as the parent which would otherwise error out with a
Not-NULL violation error in one of the cases.
:::
Let's say the articles has a many-to-many relationship with
the tags table via a bridge table article_tags.
Example: Insert an article along with a few tags.
<GraphiQLIDE
query={mutation insertArticle { insert_articles(objects: [ { title: "How to make fajitas", content: "Guide on making the best fajitas in the world", author_id: 3, article_tags: { data: [ { tag: { data: { label: "Recipes" }, on_conflict: { constraint: tags_label_key, update_columns: [label] } } }, { tag: { data: { label: "Cooking" }, on_conflict: { constraint: tags_label_key, update_columns: [label] } } } ] } } ]) { affected_rows returning { id title content author_id article_tags { tag { label } } } } }}
response={{ "data": { "insert_articles": { "affected_rows": 5, "returning": [ { "author_id": 3, "article_tags": [ { "tag": { "label": "Recipes" } }, { "tag": { "label": "Cooking" } } ], "content": "Guide on making the best fajitas in the world", "id": 34, "title": "How to make fajitas" } ] } } }}
/>
How it works
The parent object (from the perspective of article) is inserted first i.e. the article is inserted.
The id of the article is collected in this step.
The array relationship objects (from the perspective of article) are inserted next i.e. the article_tags are
inserted.
The object relationship objects (from the perspective of article_tags) are inserted now i.e. the tags are
now inserted.
The ids of the tags are collected in this step.
The parent object (from the perspective of article_tags) is inserted at the end i.e. the article_tags are
now inserted with their article_id set to the article's id collected in step 1. The tag_id is set to the
tag's id collected in step 2.1. Hence, it’s not possible to specify article_id and tag_id in the data for
the <em>article_tags</em> relationship.
on_conflict
on_conflict can be passed as an argument in a nested insert statement. In our example, we say that if the unique key
(label) already exists for a tag, we update the label of this respective tag (see
nested upsert caveats).
Example: Insert a new author object with a JSONB address field:
<GraphiQLIDE
query={mutation insert_author($address: jsonb) { insert_author ( objects: [ { name: "Ash", address: $address } ] ) { affected_rows returning { id name address } } }}
response={{ "data": { "insert_author": { "affected_rows": 1, "returning": [ { "id": 1, "name": "Ash", "address": { "city": "Bengaluru", "phone": "9090909090", "state": "Karnataka", "pincode": 560095, "street_address": "161, 19th Main Road, Koramangala 6th Block" } } ] } } }}
variables={{ "address": { "street_address": "161, 19th Main Road, Koramangala 6th Block", "city": "Bengaluru", "phone": "9090909090", "state": "Karnataka", "pincode": 560095 } }
/>
Example: Insert a new author with a text array emails field:
<GraphiQLIDE
query={mutation insert_author { insert_author ( objects: [ { name: "Ash", emails: ["[email protected]", "[email protected]"] } ] ) { affected_rows returning { id name emails } } }}
response={{ "data": { "insert_author": { "affected_rows": 1, "returning": [ { "id": 1, "name": "Ash", "emails": ["[email protected]", "[email protected]"] } ] } } }}
/>
Using variables:
<GraphiQLIDE
query={mutation insert_author($emails: _text) { insert_author ( objects: [ { name: "Ash", emails: $emails } ] ) { affected_rows returning { id name emails } } }}
response={{ "data": { "insert_author": { "affected_rows": 1, "returning": [ { "id": 1, "name": "Ash", "emails": ["[email protected]", "[email protected]"] } ] } } }}
variables={{ "emails": "{[email protected], [email protected]}" }}
/>
To insert fields of nested array types, you have to pass them as a Postgres array literal.
To set a field to its default value, just omit it from the input object, irrespective of the
default value configuration i.e. via Postgres defaults or using
column presets.
Example: If the default value of id is set to auto-incrementing integer, there's no need to pass the id field to
the input object:
<GraphiQLIDE
query={mutation insert_article_with_def_id { insert_article( objects: [ { title: "Article 1", content: "Sample article content", author_id: 3 } ] ) { returning { id title } } }}
response={{ "data": { "insert_article": { "affected_rows": 1, "returning": [ { "id": 21, "title": "Article 1" } ] } } }}
/>
If a field is nullable in the database, to set its value to null, either pass its value as null or just omit it
from the input object.
Example: If age is a nullable field, to set it to null, either don't pass the age field to the input object or
pass it as null:
<GraphiQLIDE
query={mutation insert_author_with_null_age { insert_author( objects: [ { name: "Jeff" } ] ) { returning { id name age } } }}
response={{ "data": { "insert_author": { "returning": [ { "id": 11, "name": "Jeff", "age": null } ] } } }}
/>
OR
<GraphiQLIDE
query={mutation insert_author_with_null_age { insert_author( objects: [ { name: "Jeff", age: null } ] ) { returning { id name age } } }}
response={{ "data": { "insert_author": { "returning": [ { "id": 11, "name": "Jeff", "age": null } ] } } }}
/>