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?

Cody
quelle
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

DanS
quelle
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.

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

Blorgbeard ist raus
quelle
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.

Ian Mackinnon
quelle
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.

Alix Axel
quelle
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.

aGuegu
quelle
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

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

Und :

SELECT * from TableName
 WHERE YourField REGEXP 'YOUR REGEX'

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

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

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

QUentin
quelle
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

itsjavi
quelle
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,%');
Dastan
quelle
0

Wenn Sie PHP verwenden, können Sie Ihrer SQL-Anweisung eine beliebige Funktion hinzufügen, indem Sie Folgendes verwenden: SQLite3 :: createFunction . In PDO können Sie PDO :: sqliteCreateFunction verwenden und die Funktion preg_match in Ihrer Anweisung implementieren :

Sehen Sie, wie es von Havalite gemacht wird ( RegExp in SqLite mit Php )

Code19
quelle
In der MySQL REGEXP-Funktion müssen Sie die Trennzeichen oder Modifikatoren im Muster nicht angeben.
Alix Axel
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

Avrob
quelle
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
Gipfel
quelle
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
Xian Kai Ng
quelle