Як використовувати регекс у запиті SQLite?


102

Я хотів би використовувати регулярний вираз у sqlite, але не знаю як.

У моїй таблиці є стовпець із такими рядками: "3,12,13,14,19,28,32" Тепер, якщо я набираю "де x LIKE '3" "я також отримую рядки, які містять значення, такі як 13 або 32 , але я хотів би отримати лише ті рядки, які мають саме значення 3 у цьому рядку.

Хтось знає, як це вирішити?


Ця відповідь є найкращим для додавання функції REGEXP в SQLite в C # 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

47
Згідно з документами Sqlite: Оператор REGEXP - це спеціальний синтаксис функції користувача regexp (). Жодна користувацька функція regexp () не визначена за замовчуванням, тому використання оператора REGEXP зазвичай призводить до повідомлення про помилку. Якщо під час виконання додана визначена додатком функція SQL під назвою "regexp", ця функція буде викликана для реалізації оператора REGEXP. ( Sqlite.org/lang_expr.html#regexp )
підкореневе

Для тих із нас, хто отримує помилку при спробі перевірити відповідь нижче stackoverflow.com/a/18484596/1585572, я помістив код у файл та імпортував його у визначені користувачем функції у своєму менеджері sqlite Firefox. Потрібно викликати його дещо інакше, окрім цього: ВИБІР * З таблиці, де стовпець regexp ("myregexp")
Трістан

112

Як вже вказували інші, 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'); Таким чином, коли я використовую точку входу в БД, засновану на GUI (як SQLite Manager у Firefox), у мене є спосіб завантажити можливість REGEXP.
Павло

30

Хитрий спосіб вирішити це без регулярного вираження where ',' || x || ',' like '%,3,%'


1
Так, я подумав про це, але не існує ведучого та наступного "", кожного разу. Все одно дякую :-)
коді

Я не спіткнувся з проблемою тут - мені цікаво, чи це працює як x - назва стовпця ...
cody

3
Вам слід скористатися',' || x || ','
Барух

21

За замовчуванням 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.


8

моє рішення в 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

Вичерпний або зв'язаний текст, коли стаття може це зробити без з'єднання рядків:

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)інакше це кине.
фолат

2

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

Ви просто повинні сказати WHERE x = '3'.


Я повинен був би пояснити це краще (вибачте за мою погану англійську мову), я мав на увазі лише певне точне значення, а не точну рядок. Все одно, дякую!
Коді

2

Подумайте про використання цього

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

Це відповідатиме рівно 3, коли х знаходиться в:

  • 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.