141

I'd like to use a regular expression in sqlite, but I don't know how.

My table has got a column with strings like this: "3,12,13,14,19,28,32" Now if I type "where x LIKE '3'" I also get the rows which contain values like 13 or 32, but I'd like to get only the rows which have exactly the value 3 in that string.

Does anyone know how to solve this?

cody
  • 6,389
  • 15
  • 52
  • 77
  • 2
    This answer is the best for adding REGEXP function to sqlite in c# http://stackoverflow.com/a/26155359/5734452 – hubaishan Nov 16 '16 at 08:23

20 Answers20

145

As others pointed out already, REGEXP calls a user defined function which must first be defined and loaded into the the database. Maybe some sqlite distributions or GUI tools include it by default, but my Ubuntu install did not. The solution was

sudo apt-get install sqlite3-pcre

which implements Perl regular expressions in a loadable module in /usr/lib/sqlite3/pcre.so

To be able to use it, you have to load it each time you open the database:

.load /usr/lib/sqlite3/pcre.so

Or you could put that line into your ~/.sqliterc.

Now you can query like this:

SELECT fld FROM tbl WHERE fld REGEXP '\b3\b';

If you want to query directly from the command-line, you can use the -cmd switch to load the library before your SQL:

sqlite3 "$filename" -cmd ".load /usr/lib/sqlite3/pcre.so" "SELECT fld FROM tbl WHERE fld REGEXP '\b3\b';"

If you are on Windows, I guess a similar .dll file should be available somewhere.

mivk
  • 13,452
  • 5
  • 76
  • 69
  • 19
    Another load option: I created a view with this: SELECT load_extension('/usr/lib/sqlite3/pcre.so'); That way when I use a GUI based entry point to the DB (like SQLite Manager in Firefox), I have a way to load the REGEXP capability. – Paulb May 22 '12 at 10:39
  • 7
    SQLite version 3.36.0 released 2021-06-18 now has the `REGEXP` command builtin to the shell. – user1461607 Jul 22 '21 at 11:51
106

SQLite3 supports the REGEXP operator:

WHERE x REGEXP <regex>

http://www.sqlite.org/lang_expr.html#regexp

Nabin
  • 11,216
  • 8
  • 63
  • 98
