Regex in databases
Most modern databases support regex matching:
- PostgreSQL:
~(case-sensitive),~*(case-insensitive),!~/!~*(negated). Uses POSIX ERE. - MySQL/MariaDB:
REGEXPorRLIKE. Limited POSIX ERE. - SQLite:
REGEXPrequires loading an extension or using a user-defined function. - Snowflake:
RLIKE,REGEXP_LIKE, plusREGEXP_SUBSTR,REGEXP_REPLACE.
Common helper functions across DBs: regexp_replace, regexp_substr, regexp_count.
Unicode in regex — the gotchas
The biggest source of cross-language regex bugs is Unicode handling:
- Python
re: Unicode-aware by default for\d,\w,\s. Usere.ASCIIto revert. - JavaScript: Need
/uflag for proper Unicode.\wstill ASCII-only even with/u— use\p{L}for Unicode letters. - RE2/Go: ASCII-only by default. Use
\p{Nd},\pLfor Unicode categories. - PCRE: ASCII by default;
(*UCP)or/ufor Unicode-aware.
If your data is Unicode, always test the regex against actual Unicode input. ASCII tests don't reveal these bugs.
Performance — the universal rules
- Compile patterns you reuse. One-time cost amortized over many matches.
- Anchor when you can.
^patternstops the engine from trying every position. - Prefer character classes over alternation.
[abc]beatsa|b|c. - Avoid catastrophic backtracking. Patterns like
(a+)+,(a|a)+,(.*)*are exponential. Track 8 covers ReDoS. - For huge files: stream, don't load. Most regex APIs work on iterators or generators.
The takeaway
Regex is dialect-aware. Same idea, slightly different surface in every environment. The Track 1 mental model — "shape language, engine walks the input" — carries everywhere. The 80% portable subset is your home; the rest is dialect lookup when you need it.