SQL Practice Logo

SQLPractice Online

MERGE/UPSERT: Mistakes

Module: Data Modification & Transactions

No Unique Constraint on Conflict Column

-- Table without unique constraint

CREATE TABLE users (

user_id INT,

username VARCHAR(50),

email VARCHAR(100)

);

-- UPSERT fails: no unique constraint

INSERT INTO users (user_id, username, email)

VALUES (1, 'john_doe', 'john@example.com')

ON CONFLICT (user_id) DO UPDATE SET email = EXCLUDED.email;

-- Error: there is no unique or exclusion constraint matching the ON CONFLICT specification

-- Add unique constraint or primary key

CREATE TABLE users (

user_id INT PRIMARY KEY, -- Primary key

username VARCHAR(50),

email VARCHAR(100) UNIQUE -- Unique constraint

);

-- Or add unique index

CREATE UNIQUE INDEX idx_users_user_id ON users(user_id);

-- Now UPSERT works

INSERT INTO users (user_id, username, email)

VALUES (1, 'john_doe', 'john@example.com')

ON CONFLICT (user_id) DO UPDATE SET email = EXCLUDED.email;

UPSERT requires UNIQUE constraint or PRIMARY KEY on conflict column to detect duplicates. Without constraint, database cannot determine if row exists. PostgreSQL throws error immediately. MySQL silently checks all UNIQUE indexes (can match wrong column). Solution: Add PRIMARY KEY or UNIQUE constraint on conflict column. Use CREATE UNIQUE INDEX if cannot modify table structure. Verify constraint exists before UPSERT: SELECT * FROM pg_indexes WHERE tablename = users; Real-world: Common mistake in development when testing UPSERT on table without proper constraints.

Always ensure conflict column has UNIQUE constraint or PRIMARY KEY. Use CREATE UNIQUE INDEX if cannot modify table. Verify with pg_indexes or SHOW INDEXES.

Critical

PostgreSQL: "there is no unique or exclusion constraint matching the ON CONFLICT specification". MySQL: Works but checks all UNIQUE indexes (can cause unexpected behavior).

graph TB

subgraph "Wrong: No Unique Constraint"

W1["CREATE TABLE users<br/>user_id INT (no constraint)"]

W2["INSERT...ON CONFLICT (user_id)"]

W3["Error: No unique constraint"]

W4["UPSERT fails"]

end

subgraph "Correct: With Unique Constraint"

C1["CREATE TABLE users<br/>user_id INT PRIMARY KEY"]

C2["INSERT...ON CONFLICT (user_id)"]

C3["Conflict detected via index"]

C4["UPSERT succeeds"]