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?


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


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.


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


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.


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.


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.


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


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

Dan:

SELECT * from TableName
 WHERE YourField REGEXP 'YOUR REGEX'

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.


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


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


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


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,%');


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


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

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.