Wie verwende ich Regex in einer SQLite-Abfrage?


101

Ich möchte einen regulären Ausdruck in SQLite verwenden, weiß aber nicht wie.

Meine Tabelle hat eine Spalte mit folgenden Zeichenfolgen: "3,12,13,14,19,28,32" Wenn ich nun "where x LIKE '3'" eingebe, erhalte ich auch die Zeilen, die Werte wie 13 oder 32 enthalten , aber ich möchte nur die Zeilen erhalten, die genau den Wert 3 in dieser Zeichenfolge haben.

Weiß jemand, wie man das löst?


Diese Antwort ist die beste für das Hinzufügen der REGEXP-Funktion zu sqlite in c # stackoverflow.com/a/26155359/5734452
hubaishan

Antworten:


73

SQLite3 unterstützt den REGEXP-Operator:

WHERE x REGEXP <regex>

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


3
Ich habe einen einfachen Weg gefunden: Es ist einfach \ bx \ b, wobei x der Wert ist, nach dem in der Zeichenfolge
gesucht werden muss

12
@DanS: Wie fügt man eine regex()Funktion hinzu, um den REGEXPOperator zu unterstützen ? Standardmäßig wurde keine Benutzerfunktion hinzugefügt.
SK9

47
Gemäß den Sqlite-Dokumenten: Der REGEXP-Operator ist eine spezielle Syntax für die Benutzerfunktion regexp (). Standardmäßig ist keine Benutzerfunktion von regexp () definiert. Daher führt die Verwendung des Operators REGEXP normalerweise zu einer Fehlermeldung. Wenn zur Laufzeit eine anwendungsdefinierte SQL-Funktion mit dem Namen "regexp" hinzugefügt wird, wird diese Funktion aufgerufen, um den REGEXP-Operator zu implementieren. ( sqlite.org/lang_expr.html#regexp )
Radicand

Für diejenigen von uns, die eine Fehlermeldung erhalten, wenn Sie dies versuchen, lesen Sie die Antwort unter stackoverflow.com/a/18484596/1585572. Ich habe den Code in eine Datei eingefügt und ihn in die benutzerdefinierten Funktionen in meinem Firefox-SQLite-Manager importiert. Sie müssen es jedoch etwas anders aufrufen, wie folgt: SELECT * FROM table WHERE Spalte regexp ("myregexp")
Tristan

112

Wie bereits erwähnt, ruft REGEXP eine benutzerdefinierte Funktion auf, die zuerst definiert und in die Datenbank geladen werden muss. Möglicherweise enthalten einige SQLite-Distributionen oder GUI-Tools dies standardmäßig, meine Ubuntu-Installation jedoch nicht. Die Lösung war

sudo apt-get install sqlite3-pcre

Hiermit werden reguläre Perl-Ausdrücke in einem ladbaren Modul implementiert /usr/lib/sqlite3/pcre.so

Um es verwenden zu können, müssen Sie es jedes Mal laden, wenn Sie die Datenbank öffnen:

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

Oder Sie könnten diese Zeile in Ihre setzen ~/.sqliterc.

Jetzt können Sie wie folgt abfragen:

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

Wenn Sie direkt über die Befehlszeile abfragen möchten, können Sie -cmddie Bibliothek mit dem Schalter vor Ihrem SQL laden:

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

Wenn Sie unter Windows arbeiten, sollte eine ähnliche DLL-Datei irgendwo verfügbar sein.


15
Eine weitere Ladeoption: Ich habe eine Ansicht mit folgender Adresse erstellt: SELECT load_extension ('/ usr / lib / sqlite3 / pcre.so'); Auf diese Weise kann ich die REGEXP-Funktion laden, wenn ich einen GUI-basierten Einstiegspunkt in die Datenbank verwende (wie SQLite Manager in Firefox).
Paulb

30

Ein hackiger Weg, um es ohne Regex zu lösen, ist where ',' || x || ',' like '%,3,%'


1
Ja, ich habe so gedacht, aber es gibt nicht jedes Mal ein führendes oder folgendes "".
Trotzdem

Ich bin hier nicht auf das Problem
gestoßen

3
Sie sollten verwenden',' || x || ','
Baruch

21

SQLite enthält standardmäßig keine Funktionen für reguläre Ausdrücke.

Es definiert einen REGEXPOperator, dies schlägt jedoch mit einer Fehlermeldung fehl, es sei denn, Sie oder Ihr Framework definieren eine aufgerufene Benutzerfunktionregexp() . Wie Sie dies tun, hängt von Ihrer Plattform ab.

Wenn Sie eine regexp()Funktion definiert haben, können Sie eine beliebige Ganzzahl aus einer durch Kommas getrennten Liste wie folgt abgleichen:

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

Aber es sieht wirklich so aus, als würden Sie die Dinge viel einfacher finden, wenn Sie Ihre Datenbankstruktur normalisieren würden, indem Sie diese Gruppen in einer einzelnen Spalte durch eine separate Zeile für jede Zahl in der durch Kommas getrennten Liste ersetzen . Dann könnten Sie nicht nur den =Operator anstelle eines regulären Ausdrucks verwenden, sondern auch leistungsfähigere relationale Tools wie Joins, die SQL für Sie bereitstellt.


14

Eine SQLite-UDF in PHP / PDO für das REGEXPSchlüsselwort, das das Verhalten in MySQL nachahmt:

$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;
    }
);

