¿Cómo uso expresiones regulares en una consulta SQLite?

102

Me gustaría usar una expresión regular en sqlite, pero no sé cómo.

Mi tabla tiene una columna con cadenas como esta: "3,12,13,14,19,28,32" Ahora si escribo "donde x LIKE '3'" también obtengo las filas que contienen valores como 13 o 32 , pero me gustaría obtener solo las filas que tienen exactamente el valor 3 en esa cadena.

Alguien sabe cómo resolver esto?

cody
fuente
Esta respuesta es la mejor para agregar la función REGEXP a sqlite en c # stackoverflow.com/a/26155359/5734452
hubaishan

Respuestas:

74

SQLite3 admite el operador REGEXP:

WHERE x REGEXP <regex>

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

DanS
fuente
3
Encontré una manera fácil: es simplemente \ bx \ b donde x es el valor a buscar en la cadena :)
cody
12
@DanS: ¿Cómo se agrega una regex()función para apoyar al REGEXPoperador? Por defecto, no se ha agregado una función de usuario.
SK9
47
Según los documentos de Sqlite: El operador REGEXP es una sintaxis especial para la función de usuario regexp (). Ninguna función de usuario regexp () está definida por defecto y, por lo tanto, el uso del operador REGEXP normalmente dará como resultado un mensaje de error. Si se agrega una función SQL definida por la aplicación denominada "regexp" en tiempo de ejecución, se llamará a esa función para implementar el operador REGEXP. ( sqlite.org/lang_expr.html#regexp )
radicand
Para aquellos de nosotros que obtenemos un error cuando intenta esto, consulte la respuesta a continuación stackoverflow.com/a/18484596/1585572 Puse el código en un archivo y lo importé en las Funciones definidas por el usuario en mi administrador de sqlite de Firefox. Sin embargo, debe invocarlo de manera ligeramente diferente, así: SELECT * FROM table WHERE column regexp ("myregexp")
Tristan
112

Como ya han señalado otros, REGEXP llama a una función definida por el usuario que primero debe definirse y cargarse en la base de datos. Tal vez algunas distribuciones sqlite o herramientas GUI lo incluyan de forma predeterminada, pero mi instalación de Ubuntu no lo hizo. La solucion fue

sudo apt-get install sqlite3-pcre

que implementa expresiones regulares de Perl en un módulo cargable en /usr/lib/sqlite3/pcre.so

Para poder usarlo, debes cargarlo cada vez que abras la base de datos:

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

O podrías poner esa línea en tu ~/.sqliterc.

Ahora puedes realizar consultas como esta:

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

Si desea realizar consultas directamente desde la línea de comandos, puede usar el -cmdconmutador para cargar la biblioteca antes de su SQL:

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

Si está en Windows, supongo que un archivo .dll similar debería estar disponible en alguna parte.

mivk
fuente
15
Otra opción de carga: creé una vista con esto: SELECT load_extension ('/ usr / lib / sqlite3 / pcre.so'); De esa manera, cuando uso un punto de entrada basado en GUI a la base de datos (como SQLite Manager en Firefox), tengo una forma de cargar la capacidad REGEXP.
Paulb
30

Una forma hacky de resolverlo sin regex es where ',' || x || ',' like '%,3,%'

Blorgbeard está fuera
fuente
1
Sí, lo pensé de esa manera, pero no hay "guiar ni seguir" siempre. Gracias de todos modos :-)
cody
No encontré el problema aquí, me pregunto si esto funciona ya que x es el nombre de la columna ...
cody
3
Deberías usar',' || x || ','
Baruch
21

SQLite no contiene la funcionalidad de expresión regular de forma predeterminada.

Define un REGEXPoperador, pero esto fallará con un mensaje de error a menos que usted o su marco definan una función de usuario llamada regexp(). La forma de hacerlo dependerá de su plataforma.

Si tiene una regexp()función definida, puede hacer coincidir un entero arbitrario de una lista separada por comas así:

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

Pero realmente, parece que las cosas le resultarían mucho más fáciles si normalizara la estructura de su base de datos reemplazando esos grupos dentro de una sola columna con una fila separada para cada número en la lista separada por comas. Entonces, no solo podría usar el =operador en lugar de una expresión regular, sino también usar herramientas relacionales más poderosas como las uniones que SQL le proporciona.

Ian Mackinnon
fuente
14

Una UDF de SQLite en PHP / PDO para la REGEXPpalabra clave que imita el comportamiento en 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;
    }
);

El umodificador no está implementado en MySQL, pero me resulta útil tenerlo por defecto. Ejemplos:

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

Si $datao $patternes NULL, el resultado es NULL, como en MySQL.

Alix Axel
fuente
8

mi solución en python con 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()

si la expresión regular coincide, la salida sería 1, de lo contrario 0.

aGuegu
fuente
5

No sé, es bueno responder una pregunta que se publicó hace casi un año. Pero estoy escribiendo esto para aquellos que piensan que Sqlite en sí mismo proporciona la función REGEXP .

Un requisito básico para invocar la función REGEXP en sqlite es
"Debe crear su propia función en la aplicación y luego proporcionar el enlace de devolución de llamada al controlador sqlite" .
Para eso, debe usar sqlite_create_function (interfaz C). Puedes encontrar el detalle aquí y aquí

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

Y:

SELECT * from TableName
 WHERE YourField REGEXP 'YOUR REGEX'

fuente
4

Una cláusula where exhaustiva de or'ed puede hacerlo sin la concatenación de cadenas:

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

Incluye los cuatro casos de coincidencia exacta, final de lista, comienzo de lista y lista intermedia.

Esto es más detallado, no requiere la extensión regex.

phyatt
fuente
4

Con Python, asumiendo que cones la conexión a SQLite, puede definir la UDF requerida escribiendo:

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

Aquí tienes un ejemplo más 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
fuente
En mi humilde opinión, el cheque debería ser de lo if x not Null and y not Null and re.search(x,y)contrario arrojará.
pholat
2

Podría usar una expresión regular con REGEXP , pero esa es una forma tonta de hacer una coincidencia exacta.

Deberías decir WHERE x = '3'.

Quentin
fuente
Debería haberlo explicado mejor (perdón por mi pobre inglés), quise decir solo un cierto valor exacto, no la cadena exacta. ¡Gracias de cualquier manera!
cody
2

Considere usar esto

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

Esto coincidirá exactamente con 3 cuando x esté en:

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

Otros ejemplos:

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

Esto coincidirá en 3 o 13

itsjavi
fuente
1

En caso de que si alguien busca una condición no regular para Android Sqlite , como esta cadena [1,2,3,4,5], no olvide agregar el corchete ( [] ) para otros caracteres especiales como paréntesis ( {} ) en la condición @phyatt

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

También puede considerar

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

Esto permitirá encontrar el número 3 en cualquier cadena en cualquier posición.

Avrob
fuente
0

En Julia, el modelo a seguir se puede ilustrar de la siguiente manera:

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
fuente
0

para rieles

            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
fuente