MySql: Upsert options

I was asked a question about doing an insert to a table with a unique index and id and to always set the field active if it exists. There are a multiple ways to do this, but I reached for the one that isn't actually available in MySql because I was remembering Postgres syntax. In Postgres you would do a Merge statement and mark the conditions. My mistake got to many database formats and rules in my head.

Given a table structured like this

CREATE TABLE employees (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  cust_id INT UNSIGNED DEFAULT NULL,
  emp_name NVARCHAR(100) NOT NULL,
  active BIT DEFAULT 0,
  PRIMARY KEY (id),
  UNIQUE (emp_name)
);

Insert or update all employees named Bill to be active

Merge way to do it

MERGE INTO employees ee
USING (SELECT id FROM employee WHERE emp_name = 'Bill') AS t
ON t.id = ee.id
WHEN MATCHED THEN
  UPDATE SET active = 1
WHEN NOT MATCHED THEN
  INSERT (cust_id, emp_name, active)
  VALUES (1, 'Bill', 1);

But we don't have merge in MySql

Two statements approach

  • Update if exists
  • Insert with a query if doesn't exist
update employees
INNER JOIN
(
        SELECT id
        From employees
        WHERE emp_name IN
        (
            'Bill'
        )
) as u
on employees.id = u.id
SET employees.active = 1;
INSERT INTO employees (cust_id, emp_name, active)
select 1, 'Bill', 1
from employees
where emp_name <> 'Bill';

This works, but it is two statements and there is a way to do it in a single statement for clarity by relying on the uniqueness of the emp_name field

Insert into ON DUPLICATE KEY

INSERT INTO employees (cust_id, emp_name, active) VALUES (1, 'Bill', 1)
ON DUPLICATE KEY UPDATE active=1;

This is what most people would pick because it does an in place update and is one line.

Use Replace

REPLACE INTO employees (cust_id, emp_name, active)
VALUES (1, 'Bill', 1);

Using replace has the drawback of deleting and incrementing the id because it does a delete and insert to accomplish the task and that could have implications for caching and in process queries.