Der uModifikator ist nicht in MySQL implementiert, aber ich finde es nützlich, ihn standardmäßig zu haben. Beispiele:

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

Wenn entweder $dataoder $patternNULL ist, ist das Ergebnis NULL - genau wie in MySQL.


8

meine lösung in python mit 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()

Wenn Regex übereinstimmt, wäre die Ausgabe 1, andernfalls 0.


5

Ich finde es nicht gut, eine Frage zu beantworten, die vor fast einem Jahr gestellt wurde. Aber ich schreibe dies für diejenigen, die denken, dass Sqlite selbst die Funktion REGEXP bereitstellt .

Eine Grundvoraussetzung zum Aufrufen der Funktion REGEXP in SQLite ist
"Sie sollten Ihre eigene Funktion in der Anwendung erstellen und dann den Rückruflink zum SQLite-Treiber bereitstellen" .
Dafür müssen Sie sqlite_create_function (C-Schnittstelle) verwenden. Details finden Sie hier und hier


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

Und :

SELECT * from TableName
 WHERE YourField REGEXP 'YOUR REGEX'

4

Eine erschöpfende or'ed where-Klausel kann dies ohne Verkettung von Zeichenfolgen tun:

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

Beinhaltet die exakte Übereinstimmung der vier Fälle, das Ende der Liste, den Anfang der Liste und die mittlere Liste.

Dies ist ausführlicher und erfordert keine Regex-Erweiterung.


4

Unter der Annahme, dass cones sich bei Python um eine Verbindung zu SQLite handelt, können Sie die erforderliche UDF definieren , indem Sie Folgendes schreiben:

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

Hier ist ein vollständigeres Beispiel:

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


IMHO Check sollte sein, if x not Null and y not Null and re.search(x,y)sonst wird es werfen.
Pholat

2

Sie könnten mit REGEXP einen regulären Ausdruck verwenden , aber das ist eine dumme Methode, um eine genaue Übereinstimmung zu erzielen .

Du solltest nur sagen WHERE x = '3'.


Ich hätte es besser erklären sollen (Entschuldigung für mein schlechtes Englisch), ich meinte nur einen bestimmten genauen Wert, nicht die genaue Zeichenfolge. Danke trotzdem!
Cody

2

Erwägen Sie, dies zu verwenden

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

Dies entspricht genau 3, wenn x in ist:

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

Andere Beispiele:

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

Dies wird am 3 oder 13 übereinstimmen


1

Wenn jemand wie diese Zeichenfolge nach einer Nicht-Regex-Bedingung für Android Sqlite sucht , [1,2,3,4,5]vergessen Sie nicht, die gleiche Klammer ( [] ) für andere Sonderzeichen wie Klammern ( {} ) in @phyatt-Bedingung hinzuzufügen

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


0

Sie können auch berücksichtigen

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

Dies ermöglicht es, Nummer 3 in einer beliebigen Zeichenfolge an einer beliebigen Position zu finden


0

In Julia kann das folgende Modell wie folgt dargestellt werden:

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

für Schienen

            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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.