Como faço para usar regex em uma consulta SQLite?

102

Gostaria de usar uma expressão regular no sqlite, mas não sei como.

Minha tabela tem uma coluna com strings como esta: "3,12,13,14,19,28,32" Agora, se eu digitar "where x LIKE '3'", também obtenho as linhas que contêm valores como 13 ou 32 , mas gostaria de obter apenas as linhas que têm exatamente o valor 3 nessa string.

Alguém sabe como resolver isso?

cody
fonte
Esta resposta é a melhor para adicionar a função REGEXP ao sqlite em c # stackoverflow.com/a/26155359/5734452
hubaishan

Respostas:

74

SQLite3 suporta o operador REGEXP:

WHERE x REGEXP <regex>

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

DanS
fonte
3
Encontrei uma maneira fácil: é simplesmente \ bx \ b, em que x é o valor a ser procurado na string :)
cody
12
@DanS: Como você adiciona uma regex()função para dar suporte ao REGEXPoperador? Por padrão, uma função de usuário não foi adicionada.
SK9
47
De acordo com os documentos do Sqlite: O operador REGEXP é uma sintaxe especial para a função de usuário regexp (). Nenhuma função de usuário regexp () é definida por padrão e, portanto, o uso do operador REGEXP normalmente resultará em uma mensagem de erro. Se uma função SQL definida pelo aplicativo chamada "regexp" for adicionada em tempo de execução, essa função será chamada para implementar o operador REGEXP. ( sqlite.org/lang_expr.html#regexp )
radicand
Para aqueles de nós que obtêm um erro ao tentar fazer isso, verifique a resposta abaixo stackoverflow.com/a/18484596/1585572 Eu coloquei o código em um arquivo e importei-o nas Funções definidas pelo usuário em meu gerenciador de sqlite do Firefox. Você precisa invocá-lo de forma um pouco diferente, como este: SELECT * FROM tabela WHERE coluna regexp ("myregexp")
Tristan
112

Como outros já apontaram, REGEXP chama uma função definida pelo usuário que deve primeiro ser definida e carregada no banco de dados. Talvez algumas distribuições sqlite ou ferramentas GUI incluam por padrão, mas minha instalação do Ubuntu não. A solução foi

sudo apt-get install sqlite3-pcre

que implementa expressões regulares Perl em um módulo carregável em /usr/lib/sqlite3/pcre.so

Para poder usá-lo, você deve carregá-lo toda vez que abrir o banco de dados:

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

Ou você pode colocar essa linha no seu ~/.sqliterc.

Agora você pode consultar assim:

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

Se você deseja consultar diretamente da linha de comando, pode usar a -cmdopção para carregar a biblioteca antes do SQL:

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

Se você estiver no Windows, acho que um arquivo .dll semelhante deve estar disponível em algum lugar.

mivk
fonte
15
Outra opção de carregamento: Criei uma visão com este: SELECT load_extension ('/ usr / lib / sqlite3 / pcre.so'); Dessa forma, quando eu uso um ponto de entrada baseado em GUI para o banco de dados (como SQLite Manager no Firefox), tenho uma maneira de carregar o recurso REGEXP.
Paulb de
30

Uma maneira hacky de resolvê-lo sem regex é where ',' || x || ',' like '%,3,%'

Blorgbeard está fora
fonte
1
Sim, eu pensei dessa forma, mas não há orientação ou seguimento "," toda vez. Obrigado de qualquer maneira :-)
cody
Não me deparei com o problema aqui - me pergunto se isso funciona porque x é o nome da coluna ...
cody
3
Você deve usar',' || x || ','
Baruch
21

O SQLite não contém funcionalidade de expressão regular por padrão.

Ele define um REGEXPoperador, mas falhará com uma mensagem de erro, a menos que você ou sua estrutura definam uma função de usuário chamadaregexp() . Como você fará isso dependerá da sua plataforma.

Se você tem uma regexp()função definida, pode corresponder a um número inteiro arbitrário de uma lista separada por vírgulas da seguinte forma:

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

Mas, realmente, parece que você achará as coisas muito mais fáceis se normalizar a estrutura do seu banco de dados substituindo esses grupos em uma única coluna por uma linha separada para cada número na lista separada por vírgulas. Então, você não poderia apenas usar o =operador em vez de uma expressão regular, mas também usar ferramentas relacionais mais poderosas, como junções, que o SQL fornece para você.

Ian Mackinnon
fonte
14

Um UDF SQLite em PHP / PDO para a REGEXPpalavra - chave que simula o comportamento no 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;
    }
);

O umodificador não está implementado no MySQL, mas acho útil tê-lo por padrão. Exemplos:

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

Se $dataou $patternfor NULL, o resultado será NULL - exatamente como no MySQL.

Alix Axel
fonte
8

minha solução em python com 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()

se regex corresponder, a saída será 1, caso contrário, 0.

aGuegu
fonte
5

Não é bom responder a uma pergunta que foi postada quase um ano atrás. Mas estou escrevendo isso para aqueles que pensam que o próprio Sqlite fornece a função REGEXP .

Um requisito básico para invocar a função REGEXP no sqlite é
"Você deve criar sua própria função no aplicativo e, em seguida, fornecer o link de retorno de chamada para o driver sqlite" .
Para isso você deve usar sqlite_create_function (interface C). Você pode encontrar os detalhes aqui e aqui

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

E:

SELECT * from TableName
 WHERE YourField REGEXP 'YOUR REGEX'

fonte
4

Uma exaustiva cláusula or'ed where pode fazer isso sem concatenação de string:

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

Inclui a correspondência exata de quatro casos, fim da lista, início da lista e lista intermediária.

Isso é mais detalhado, não requer a extensão regex.

Phyatt
fonte
4

Com o python, supondo que conseja a conexão com o SQLite, você pode definir a UDF necessária escrevendo:

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

Aqui está um exemplo mais completo:

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

pico
fonte
Verificação IMHO deve ser if x not Null and y not Null and re.search(x,y)caso contrário, ele vai jogar.
pholat
2

Você pode usar uma expressão regular com REGEXP , mas essa é uma maneira boba de fazer uma correspondência exata.

Você deveria apenas dizer WHERE x = '3'.

Quentin
fonte
Eu deveria ter explicado melhor (desculpe pelo meu inglês pobre), eu quis dizer apenas um determinado valor exato, não a string exata. Obrigado mesmo assim!
cody
2

Considere usar isso

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

Isso corresponderá exatamente a 3 quando x estiver em:

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

Outros exemplos:

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

Isso vai combinar em 3 ou 13

itsjavi
fonte
1

No caso de alguém procurando uma condição sem regex para Android Sqlite , como esta string [1,2,3,4,5], não se esqueça de adicionar colchetes ( [] ) mesmo para outros caracteres especiais como parênteses ( {} ) na condição @phyatt

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

Se estiver usando php, você pode adicionar qualquer função à instrução sql usando: SQLite3 :: createFunction . No PDO, você pode usar PDO :: sqliteCreateFunction e implementar a função preg_match em sua instrução:

Veja como é feito por Havalite ( RegExp em SqLite usando Php )

código 19
fonte
Na função MySQL REGEXP você não precisa especificar os delimitadores ou modificadores no padrão.
Alix Axel
0

Você pode considerar também

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

Isso permitirá encontrar o número 3 em qualquer string em qualquer posição

Avrob
fonte
0

Em Julia, o modelo a seguir pode ser ilustrado da seguinte forma:

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
pico
fonte
0

para trilhos

            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
Xian Kai Ng
fonte