Как использовать регулярное выражение в запросе SQLite?


105

Я бы хотел использовать регулярное выражение в sqlite, но не знаю как.

В моей таблице есть столбец с такими строками: «3,12,13,14,19,28,32». Теперь, если я наберу «где x LIKE '3'», я также получу строки, содержащие такие значения, как 13 или 32 , но я хотел бы получить только те строки, которые имеют в этой строке точное значение 3.

Кто-нибудь знает, как это решить?


Этот ответ лучше всего подходит для добавления функции REGEXP в sqlite в С # stackoverflow.com/a/26155359/5734452
hubaishan

Ответы:


74

SQLite3 поддерживает оператор REGEXP:

WHERE x REGEXP <regex>

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


3
Я нашел простой способ: это просто \ bx \ b, где x - значение, которое нужно искать в строке :)
cody

12
@DanS: Как добавить regex()функцию поддержки REGEXPоператора? По умолчанию пользовательская функция не добавлена.
SK9,

48
Согласно документации Sqlite: оператор REGEXP - это специальный синтаксис для пользовательской функции regexp (). По умолчанию пользовательская функция regexp () не определена, поэтому использование оператора REGEXP обычно приводит к сообщению об ошибке. Если определяемая приложением функция SQL с именем «regexp» добавляется во время выполнения, эта функция будет вызываться для реализации оператора REGEXP. ( Sqlite.org/lang_expr.html#regexp )
подкоренное

Для тех из нас, у кого возникает ошибка, когда вы пытаетесь это сделать, ознакомьтесь с ответом ниже stackoverflow.com/a/18484596/1585572 Я поместил код в файл и импортировал его в пользовательские функции в моем диспетчере sqlite Firefox. Однако вам нужно вызвать его немного по-другому, например: SELECT * FROM table WHERE column regexp ("myregexp")
Тристан

Как это принятый ответ? См. Ответ mivk с более высоким рейтингом ниже stackoverflow.com/a/8338515/828885 .
Ахан

114

Как уже указывали другие, REGEXP вызывает определяемую пользователем функцию, которая сначала должна быть определена и загружена в базу данных. Возможно, некоторые дистрибутивы sqlite или инструменты с графическим интерфейсом включают его по умолчанию, но моя установка Ubuntu этого не сделала. Решение было

sudo apt-get install sqlite3-pcre

который реализует регулярные выражения Perl в загружаемом модуле в /usr/lib/sqlite3/pcre.so

Чтобы иметь возможность использовать его, вы должны загружать его каждый раз, когда открываете базу данных:

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

Или вы можете поместить эту строку в свой ~/.sqliterc.

Теперь вы можете запросить вот так:

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

Если вы хотите запросить непосредственно из командной строки, вы можете использовать -cmdпереключатель для загрузки библиотеки перед вашим SQL:

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

Если вы работаете в Windows, я думаю, что где-то должен быть аналогичный файл .dll.


15
Другой вариант загрузки: я создал представление с этим: SELECT load_extension ('/ usr / lib / sqlite3 / pcre.so'); Таким образом, когда я использую точку входа в БД на основе графического интерфейса пользователя (например, SQLite Manager в Firefox), у меня есть способ загрузить возможность REGEXP.
Paulb

30

Хакерский способ решить эту проблему без регулярного выражения - where ',' || x || ',' like '%,3,%'


1
Да, я думал об этом, но нет никаких «ведущих» или «следящих» каждый раз. В любом случае спасибо :-)
cody

Я не наткнулся на проблему здесь - интересно, работает ли это, поскольку x - это имя столбца ...
cody

3
Вы должны использовать',' || x || ','
Барух

22

SQLite по умолчанию не содержит функций регулярных выражений.

Он определяет REGEXPоператор, но это приведет к ошибке с сообщением об ошибке, если вы или ваша платформа не определите вызываемую пользовательскую функциюregexp() . Как вы это сделаете, будет зависеть от вашей платформы.

Если у вас есть определенная regexp()функция, вы можете сопоставить произвольное целое число из списка, разделенного запятыми, например:

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

Но на самом деле, похоже, вам будет намного проще, если вы нормализуете структуру своей базы данных , заменив эти группы в одном столбце отдельной строкой для каждого числа в списке, разделенном запятыми. Тогда вы можете не только использовать =оператор вместо регулярного выражения, но и использовать более мощные реляционные инструменты, такие как объединения, которые предоставляет вам SQL.


14

SQLite UDF в PHP / PDO для REGEXPключевого слова, которое имитирует поведение в 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;
    }
);

uМодификатор не реализован в MySQL, но я считаю , что полезно иметь его по умолчанию. Примеры:

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

Если либо $dataили $patternравно NULL, результат будет NULL - как и в MySQL.


9

мое решение в python с 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()

если регулярное выражение совпадает, вывод будет 1, иначе 0.


5

Я не хочу отвечать на вопрос, который был задан почти год назад. Но я пишу это для тех, кто думает, что сам Sqlite предоставляет функцию REGEXP .

Одно из основных требований для вызова функции REGEXP в sqlite:
«Вы должны создать свою собственную функцию в приложении, а затем предоставить обратную ссылку для драйвера sqlite» .
Для этого вам нужно использовать sqlite_create_function (интерфейс C). Вы можете найти подробности здесь и здесь


4
UPDATE TableName
 SET YourField = ''
WHERE YourField REGEXP 'YOUR REGEX'

И :

SELECT * from TableName
 WHERE YourField REGEXP 'YOUR REGEX'

4

Исчерпывающее предложение or'ed where может делать это без конкатенации строк:

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

Включает четыре случая: точное совпадение, конец списка, начало списка и середину списка.

Это более подробный вариант, не требует расширения регулярного выражения.


4

С python, предполагая, что conэто соединение с SQLite, вы можете определить необходимый UDF, написав:

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

Вот более полный пример:

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' ")


ИМХО проверять надо if x not Null and y not Null and re.search(x,y)иначе выкинут.
pholat

2

Вы можете использовать регулярное выражение с REGEXP , но это глупый способ получить точное соответствие.

Вы должны просто сказать WHERE x = '3'.


Я должен был объяснить это лучше (извините за мой плохой английский), я имел в виду только определенное точное значение, а не точную строку. Спасибо, в любом случае!
cody

2

Рассмотрите возможность использования этого

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

Это будет соответствовать ровно 3, когда x находится в:

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

Другие примеры:

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

Это будет соответствовать 3 или 13


1

В случае, если кто-то ищет условие без регулярного выражения для Android Sqlite , например, эту строку [1,2,3,4,5], не забудьте добавить скобку ( [] ) так же, как и другие специальные символы, такие как скобка ( {} ), в условии @phyatt

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

0

Если вы используете php, вы можете добавить любую функцию в свой оператор sql, используя: SQLite3 :: createFunction . В PDO вы можете использовать PDO :: sqliteCreateFunction и реализовать функцию preg_match в своем операторе:

Посмотрите, как это делается в Havalite ( RegExp в SqLite с использованием Php )


В функции MySQL REGEXP вам не нужно указывать разделители или модификаторы в шаблоне.
Аликс Аксель

0

Вы также можете рассмотреть

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

Это позволит найти цифру 3 в любой строке в любой позиции


0

В Юлии модель, которой нужно следовать, можно проиллюстрировать следующим образом:

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

0

для рельсов

            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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.