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?


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


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.


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,%'


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


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.


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.


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


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

E:

SELECT * from TableName
 WHERE YourField REGEXP 'YOUR REGEX'

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.


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


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


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


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,%');


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


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

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.