Bagaimana cara menggunakan regex dalam kueri SQLite?

102

Saya ingin menggunakan ekspresi reguler dalam sqlite, tetapi saya tidak tahu caranya.

Tabel saya memiliki kolom dengan string seperti ini: "3,12,13,14,19,28,32" Sekarang jika saya mengetik "di mana x LIKE '3'" saya juga mendapatkan baris yang berisi nilai seperti 13 atau 32 , tapi saya hanya ingin mendapatkan baris yang memiliki nilai persis 3 dalam string itu.

Apakah ada yang tahu bagaimana mengatasi ini?

cody
sumber
Jawaban ini adalah yang terbaik untuk menambahkan fungsi REGEXP ke sqlite di c # stackoverflow.com/a/26155359/5734452
hubaishan

Jawaban:

74

SQLite3 mendukung operator REGEXP:

WHERE x REGEXP <regex>

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

DanS
sumber
3
Saya menemukan cara mudah: Ini hanya \ bx \ b di mana x adalah nilai yang dicari dalam string :)
cody
12
@DanS: Bagaimana Anda menambahkan regex()fungsi untuk mendukung REGEXPoperator? Secara default, fungsi pengguna belum ditambahkan.
SK9
47
Menurut dokumen Sqlite: Operator REGEXP adalah sintaks khusus untuk fungsi pengguna regexp (). Tidak ada fungsi pengguna regexp () yang ditentukan secara default sehingga penggunaan operator REGEXP biasanya akan menghasilkan pesan kesalahan. Jika fungsi SQL yang ditentukan aplikasi bernama "regexp" ditambahkan saat run-time, fungsi itu akan dipanggil untuk mengimplementasikan operator REGEXP. ( sqlite.org/lang_expr.html#regexp )
radicand
Bagi kita yang mendapatkan kesalahan ketika Anda mencoba ini, periksa respons di bawah ini stackoverflow.com/a/18484596/1585572 Saya memasukkan kode dalam file dan mengimpornya di Fungsi yang Ditentukan Pengguna di manajer sqlite Firefox saya. Anda perlu memanggilnya sedikit berbeda, seperti ini: SELECT * FROM table WHERE column regexp ("myregexp")
Tristan
112

Seperti yang telah ditunjukkan oleh orang lain, REGEXP memanggil fungsi yang ditentukan pengguna yang harus didefinisikan terlebih dahulu dan dimuat ke dalam database. Mungkin beberapa distribusi sqlite atau alat GUI memasukkannya secara default, tetapi pemasangan Ubuntu saya tidak. Solusinya adalah

sudo apt-get install sqlite3-pcre

yang mengimplementasikan ekspresi reguler Perl dalam modul yang dapat dimuat di /usr/lib/sqlite3/pcre.so

Untuk dapat menggunakannya, Anda harus memuatnya setiap kali Anda membuka database:

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

Atau Anda bisa memasukkan baris itu ke file ~/.sqliterc.

Sekarang Anda dapat melakukan kueri seperti ini:

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

Jika Anda ingin membuat kueri langsung dari baris perintah, Anda dapat menggunakan -cmdsakelar untuk memuat pustaka sebelum SQL Anda:

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

Jika Anda menggunakan Windows, saya kira file .dll serupa harus tersedia di suatu tempat.

mivk
sumber
15
Opsi pemuatan lain: Saya membuat tampilan dengan ini: SELECT load_extension ('/ usr / lib / sqlite3 / pcre.so'); Dengan cara itu ketika saya menggunakan titik masuk berbasis GUI ke DB (seperti SQLite Manager di Firefox), saya memiliki cara untuk memuat kemampuan REGEXP.
Paulb
30

Cara hacky untuk menyelesaikannya tanpa regex adalah where ',' || x || ',' like '%,3,%'

Blorgbeard keluar
sumber
1
Ya, saya berpikir seperti itu, tetapi tidak ada memimpin atau mengikuti "," setiap saat. Terima kasih :-)
cody
Saya tidak menemukan masalah di sini - Saya ingin tahu apakah ini berfungsi karena x adalah nama kolom ...
cody
3
Anda harus menggunakan',' || x || ','
Baruch
21

SQLite tidak berisi fungsionalitas ekspresi reguler secara default.

Ini mendefinisikan REGEXPoperator, tetapi ini akan gagal dengan pesan kesalahan kecuali Anda atau kerangka kerja Anda menentukan fungsi pengguna yang dipanggil regexp(). Bagaimana Anda melakukan ini akan bergantung pada platform Anda.

