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?

cody
la source
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

DanS
la source
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.

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

Blorgbeard est sorti
la source
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.

Ian Mackinnon
la source
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.

Alix Axel
la source
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.

aGuegu
la source
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

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

Et :

SELECT * from TableName
 WHERE YourField REGEXP 'YOUR REGEX'

la source
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.

phyatt
la source
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' ")

de pointe
la source
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'.

Quentin
la source
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

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

Si vous utilisez php, vous pouvez ajouter n'importe quelle fonction à votre instruction sql en utilisant: SQLite3 :: createFunction . Dans PDO, vous pouvez utiliser PDO :: sqliteCreateFunction et implémenter la fonction preg_match dans votre instruction:

Voyez comment c'est fait par Havalite ( RegExp dans SqLite en utilisant Php )

code19
la source
Dans la fonction MySQL REGEXP, vous n'avez pas besoin de spécifier les délimiteurs ou les modificateurs dans le modèle.
Alix Axel
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

Avrob
la source
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
de pointe
la source
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
Xian Kai Ng
la source