Writing Effective SELECT Queries
The pattern has two steps: attempt the insertion with INSERT OR IGNORE, then SELECT the primary key using the value that identifies the record.
A Safe Way to Reuse Records
Many database tasks have the same shape: try to create a record, but reuse it if it already exists. A user may register with a username that is already present. A tag may already be stored. A reference record may need to be created only when it is missing. INSERT OR IGNORE provides the safe insertion step, and a following SELECT can retrieve the record's primary key in either case.
The pattern has two steps: attempt the insertion with INSERT OR IGNORE, then SELECT the primary key using the value that identifies the record.
The Insertion Decision
A normal INSERT that violates a constraint raises an error and rejects the operation. INSERT OR IGNORE changes that behavior in SQLite. If the new row would violate a constraint, the database does not add the row and does not raise an error for that insertion. The program continues. If no constraint is violated, the row is inserted normally.
A Two-Step Primary-Key Pattern
The insertion alone does not solve every application problem. Often, the application needs the primary key of the record so it can reference that record elsewhere. The record might be new, or it might already exist. The reliable pattern is to first execute INSERT OR IGNORE and then immediately execute SELECT to retrieve the primary key.
INSERT OR IGNORE INTO users (username)
VALUES ('maya');
SELECT user_id
FROM users
WHERE username = 'maya';- 1First, the database evaluates the INSERT OR IGNORE statement.
- 2If maya is new and the insertion satisfies the constraints, a row is added.
- 3If maya already exists under a relevant constraint, no duplicate row is added.
- 4The SELECT then retrieves the
user_idfor the row identified by username.
- The first statement attempts to add the username and quietly skips the insertion if a constraint would be violated.
- The second statement searches for the username and retrieves its primary key.
The SELECT is what gives the application the primary key. INSERT OR IGNORE ensures that the target record is present without allowing a duplicate constraint violation to interrupt the insertion step.
Why UNIQUE Matters
A UNIQUE constraint is a rule on one or more columns that restricts duplicate values. For a column with a UNIQUE constraint, no two rows can have the same value in that column, except that NULL is often treated as a special case.
| Column situation | Effect of duplicate value | Effect on INSERT OR IGNORE |
|---|---|---|
| UNIQUE constraint present | The duplicate violates a constraint | The insertion is skipped |
| No UNIQUE constraint | The duplicate value is allowed | The row is added, assuming no other constraint is violated |
A uniqueness constraint determines whether a repeated value counts as a duplicate for constraint handling.
The follow-up SELECT is reliable when the value used to find the record is protected by a UNIQUE constraint. That constraint guarantees that the value maps to exactly one row. Without it, duplicate values are allowed. For example, if eye_color has no UNIQUE constraint, many rows may contain Blue. INSERT OR IGNORE has no uniqueness violation to ignore in that situation, and a SELECT for Blue cannot use uniqueness to identify one specific row.
A Registration Example
Reuse an Existing Username Record
Ensure that the username maya exists in users, then obtain the corresponding user_id without allowing a duplicate username insertion to interrupt the program.
- 1Attempt the insert
Execute INSERT OR IGNORE for maya. If the username is new and the constraints are satisfied, the database adds the row.
- 2Handle an existing username
If maya already exists under the UNIQUE username constraint, the attempted insertion is silently skipped rather than raising an error.
- 3Retrieve the identifier
Execute SELECT for the
user_idwhere username is maya. Because username is unique, the value identifies exactly one row.
The application can use the primary key for the existing or newly inserted user record.
INSERT INTO users (username)
VALUES ('maya');A duplicate username causes the normal INSERT operation to raise an error and reject the operation.
INSERT OR IGNORE INTO users (username)
VALUES ('maya');A duplicate username causes the insertion to be skipped, while the program continues without an error from that insertion.
Constraints Beyond Uniqueness
INSERT OR IGNORE can handle violations of constraints other than UNIQUE. The source examples include NOT NULL, which requires a column to have a value, FOREIGN KEY, which requires a value to reference an existing row in another table, and CHECK, which requires a value to satisfy a condition. However, the follow-up SELECT pattern is most reliable with a UNIQUE constraint because uniqueness guarantees that the identifying value maps to exactly one row.
Common mistake Assuming every repeated value creates a constraint violation.
What it looks likeUsing INSERT OR IGNORE with an eye_color column that has no UNIQUE constraint.
Why it failsWithout a UNIQUE constraint, repeated values are allowed, so there is no duplicate violation for INSERT OR IGNORE to ignore.
Do this insteadConfirm that the value used to identify the record is governed by a UNIQUE constraint.
Common mistake Expecting INSERT OR IGNORE to update an existing row.
What it looks likeAttempting to insert a username that already exists and expecting its other data to be replaced.
Why it failsWhen a constraint would be violated, the attempted insertion is skipped; the source describes no replacement or update.
Do this insteadUse INSERT OR IGNORE only when skipping the attempted insertion is the desired behavior.
Common mistake Using the follow-up SELECT without a unique identifying value.
What it looks likeSelecting a primary key with WHERE eye_color = 'Blue' when eye_color is not unique.
Why it failsMultiple rows may have the same value, so the value does not identify exactly one record.
Do this insteadSelect with the value protected by a UNIQUE constraint when the goal is to retrieve one record's primary key.
Common mistake Assuming the pattern reveals whether insertion occurred.
What it looks likeTreating the successful completion of INSERT OR IGNORE as proof that a new row was added.
Why it failsThe insertion may have been silently skipped because the record already existed.
Do this insteadUse a different approach when application logic must distinguish a new insertion from an ignored duplicate.
Practice the Decision
What do you think happens?
A users table has a UNIQUE constraint on username. The username maya already exists. What happens when this statement runs?
Reveal answer
The insertion is skipped and the program continues.
INSERT OR IGNORE silently skips an insertion that would violate a constraint. The existing row remains available for the following SELECT.
Describe the two statements you would use to ensure that a tag named urgent exists and then retrieve its primary key. State which column must have a UNIQUE constraint for the lookup to identify one row reliably.
Hints
- The first statement should use INSERT OR IGNORE.
- The second statement should use SELECT to retrieve the primary key.
- The identifying tag value should be protected by a UNIQUE constraint.
Pattern Checklist
- 1Identify the value that should occur only once, such as a username or tag name.
- 2Ensure that the identifying column has a UNIQUE constraint.
- 3Attempt the insertion with INSERT OR IGNORE.
- 4Run SELECT to retrieve the primary key using the unique value.
- 5Use another approach if the application must know whether the row was newly inserted or already existed.
INSERT OR IGNORE is a graceful way to handle constraint violations when an existing record can be reused. Its most useful form is the two-step pattern: attempt the insertion, then select the primary key. The UNIQUE constraint is essential because it prevents duplicate identifying values and makes the primary-key lookup reliable.
Key Takeaways
- INSERT OR IGNORE skips an insertion that would violate a constraint instead of raising an error for that insertion.
- Pair INSERT OR IGNORE with SELECT to ensure a record exists and retrieve its primary key.
- A UNIQUE constraint makes the identifying value map to exactly one row.
- Without a UNIQUE constraint, repeated values are allowed and the insertion may proceed normally.
- Use a different approach when the application must distinguish a newly inserted row from an ignored duplicate.