“Find ‘acme’ whether it’s stored as ACME or Acme.” The portable approach is to lower-case both sides:
SELECT * FROM companies
WHERE LOWER(name) = LOWER(:q); -- exact, case-insensitive
SELECT * FROM companies
WHERE LOWER(name) LIKE LOWER(:q) || '%'; -- prefix search
Dialect shortcuts:
- PostgreSQL / DuckDB:
ILIKEdoes a case-insensitiveLIKE:WHERE name ILIKE :q. - MySQL: the default collation is usually case-insensitive (
..._ci), so plain=andLIKEalready ignore case. Force it withWHERE name LIKE :q COLLATE utf8mb4_general_ciif needed. - SQLite:
LIKEis case-insensitive for ASCII by default;=is case-sensitive. UseLOWER()for reliable Unicode behavior. - Snowflake: string comparison is case-sensitive by default — use
ILIKEorLOWER(). - BigQuery: case-sensitive — use
LOWER(), orREGEXP_CONTAINS(name, r'(?i)acme').
Keep it index-friendly.
WHERE LOWER(name) = LOWER(:q)can’t use a plain index onname. Add a functional index on the expression (Postgres/SQLite:CREATE INDEX ON companies (LOWER(name));), or store a normalizedname_lowercolumn and index that. For accent-insensitive matching too, use a case- and accent-insensitive collation (e.g. Postgrescitext/ICU collations,und-ci-ai).