Comment utiliser regex dans une requête SQLite?


102

J'aimerais utiliser une expression régulière dans sqlite, mais je ne sais pas comment.

Ma table a une colonne avec des chaînes comme celle-ci: "3,12,13,14,19,28,32" Maintenant, si je tape "où x LIKE '3'" J'obtiens également les lignes qui contiennent des valeurs comme 13 ou 32 , mais j'aimerais obtenir uniquement les lignes qui ont exactement la valeur 3 dans cette chaîne.

Quelqu'un sait-il comment résoudre ceci?


Cette réponse est la meilleure pour ajouter la fonction REGEXP à sqlite dans c # stackoverflow.com/a/26155359/5734452
hubaishan

Réponses:


74

SQLite3 prend en charge l'opérateur REGEXP:

WHERE x REGEXP <regex>

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


3
J'ai trouvé un moyen simple: c'est simplement \ bx \ b où x est la valeur à rechercher dans la chaîne :)
cody

12
@DanS: Comment ajouter une regex()fonction pour soutenir l' REGEXPopérateur? Par défaut, aucune fonction utilisateur n'a été ajoutée.
SK9

47
Selon la documentation Sqlite: L'opérateur REGEXP est une syntaxe spéciale pour la fonction utilisateur regexp (). Aucune fonction utilisateur regexp () n'est définie par défaut et donc l'utilisation de l'opérateur REGEXP entraînera normalement un message d'erreur. Si une fonction SQL définie par l'application nommée "regexp" est ajoutée au moment de l'exécution, cette fonction sera appelée afin d'implémenter l'opérateur REGEXP. ( sqlite.org/lang_expr.html#regexp )
radicand

Pour ceux d'entre nous qui obtiennent une erreur lorsque vous essayez ceci, consultez la réponse ci-dessous stackoverflow.com/a/18484596/1585572 J'ai mis le code dans un fichier et je l'ai importé sur les fonctions définies par l'utilisateur dans mon gestionnaire Firefox sqlite. Vous devez l'appeler légèrement différemment, comme ceci: SELECT * FROM table WHERE colonne regexp ("myregexp")
Tristan

112

Comme d'autres l'ont déjà souligné, REGEXP appelle une fonction définie par l'utilisateur qui doit d'abord être définie et chargée dans la base de données. Peut-être que certaines distributions de sqlite ou outils d'interface graphique l'incluent par défaut, mais pas mon installation Ubuntu. La solution était

sudo apt-get install sqlite3-pcre

qui implémente des expressions régulières Perl dans un module chargeable dans /usr/lib/sqlite3/pcre.so

Pour pouvoir l'utiliser, vous devez le charger à chaque fois que vous ouvrez la base de données:

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

Ou vous pouvez mettre cette ligne dans votre ~/.sqliterc.

Vous pouvez maintenant interroger comme ceci:

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

Si vous souhaitez interroger directement à partir de la ligne de commande, vous pouvez utiliser le -cmdcommutateur pour charger la bibliothèque avant votre SQL:

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

Si vous êtes sous Windows, je suppose qu'un fichier .dll similaire devrait être disponible quelque part.


15
Une autre option de chargement: j'ai créé une vue avec ceci: SELECT load_extension ('/ usr / lib / sqlite3 / pcre.so'); De cette façon, lorsque j'utilise un point d'entrée basé sur l'interface graphique dans la base de données (comme SQLite Manager dans Firefox), j'ai un moyen de charger la capacité REGEXP.
Paulb

30

Une façon hacky de le résoudre sans regex est where ',' || x || ',' like '%,3,%'


1
Oui, j'ai pensé de cette façon, mais il n'y a pas de "," à chaque fois. Merci quand même :-)
cody

Je ne suis pas tombé sur le problème ici - je me demande si cela fonctionne car x est le nom de la colonne ...
cody

3
Vous devriez utiliser',' || x || ','
Baruch

21

SQLite ne contient pas de fonctionnalité d'expression régulière par défaut.

Il définit un REGEXPopérateur, mais cela échouera avec un message d'erreur à moins que vous ou votre infrastructure définissez une fonction utilisateur appelée regexp(). La façon dont vous procédez dépendra de votre plate-forme.

Si vous avez regexp()défini une fonction, vous pouvez faire correspondre un entier arbitraire dans une liste séparée par des virgules comme ceci:

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

Mais en réalité, il semble que vous trouveriez les choses beaucoup plus faciles si vous normalisiez la structure de votre base de données en remplaçant ces groupes dans une seule colonne par une ligne séparée pour chaque nombre dans la liste séparée par des virgules. Ensuite, vous pouvez non seulement utiliser l' =opérateur au lieu d'une expression régulière, mais également utiliser des outils relationnels plus puissants tels que les jointures que SQL fournit pour vous.


14

Un UDF SQLite en PHP / PDO pour le REGEXPmot-clé qui imite le comportement dans 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;
    }
);

Le umodificateur n'est pas implémenté dans MySQL, mais je trouve utile de l'avoir par défaut. Exemples:

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

Si l'un $dataou l' autre $patternest NULL, le résultat est NULL - comme dans MySQL.


8

ma solution en python avec 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 regex correspond, la sortie serait 1, sinon 0.


5

Je ne sais pas, il est bon de répondre à une question qui a été postée il y a presque un an. Mais j'écris ceci pour ceux qui pensent que Sqlite lui-même fournit la fonction REGEXP .

Une exigence de base pour appeler la fonction REGEXP dans sqlite est
"Vous devez créer votre propre fonction dans l'application et ensuite fournir le lien de rappel vers le pilote sqlite" .
Pour cela, vous devez utiliser sqlite_create_function (interface C). Vous pouvez trouver le détail ici et ici


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

Et :

SELECT * from TableName
 WHERE YourField REGEXP 'YOUR REGEX'

4

Une clause or'ed where exhaustive peut le faire sans concaténation de chaînes:

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

Comprend la correspondance exacte des quatre cas, la fin de la liste, le début de la liste et la mi-liste.

Ceci est plus détaillé, ne nécessite pas l'extension regex.


4

Avec python, en supposant conla connexion à SQLite, vous pouvez définir l'UDF requise en écrivant:

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

Voici un exemple plus complet:

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


Chèque IMHO devrait être if x not Null and y not Null and re.search(x,y)sinon il jettera.
pholat

2

Vous pouvez utiliser une expression régulière avec REGEXP , mais c'est une façon idiote de faire une correspondance exacte.

Tu devrais juste dire WHERE x = '3'.


J'aurais dû mieux l'expliquer (désolé pour mon mauvais anglais), je voulais dire seulement une certaine valeur exacte, pas la chaîne exacte. Merci quand même!
cody

2

Pensez à utiliser ceci

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

Cela correspondra exactement à 3 lorsque x est dans:

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

Autres exemples:

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

Cela correspondra le 3 ou le 13


1

Dans le cas où quelqu'un cherche une condition non-regex pour Android Sqlite , comme cette chaîne, [1,2,3,4,5]n'oubliez pas d'ajouter le crochet ( [] ) même pour les autres caractères spéciaux comme la parenthèse ( {} ) dans la condition @phyatt

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


0

Vous pouvez également envisager

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

Cela permettra de trouver le numéro 3 dans n'importe quelle chaîne à n'importe quelle position


0

Dans Julia, le modèle à suivre peut être illustré comme suit:

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

pour rails

            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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.