VoltDB Home » Documentation » Using VoltDB


UPSERT — Either inserts new rows or updates existing rows depending on the primary key value.


UPSERT INTO table-name [( column-name [,...] )] VALUES ( value-expression [,...] )

UPSERT INTO table-name [( column-name [,...] )] SELECT select-expression


The UPSERT statement has the same syntax as the INSERT statement and will perform the same function, assuming a record with a matching primary key does not already exist in the database. If such a record does exist, UPSERT updates the existing record with the new column values. Note that the UPSERT statement can only be executed on tables that have a primary key.

UPSERT has the same two forms as the INSERT statement: UPSERT INTO... VALUES and UPSERT INTO... SELECT. The UPSERT statement also has similar constraints and limitations as the INSERT statement with regards to joining partitioned tables and overly complex SELECT clauses. (See the description of the INSERT statement for details.)

However, UPSERT INTO... SELECT has an additional limitation: the SELECT statement must produce deterministically ordered results. That is, the query must not only produce the same rows, they must be in the same order to ensure the subsequent inserts and updates produce identical results.

You can use subqueries within the VALUES clause of the UPSERT statement, with the following provisions:

  • See the description of subqueries in the SELECT statement for general rules concerning the construction of subqueries.

  • In a multi-partition procedure, subqueries of the UPSERT statement can only reference replicated tables.

  • In single-partitioned procedures, the subquery can reference both partitioned and replicated tables.

  • For ad hoc UPSERT statements, the same rules apply except the SQL statement itself determines whether VoltDB executes it as a single-partitoned or multi-partitioned procedure. Statements that modify a partitioned table based on a specific value of the partitioning column are executed as single-partitioned procedures. All other statements are multi-partitioned.


The following examples use two tables, Employee and Manager, both of which define the column emp_id as a primary key. In the first example, the UPSERT statement either creates a new row with the specified values or updates an existing row with the primary key 145303.

UPSERT INTO employee (emp_id, lastname, firstname, title, department) 
       VALUES (145303, 'Public', 'Jane', 'Manager', 'HR');

The next example copies records from the Employee table to the Manager table, if the employee's title is "Manager". Again, new records will be created or existing records updated depending on whether the employee already has a record in the Manager table.

UPSERT  INTO Manager (emp_id, lastname, firstname, title, department)
       SELECT * from Employee WHERE title='Manager' ORDER BY emp_id;