---
id: upsert
title: "Upsert data: upsert()"
slug: upsert
custom_edit_url: https://github.com/supabase/supabase/edit/master/web/spec/supabase.yml
---

import Tabs from '@theme/Tabs';
import TabsPanel from '@theme/TabsPanel';

Performs an UPSERT into the table.

<Tabs
  defaultActiveId="js"
  groupId="reference/supabase-js"
  values={[{ label: 'JavaScript', value: 'js' }]}>

<TabsPanel id="js" label="js">

```js
const { data, error } = await supabase
  .from('messages')
  .upsert({ id: 3, message: 'foo', username: 'supabot' })
```


</TabsPanel>

</Tabs>

## Parameters


<ul className="method-list-group">
  
<li className="method-list-item">
  <h4 className="method-list-item-label">
    <span className="method-list-item-label-name">
      values
    </span>
    <span className="method-list-item-label-badge required">
      required
    </span>
    <span className="method-list-item-validation">
      <code>Partial</code> | <code>array</code>
    </span>
  </h4>
  <div class="method-list-item-description">

The values to insert.

  </div>
  
</li>


<li className="method-list-item">
  <h4 className="method-list-item-label">
    <span className="method-list-item-label-name">
      __namedParameters
    </span>
    <span className="method-list-item-label-badge required">
      required
    </span>
    <span className="method-list-item-validation">
      <code>object</code>
    </span>
  </h4>
  <div class="method-list-item-description">

No description provided. 

  </div>
  
<ul className="method-list-group">
  <h5 class="method-list-title method-list-title-isChild expanded">Properties</h5>

<li className="method-list-item">
  <h4 className="method-list-item-label">
    <span className="method-list-item-label-name">
      returning
    </span>
    <span className="method-list-item-label-badge required">
      required
    </span>
    <span className="method-list-item-validation">
      <code>minimal</code> | <code>representation</code>
    </span>
  </h4>
  <div class="method-list-item-description">

By default the new record is returned. Set this to 'minimal' if you don't need this value.

  </div>
  
</li>


<li className="method-list-item">
  <h4 className="method-list-item-label">
    <span className="method-list-item-label-name">
      onConflict
    </span>
    <span className="method-list-item-label-badge required">
      required
    </span>
    <span className="method-list-item-validation">
      <code>undefined</code> | <code>string</code>
    </span>
  </h4>
  <div class="method-list-item-description">

By specifying the `on_conflict` query parameter, you can make UPSERT work on a column(s) that has a UNIQUE constraint.

  </div>
  
</li>


<li className="method-list-item">
  <h4 className="method-list-item-label">
    <span className="method-list-item-label-name">
      ignoreDuplicates
    </span>
    <span className="method-list-item-label-badge required">
      required
    </span>
    <span className="method-list-item-validation">
      <code>boolean</code>
    </span>
  </h4>
  <div class="method-list-item-description">

Specifies if duplicate rows should be ignored and not inserted.

  </div>
  
</li>


<li className="method-list-item">
  <h4 className="method-list-item-label">
    <span className="method-list-item-label-name">
      count
    </span>
    <span className="method-list-item-label-badge required">
      required
    </span>
    <span className="method-list-item-validation">
      <code>null</code> | <code>exact</code> | <code>planned</code> | <code>estimated</code>
    </span>
  </h4>
  <div class="method-list-item-description">

Count algorithm to use to count rows in a table.

  </div>
  
</li>

</ul>

</li>

</ul>


## Notes

- Primary keys should be included in the data payload in order for an update to work correctly. 
- Primary keys  must be natural, not surrogate. There are however, [workarounds](https://github.com/PostgREST/postgrest/issues/1118) for surrogate primary keys.










## Examples

### Upsert your data



<Tabs
  defaultActiveId="js"
  groupId="reference/supabase-js"
  values={[{ label: 'JavaScript', value: 'js' }]}>

<TabsPanel id="js" label="js">

```js
const { data, error } = await supabase
  .from('messages')
  .upsert({ id: 3, message: 'foo', username: 'supabot' })
```


</TabsPanel>

</Tabs>

### Bulk Upsert your data



<Tabs
  defaultActiveId="js"
  groupId="reference/supabase-js"
  values={[{ label: 'JavaScript', value: 'js' }]}>

<TabsPanel id="js" label="js">

```js
const { data, error } = await supabase
  .from('messages')
  .upsert([
  { id: 3, message: 'foo', username: 'supabot' },
  { id: 4, message: 'bar', username: 'supabot' }
  ])
```


</TabsPanel>

</Tabs>

### Upserting into tables with constraints

Running the following will cause supabase to upsert data into the `users` table. 
If the username 'supabot' already exists, the `onConflict` argument tells supabase to overwrite that row 
based on the column passed into `onConflict`.


<Tabs
  defaultActiveId="js"
  groupId="reference/supabase-js"
  values={[{ label: 'JavaScript', value: 'js' }]}>

<TabsPanel id="js" label="js">

```js
const { data, error } = await supabase
  .from('users')
  .upsert({ username: 'supabot' }, { onConflict: 'username' })
```


</TabsPanel>

</Tabs>

### Return the exact number of rows



<Tabs
  defaultActiveId="js"
  groupId="reference/supabase-js"
  values={[{ label: 'JavaScript', value: 'js' }]}>

<TabsPanel id="js" label="js">

```js
const { data, error, count } = await supabase
  .from('users')
  .upsert({ 
      id: 3, message: 'foo', 
      username: 'supabot' 
  }, { 
    count: 'exact' 
  })
```


</TabsPanel>

</Tabs>