Forgly

SQL to insert or update (upsert)

Insert a row, or update it instead when a key already exists (upsert).

PostgreSQL / SQLite 3.24+
INSERT INTO users (id, email, name)
VALUES (1, 'a@example.com', 'Ann')
ON CONFLICT (id) DO UPDATE
  SET email = EXCLUDED.email,
      name  = EXCLUDED.name;

EXCLUDED refers to the row you tried to insert.

MySQL
INSERT INTO users (id, email, name)
VALUES (1, 'a@example.com', 'Ann')
ON DUPLICATE KEY UPDATE
  email = VALUES(email),
  name  = VALUES(name);
SQL Server
MERGE users AS target
USING (SELECT 1 AS id, 'a@example.com' AS email, 'Ann' AS name) AS src
ON target.id = src.id
WHEN MATCHED THEN
  UPDATE SET email = src.email, name = src.name
WHEN NOT MATCHED THEN
  INSERT (id, email, name) VALUES (src.id, src.email, src.name);

How to insert a row or update it if it already exists

An upsert inserts a new row or, on a unique-key conflict, updates the existing one — avoiding a separate check-then-write.

How it works

  • The conflict target (id) must have a primary key or unique constraint for the upsert to trigger.
  • On conflict, the DO UPDATE / ON DUPLICATE KEY UPDATE branch runs instead of failing.
  • EXCLUDED (Postgres/SQLite) and VALUES() (MySQL) expose the values you attempted to insert.

Related SQL queries

Frequently asked questions

How do I insert a row or update it if it already exists in SQL?

An upsert inserts a new row or, on a unique-key conflict, updates the existing one — avoiding a separate check-then-write. The conflict target (id) must have a primary key or unique constraint for the upsert to trigger. On conflict, the DO UPDATE / ON DUPLICATE KEY UPDATE branch runs instead of failing. EXCLUDED (Postgres/SQLite) and VALUES() (MySQL) expose the values you attempted to insert.

Does this work in PostgreSQL, MySQL, SQL Server, and SQLite?

Yes — this page lists the query for each dialect, since the syntax can differ between database engines.

Can I generate this query for my own tables?

Yes. Describe what you want in plain English with Forgly's free AI SQL Generator and it writes the query for your dialect.