Jika Anda memiliki regexp()fungsi yang ditentukan, Anda dapat mencocokkan bilangan bulat arbitrer dari daftar yang dipisahkan koma seperti:

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

Tapi sungguh, sepertinya Anda akan menemukan hal-hal jauh lebih mudah jika Anda menormalkan struktur database Anda dengan mengganti grup tersebut dalam satu kolom dengan baris terpisah untuk setiap nomor dalam daftar yang dipisahkan koma. Kemudian Anda tidak hanya dapat menggunakan =operator alih-alih ekspresi reguler, tetapi juga menggunakan alat relasional yang lebih canggih seperti gabungan yang disediakan SQL untuk Anda.

Ian Mackinnon
sumber
14

UDF SQLite di PHP / PDO untuk REGEXPkata kunci yang meniru perilaku di 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;
    }
);

The upengubah tidak diterapkan di MySQL, tapi saya merasa berguna untuk memilikinya secara default. Contoh:

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

Jika salah satu $dataatau $patternadalah NULL, hasilnya adalah NULL - seperti di MySQL.

Alix Axel
sumber
8

solusi saya dengan python dengan 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()

jika regex cocok, outputnya adalah 1, jika tidak 0.

aGuegu
sumber
5

I don't it is good untuk menjawab pertanyaan yang diposting hampir setahun yang lalu. Tetapi saya menulis ini untuk mereka yang berpikir bahwa Sqlite sendiri menyediakan fungsi REGEXP .

Satu persyaratan dasar untuk menjalankan fungsi REGEXP di sqlite adalah
"Anda harus membuat fungsi Anda sendiri di aplikasi dan kemudian memberikan link callback ke driver sqlite" .
Untuk itu Anda harus menggunakan sqlite_create_function (C interface). Anda dapat menemukan detailnya dari sini dan sini

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

Dan:

SELECT * from TableName
 WHERE YourField REGEXP 'YOUR REGEX'

sumber
4

Sebuah or'ed lengkap di mana klausa dapat melakukannya tanpa penggabungan string:

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

Termasuk empat kasus yang sama persis, akhir daftar, awal daftar, dan daftar tengah.

Ini lebih bertele-tele, tidak memerlukan ekstensi regex.

phyatt.dll
sumber
4

Dengan python, dengan asumsi conadalah koneksi ke SQLite, Anda dapat menentukan UDF yang diperlukan dengan menulis:

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

Berikut contoh yang lebih lengkap:

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

puncak
sumber
Pemeriksaan IMHO harus if x not Null and y not Null and re.search(x,y)sebaliknya itu akan melempar.
pholat
2

Anda dapat menggunakan ekspresi reguler dengan REGEXP , tetapi itu adalah cara konyol untuk melakukan pencocokan tepat.

Anda hanya harus mengatakan WHERE x = '3'.

Quentin
sumber
Saya seharusnya menjelaskannya lebih baik (maaf untuk bahasa Inggris saya yang buruk), yang saya maksudkan hanya nilai pasti tertentu, bukan string yang tepat. Terima kasih!
cody
2

Pertimbangkan untuk menggunakan ini

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

Ini akan sama persis dengan 3 ketika x ada di:

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

Contoh lain:

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

Ini akan cocok pada 3 atau 13

itsjavi
sumber
1

Jika seseorang mencari kondisi non-regex untuk Android Sqlite , seperti string ini [1,2,3,4,5]maka jangan lupa untuk menambahkan tanda kurung ( [] ) yang sama untuk karakter khusus lainnya seperti tanda kurung ( {} ) dalam kondisi @phyatt

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

Jika Anda menggunakan php, Anda dapat menambahkan fungsi apa pun ke pernyataan sql Anda dengan menggunakan: SQLite3 :: createFunction . Di PDO Anda dapat menggunakan PDO :: sqliteCreateFunction dan mengimplementasikan fungsi preg_match dalam pernyataan Anda:

Lihat bagaimana ini dilakukan oleh Havalite ( RegExp di SqLite menggunakan Php )

kode 19
sumber
Dalam fungsi MySQL REGEXP, Anda tidak perlu menentukan pembatas atau pengubah dalam pola.
Alix Axel
0

Anda juga bisa mempertimbangkan

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

Ini akan memungkinkan menemukan nomor 3 dalam string apa pun di posisi mana pun

Avrob
sumber
0

Dalam Julia, model yang diikuti dapat diilustrasikan sebagai berikut:

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
puncak
sumber
0

untuk rel

            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
sumber