**I'd consider that a bug myself**, unlike Simon and Keith, because SQLite strives for PostgreSQL compatibility, and PostgreSQL gets this right: ``` [ddevienne@nemo ~]$ psql Password for user ddevienne: psql (11.2, server 12.0) WARNING: psql major version 11, server major version 12. Some psql features might not work. Type "help" for help. ddevienne=> create table t (v text); CREATE TABLE ddevienne=> insert into t values ('100%'), ('100 percent'); INSERT 0 2 ddevienne=> select v from t; v ------------- 100% 100 percent (2 rows) ddevienne=> select v from t where v like '100%%' escape '%'; v ------ 100% (1 row) ``` I had a quick look at SQLite's impl (which as a reminder, just in case, is nicely exposed as a public API, `sqlite3_strlike()`), and this is because that impl attempts to first *compress* the *like-pattern* to consecutive `matchAll` characters (`'%'` here), **before** testing the `matchOther` escape-character: ``` static int patternCompare( const u8 *zPattern, /* The glob pattern */ const u8 *zString, /* The string to compare against the glob */ const struct compareInfo *pInfo, /* Information about how to do the compare */ u32 matchOther /* The escape char (LIKE) or '[' (GLOB) */ ){ u32 c, c2; /* Next pattern and input string chars */ u32 matchOne = pInfo->matchOne; /* "?" or "_" */ u32 matchAll = pInfo->matchAll; /* "*" or "%" */ u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */ const u8 *zEscaped = 0; /* One past the last escaped input char */ while( (c = Utf8Read(zPattern))!=0 ){ if( c==matchAll ){ /* Match "*" */ /* Skip over multiple "*" characters in the pattern. If there ** are also "?" characters, skip those as well, but consume a ** single character of the input string for each "?" skipped */ while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){ ``` The fact the doc never mentions the escape character cannot be `'%'` puts this in the fuzzy *unspecified* category, but again, Richard usually considers PostgreSQL as the reference, so I hope he'll fix this. --DD