Come si usa regex in una query SQLite?


102

Vorrei usare un'espressione regolare in sqlite, ma non so come.

La mia tabella ha una colonna con stringhe come questa: "3,12,13,14,19,28,32" Ora se digito "dove x LIKE '3'" ottengo anche le righe che contengono valori come 13 o 32 , ma vorrei ottenere solo le righe che hanno esattamente il valore 3 in quella stringa.

Qualcuno sa come risolvere questo problema?


Questa risposta è la migliore per l'aggiunta di funzionalità REGEXP a SQLite in C # stackoverflow.com/a/26155359/5734452
hubaishan

Risposte:


74

SQLite3 supporta l'operatore REGEXP:

WHERE x REGEXP <regex>

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


3
Ho trovato un modo semplice: è semplicemente \ bx \ b dove x è il valore da cercare nella stringa :)
cody

12
@ DanS: come si aggiunge una regex()funzione per supportare l' REGEXPoperatore? Per impostazione predefinita, non è stata aggiunta una funzione utente.
SK9

47
Secondo la documentazione di Sqlite: L'operatore REGEXP è una sintassi speciale per la funzione utente regexp (). Nessuna funzione utente regexp () è definita per impostazione predefinita, quindi l'uso dell'operatore REGEXP normalmente genererà un messaggio di errore. Se una funzione SQL definita dall'applicazione denominata "regexp" viene aggiunta in fase di esecuzione, tale funzione verrà chiamata per implementare l'operatore REGEXP. ( sqlite.org/lang_expr.html#regexp )
radicand

Per quelli di noi che ottengono un errore quando provi, controlla la risposta sotto stackoverflow.com/a/18484596/1585572 Ho inserito il codice in un file e l'ho importato nelle funzioni definite dall'utente nel mio gestore sqlite di Firefox. Tuttavia, è necessario richiamarlo in modo leggermente diverso, in questo modo: SELECT * FROM table WHERE column regexp ("myregexp")
Tristan

112

Come altri hanno già sottolineato, REGEXP chiama una funzione definita dall'utente che deve essere prima definita e caricata nel database. Forse alcune distribuzioni sqlite o strumenti GUI lo includono per impostazione predefinita, ma la mia installazione di Ubuntu no. La soluzione era

sudo apt-get install sqlite3-pcre

che implementa le espressioni regolari Perl in un modulo caricabile in /usr/lib/sqlite3/pcre.so

Per poterlo utilizzare, devi caricarlo ogni volta che apri il database:

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

Oppure potresti mettere quella linea nel tuo file ~/.sqliterc.

Ora puoi eseguire query in questo modo:

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

Se desideri eseguire una query direttamente dalla riga di comando, puoi utilizzare il file -cmd opzione per caricare la libreria prima del tuo SQL:

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

Se sei su Windows, immagino che un file .dll simile dovrebbe essere disponibile da qualche parte.


15
Un'altra opzione di caricamento: ho creato una vista con questa: SELECT load_extension ('/ usr / lib / sqlite3 / pcre.so'); In questo modo, quando utilizzo un punto di ingresso basato su GUI per il DB (come SQLite Manager in Firefox), ho un modo per caricare la funzionalità REGEXP.
Paulb

30

Un modo hacky per risolverlo senza regex è where ',' || x || ',' like '%,3,%'


1
Sì, ho pensato in questo modo, ma non ci sono "", "" che guidano o seguono ogni volta. Grazie comunque :-)
cody

Non mi sono imbattuto nel problema qui - Mi chiedo se funziona come x è il nome della colonna ...
cody

3
Dovresti usare',' || x || ','
Baruch

21

SQLite non contiene funzionalità di espressioni regolari per impostazione predefinita.

Definisce un REGEXPoperatore, ma fallirà con un messaggio di errore a meno che tu o il tuo framework non definiate una funzione utente chiamataregexp() . Il modo in cui lo fai dipenderà dalla tua piattaforma.

Se hai una regexp()funzione definita, puoi trovare un numero intero arbitrario da un elenco separato da virgole in questo modo:

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

Ma in realtà, sembra che troverai le cose molto più semplici se normalizzassi la struttura del tuo database sostituendo quei gruppi all'interno di una singola colonna con una riga separata per ogni numero nell'elenco separato da virgole. Quindi non solo potresti usare l' =operatore invece di un'espressione regolare, ma anche usare strumenti relazionali più potenti come i join che SQL ti fornisce.


14

Una UDF SQLite in PHP / PDO per la REGEXPparola chiave che imita il comportamento in 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;
    }
);

Il umodificatore non è implementato in MySQL, ma trovo utile averlo di default. Esempi:

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

Se $datao $patternè NULL, il risultato è NULL, proprio come in MySQL.


8

la mia soluzione in 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()

se regex corrisponde, l'output sarebbe 1, altrimenti 0.


5

Non è bene rispondere a una domanda che è stata posta quasi un anno fa. Ma sto scrivendo questo per coloro che pensano che Sqlite stesso fornisca la funzione REGEXP .

Un requisito di base per richiamare la funzione REGEXP in sqlite è
"È necessario creare la propria funzione nell'applicazione e quindi fornire il collegamento di richiamata al driver sqlite" .
Per questo devi usare sqlite_create_function (interfaccia C). Puoi trovare i dettagli da qui e qui


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

E :

SELECT * from TableName
 WHERE YourField REGEXP 'YOUR REGEX'

4

Una clausola or'ed where esaustiva può farlo senza concatenazione di stringhe:

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

Include la corrispondenza esatta dei quattro casi, la fine della lista, l'inizio della lista e la metà della lista.

Questo è più dettagliato, non richiede l'estensione regex.


4

Con python, supponendo che consia la connessione a SQLite, puoi definire l'UDF richiesta scrivendo:

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

Ecco un esempio più 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' ")


Il controllo IMHO dovrebbe essere if x not Null and y not Null and re.search(x,y)altrimenti verrà lanciato.
pholat

2

È possibile utilizzare un'espressione regolare con REGEXP , ma questo è un modo sciocco per fare una corrispondenza esatta.

Dovresti solo dire WHERE x = '3'.


Avrei dovuto spiegarlo meglio (scusate il mio inglese scadente), intendevo solo un certo valore esatto, non la stringa esatta. Grazie comunque!
cody

2

Considera l'idea di usarlo

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

Questo corrisponderà esattamente a 3 quando x è in:

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

Altri esempi:

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

Questo corrisponderà al 3 o al 13


1

Nel caso in cui qualcuno cerchi una condizione non regex per Android Sqlite , come questa stringa [1,2,3,4,5], non dimenticare di aggiungere la parentesi ( [] ) stessa per altri caratteri speciali come le parentesi ( {} ) nella condizione @phyatt

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


0

Puoi anche considerare

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

Ciò consentirà di trovare il numero 3 in qualsiasi stringa in qualsiasi posizione


0

In Julia, il modello da seguire può essere illustrato come segue:

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

per rotaie

            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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.