DanS
  • 17,550
  • 9
  • 53
  • 47
  • 4
    I found an easy way: It's simply \bx\b where x is the value to look for in the string :) – cody Feb 21 '11 at 23:06
  • 15
    @DanS: How do you add a `regex()` function to support the `REGEXP` operator? By default a user function has not been added. – Ken Jun 09 '11 at 04:54
  • 65
    According to the Sqlite docs: The REGEXP operator is a special syntax for the regexp() user function. No regexp() user function is defined by default and so use of the REGEXP operator will normally result in an error message. If a application-defined SQL function named "regexp" is added at run-time, that function will be called in order to implement the REGEXP operator. (http://www.sqlite.org/lang_expr.html#regexp) – radicand Jan 07 '12 at 00:49
  • For those of us who get an error when you try this check out the response below http://stackoverflow.com/a/18484596/1585572 I put the code in a file and imported it on the User-defined Functions in my Firefox sqlite manager. You need to invoke it slightly differently though, like this: SELECT * FROM table WHERE column regexp("myregexp") – Tristan May 30 '14 at 17:16
  • 2
    @ugh! What is the point of adding REGEXP support if it doesn't work out of the box??! – Michael Sep 26 '22 at 22:38
  • @Michael Well I guess it's part of SQLite's philosophy, being light and customizable. It is intended to be embedded in applications, alongside any library you need. Plus it already has builtin pattern matching with the LIKE operator. Also I just tested `REGEXP` in my Linux distribution's SQLite and it works by default. – foxesque Sep 30 '22 at 10:01
36

A hacky way to solve it without regex is where ',' || x || ',' like '%,3,%'

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
30

SQLite does not contain regular expression functionality by default.

It defines a REGEXP operator, but this will fail with an error message unless you or your framework define a user function called regexp(). How you do this will depend on your platform.

If you have a regexp() function defined, you can match an arbitrary integer from a comma-separated list like so:

... WHERE your_column REGEXP "\b" || your_integer || "\b";

But really, it looks like you would find things a whole lot easier if you normalised your database structure by replacing those groups within a single column with a separate row for each number in the comma-separated list. Then you could not only use the = operator instead of a regular expression, but also use more powerful relational tools like joins that SQL provides for you.

Ian Mackinnon
  • 13,381
  • 13
  • 51
  • 67
19

A SQLite UDF in PHP/PDO for the REGEXP keyword that mimics the behavior in MySQL:

$pdo->sqliteCreateFunction('regexp',
    function ($pattern, $data, $delimiter = '~', $modifiers = 'isuS')
    {
        if (isset($pattern, $data) === true)
        {
            return (preg_match(sprintf('%1$s%2$s%1$s%3$s', $delimiter, $pattern, $modifiers), $data) > 0);
        }

        return null;
    }
);

The u modifier is not implemented in MySQL, but I find it useful to have it by default. Examples:

SELECT * FROM "table" WHERE "name" REGEXP 'sql(ite)*';
SELECT * FROM "table" WHERE regexp('sql(ite)*', "name", '#', 's');

If either $data or $pattern is NULL, the result is NULL - just like in MySQL.

Alix Axel
  • 151,645
  • 95
  • 393
  • 500
17

My solution in Python with sqlite3:

import sqlite3
import re

def match(expr, item):
    return re.match(expr, item) is not None

conn = sqlite3.connect(':memory:')
conn.create_function("MATCHES", 2, match)
cursor = conn.cursor()
cursor.execute("SELECT MATCHES('^b', 'busy');")
print cursor.fetchone()[0]

cursor.close()
conn.close()

If regex matches, the output would be 1, otherwise 0.

Nick Chammas
  • 11,843
  • 8
  • 56
  • 115
aGuegu
  • 1,813
  • 1
  • 21
  • 22
11

With python, assuming con is the connection to SQLite, you can define the required UDF by writing:

con.create_function('regexp', 2, lambda x, y: 1 if re.search(x,y) else 0)

Here is a more complete example:

import re
import sqlite3

with sqlite3.connect(":memory:") as con:
    con.create_function('regexp', 2, lambda x, y: 1 if re.search(x,y) else 0)
    cursor = con.cursor()
    # ...
    cursor.execute("SELECT * from person WHERE surname REGEXP '^A' ")


peak
  • 105,803
  • 17
  • 152
  • 177
  • IMHO check should be `if x not Null and y not Null and re.search(x,y)` otherwise it will throw. – pholat Oct 23 '19 at 16:06
7

An exhaustive or'ed where clause can do it without string concatenation:

WHERE ( x == '3' OR
        x LIKE '%,3' OR
        x LIKE '3,%' OR
        x LIKE '%,3,%');

Includes the four cases exact match, end of list, beginning of list, and mid list.

This is more verbose, doesn't require the regex extension.

phyatt
  • 18,472
  • 5
  • 61
  • 80
7

I don't it is good to answer a question which was posted almost an year ago. But I am writing this for those who think that Sqlite itself provide the function REGEXP.

One basic requirement to invoke the function REGEXP in sqlite is
"You should create your own function in the application and then provide the callback link to the sqlite driver".
For that you have to use sqlite_create_function (C interface). You can find the detail from here and here

Naved
  • 4,020
  • 4
  • 31
  • 45
4
UPDATE TableName
 SET YourField = ''
WHERE YourField REGEXP 'YOUR REGEX'

And :

SELECT * from TableName
 WHERE YourField REGEXP 'YOUR REGEX'
4

SQLite version 3.36.0 released 2021-06-18 now has the REGEXP command builtin. For CLI build only.

panofish
  • 7,578
  • 13
  • 55
  • 96
2

You may consider also

WHERE x REGEXP '(^|\D{1})3(\D{1}|$)'

This will allow find number 3 in any string at any position

Avrob
  • 533
  • 2
  • 10
  • 20
2

Consider using this

WHERE x REGEXP '(^|,)(3)(,|$)'

This will match exactly 3 when x is in:

  • 3
  • 3,12,13
  • 12,13,3
  • 12,3,13

Other examples:

WHERE x REGEXP '(^|,)(3|13)(,|$)'

This will match on 3 or 13

itsjavi
  • 2,574
  • 2
  • 21
  • 24
1

If you are using php you can add any function to your sql statement by using: SQLite3::createFunction. In PDO you can use PDO::sqliteCreateFunction and implement the preg_match function within your statement:

See how its done by Havalite (RegExp in SqLite using Php)

code19
  • 75
  • 4
1

You could use a regular expression with REGEXP, but that is a silly way to do an exact match.

You should just say WHERE x = '3'.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • I should have explained it better (sorry for my poor english), I meant only a certain exact value, not the exact string. Thanks anyway! – cody Feb 21 '11 at 22:09
1

In case if someone looking non-regex condition for Android Sqlite, like this string [1,2,3,4,5] then don't forget to add bracket([]) same for other special characters like parenthesis({}) in @phyatt condition

WHERE ( x == '[3]' OR
        x LIKE '%,3]' OR
        x LIKE '[3,%' OR
        x LIKE '%,3,%');
dastan
  • 892
  • 10
  • 17
1

You can use the sqlean-regexp extension, which provides regexp search and replace functions.

Based on the PCRE2 engine, this extension supports all major regular expression features. It also supports Unicode. The extension is available for Windows, Linux, and macOS.

Some usage examples:

-- select messages containing number 3
select * from messages
where msg_text regexp '\b3\b';

-- count messages containing digits
select count(*) from messages
where msg_text regexp '\d+';
-- 42

select regexp_like('Meet me at 10:30', '\d+:\d+');
-- 1

select regexp_substr('Meet me at 10:30', '\d+:\d+');
-- 10:30

select regexp_replace('password = "123456"', '"[^"]+"', '***');
-- password = ***
Anton Zhiyanov
  • 134
  • 1
  • 3
0

In Julia, the model to follow can be illustrated as follows:

using SQLite
using DataFrames

db = SQLite.DB("<name>.db")

register(db, SQLite.regexp, nargs=2, name="regexp")

SQLite.Query(db, "SELECT * FROM test WHERE name REGEXP '^h';") |> DataFrame
peak
  • 105,803
  • 17
  • 152
  • 177
0

for rails

            db = ActiveRecord::Base.connection.raw_connection
            db.create_function('regexp', 2) do |func, pattern, expression|
              func.result = expression.to_s.match(Regexp.new(pattern.to_s, Regexp::IGNORECASE)) ? 1 : 0
            end
0

There's an SQLite extension called sqlite_jq (https://github.com/mgdm/sqlite-jq) which allows one to use jq's regexp functions, which are more powerful that SQLite's as suggested by the second of the following examples.

Using the table created by test_table.sql (https://github.com/mgdm/sqlite-jq/blob/main/test_table.sql)

sqlite> select jq(raw,'.[]|select(.id|test("6$") ).id' ) from test;
24583836616

sqlite> select jq(raw,'.[] | .actor.avatar_url | capture("https://(?<domain>[^.]*)")' ) from test;
[{"domain":"avatars"},{"domain":"avatars"}]

The extension also provides a jq_each() table-valued function.


The neat thing is that the jq() function is marked as "deterministic" and can therefore be used in "CREATE INDEX" commands.

peak
  • 105,803
  • 17
  • 152
  • 177