SQL-Engineering-Handbook

02 — String Search & Extraction

🏠 Module Home · 🗂️ Handbook Home · ← 01 Basic String Functions · Next → 03 String Transformation

String Search and Extraction

Introduction

Once text is cleaned and normalized, the next recurring need is finding things inside it: does this email contain a domain you recognize, does this product code match a known prefix pattern, what comes after the third delimiter in this pipe-separated reference number. This topic covers SQL’s search and extraction toolkit using an e-commerce schema — customer emails, order reference codes, and product SKUs.

Concept Overview

Search and extraction split into two concerns:

  1. Search — does a pattern exist, and where: LOCATE(), POSITION(), INSTR(), LIKE, REGEXP
  2. Extraction — pull out a specific piece based on a delimiter or position: SUBSTRING_INDEX(), combined with LOCATE()/POSITION()

LOCATE()/POSITION()/INSTR() are functionally overlapping but engine-specific in syntax; this topic treats them as a family and calls out the differences explicitly.

Business Motivation

Structured-looking text — emails, SKUs, order references, tracking numbers — is often the only place certain business information lives. A product’s category might only exist as a prefix in its SKU. A customer’s email domain might be the only signal for identifying corporate versus personal accounts. Extracting these values in SQL avoids exporting raw data to a scripting language just to parse it.

Why These Functions Exist

Fixed-position slicing (LEFT/RIGHT/SUBSTRING with hard-coded offsets, from Topic 01) breaks the moment a field’s format isn’t perfectly consistent. Search and extraction functions exist to make slicing relative to content — “everything after the @ symbol,” “everything before the second dash” — rather than relative to a fixed character position, which is far more robust against real-world formatting drift.

Real Company Use Cases

Functions Covered

Function Purpose
LOCATE() Position of a substring (MySQL-style, args: substring first)
POSITION() ANSI-standard position search: POSITION(substr IN str)
INSTR() Position search (Oracle/MySQL-style, args: string first)
LIKE Pattern match using % and _ wildcards
REGEXP Pattern match using full regular expressions
SUBSTRING_INDEX() Returns the substring before/after the Nth occurrence of a delimiter (MySQL)

Syntax

LOCATE(substr, str [, start_pos])
POSITION(substr IN str)
INSTR(str, substr)
str LIKE pattern
str REGEXP pattern
SUBSTRING_INDEX(str, delimiter, count)

Parameters

Return Values

ASCII Visual Explanation

email = "j.martinez@globalretailcorp.com"

SUBSTRING_INDEX(email, '@', -1)
        →  "globalretailcorp.com"
                          ^^^^^^^^^^^^^^^^^^^^^ everything after the LAST '@'

SUBSTRING_INDEX(email, '@', 1)
        →  "j.martinez"
             ^^^^^^^^^^ everything before the FIRST '@'

Step-by-Step Examples

Goal: Classify customer accounts as corporate or personal based on email domain.

SELECT
    customer_email,
    SUBSTRING_INDEX(customer_email, '@', -1) AS email_domain,
    CASE
        WHEN customer_email LIKE '%@gmail.com'
          OR customer_email LIKE '%@yahoo.com'
          OR customer_email LIKE '%@outlook.com'
            THEN 'Personal'
        ELSE 'Likely Corporate'
    END AS account_classification
FROM customers;

Reasoning: SUBSTRING_INDEX(..., -1) isolates everything after the last @, which correctly handles the (rare but valid) case of a local part containing @ inside quotes. LIKE with trailing-anchored patterns then checks against known free-email providers.

Production Considerations

Performance Notes

Edge Cases

Common Mistakes

Interview Questions

  1. What’s the difference between LOCATE(), POSITION(), and INSTR(), and why do three functions doing roughly the same thing exist across SQL engines?
  2. Given an email column, write a query to extract just the domain, and explain why you chose -1 vs 1 as the SUBSTRING_INDEX count.
  3. Why is LIKE '%value%' generally slower than LIKE 'value%' on a large indexed table?
  4. When would you choose REGEXP over LIKE, and what’s the performance trade-off?

Practice Challenges

  1. Given a tracking_number column formatted as CARRIER-REGION-SEQUENCE (e.g., FEDX-EU-88213), extract just the carrier code.
  2. Write a query flagging any customer email that does not contain an @ symbol at all, as a basic validity check.
  3. Using SUBSTRING_INDEX() twice, extract the middle segment (REGION) from the tracking number format above.

Summary

Search and extraction functions make string parsing robust to content rather than dependent on fixed positions. LOCATE/POSITION/INSTR answer “where,” LIKE/REGEXP answer “does this match,” and SUBSTRING_INDEX answers “give me the piece before/after a delimiter” — together they cover the majority of real-world text-parsing needs without leaving SQL.

Further Reading


⬆ Back to top · 🏠 Module Home · 🗂️ Handbook Home