Làm cách nào để sử dụng regex trong truy vấn SQLite?


102

Tôi muốn sử dụng một biểu thức chính quy trong sqlite, nhưng tôi không biết làm thế nào.

Bảng của tôi có một cột với các chuỗi như sau: "3,12,13,14,19,28,32" Bây giờ nếu tôi nhập "trong đó x LIKE '3'", tôi cũng nhận được các hàng chứa các giá trị như 13 hoặc 32 , nhưng tôi chỉ muốn lấy các hàng có chính xác giá trị 3 trong chuỗi đó.

Có ai biết làm thế nào để giải quyết điều này?


Câu trả lời này là tốt nhất cho việc thêm chức năng REGEXP để sqlite trong c # stackoverflow.com/a/26155359/5734452
hubaishan

Câu trả lời:


74

SQLite3 hỗ trợ toán tử REGEXP:

WHERE x REGEXP <regex>

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


3
Tôi đã tìm thấy một cách dễ dàng: Nó chỉ đơn giản là \ bx \ b trong đó x là giá trị cần tìm trong chuỗi :)
cody

12
@DanS: Làm thế nào để bạn thêm một regex()chức năng để hỗ trợ người REGEXPđiều hành? Theo mặc định, một chức năng người dùng chưa được thêm vào.
SK9

47
Theo tài liệu Sqlite: Toán tử REGEXP là một cú pháp đặc biệt cho hàm người dùng regexp (). Không có hàm người dùng regexp () nào được xác định theo mặc định và do đó việc sử dụng toán tử REGEXP thường sẽ dẫn đến thông báo lỗi. Nếu một hàm SQL do ứng dụng xác định có tên "regexp" được thêm vào lúc chạy, thì hàm đó sẽ được gọi để triển khai toán tử REGEXP. ( sqlite.org/lang_expr.html#regexp )
radicand

Đối với những người trong chúng ta gặp lỗi khi bạn thử điều này, hãy xem phản hồi bên dưới stackoverflow.com/a/18484596/1585572 Tôi đặt mã vào một tệp và nhập mã đó vào Chức năng do người dùng xác định trong trình quản lý sqlite của Firefox. Tuy nhiên, bạn cần gọi nó hơi khác một chút, như thế này: SELECT * FROM table WHERE cột regexp ("myregexp")
Tristan

112

Như những người khác đã chỉ ra, REGEXP gọi một hàm do người dùng định nghĩa, hàm này trước tiên phải được xác định và tải vào cơ sở dữ liệu. Có thể một số bản phân phối sqlite hoặc công cụ GUI bao gồm nó theo mặc định, nhưng cài đặt Ubuntu của tôi thì không. Giải pháp là

sudo apt-get install sqlite3-pcre

triển khai các biểu thức chính quy Perl trong một mô-đun có thể tải trong /usr/lib/sqlite3/pcre.so

Để có thể sử dụng nó, bạn phải tải nó mỗi khi bạn mở cơ sở dữ liệu:

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

Hoặc bạn có thể đặt dòng đó vào của bạn ~/.sqliterc.

Bây giờ bạn có thể truy vấn như sau:

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

Nếu bạn muốn truy vấn trực tiếp từ dòng lệnh, bạn có thể sử dụng công -cmdtắc để tải thư viện trước SQL của bạn:

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

Nếu bạn đang sử dụng Windows, tôi đoán sẽ có một tệp .dll tương tự ở đâu đó.


15
Một tùy chọn tải khác: Tôi đã tạo một dạng xem với cái này: SELECT load_extension ('/ usr / lib / sqlite3 / pcre.so'); Bằng cách đó khi tôi sử dụng điểm nhập dựa trên GUI cho DB (như SQLite Manager trong Firefox), tôi có một cách để tải khả năng REGEXP.
Paulb

30

Một cách hacky để giải quyết nó mà không cần regex là where ',' || x || ',' like '%,3,%'


1
Có, tôi đã nghĩ về cách đó, nhưng không phải lúc nào cũng dẫn đầu hoặc theo sau ",". Cảm ơn dù sao :-)
cody

Tôi không tình cờ gặp vấn đề ở đây - tôi tự hỏi liệu điều này có hoạt động như x là tên cột ...
cody

3
Bạn nên sử dụng',' || x || ','
Baruch

21

SQLite không chứa chức năng biểu thức chính quy theo mặc định.

Nó xác định một REGEXPtoán tử, nhưng điều này sẽ không thành công với thông báo lỗi trừ khi bạn hoặc khung của bạn xác định một hàm người dùng được gọi regexp(). Cách bạn làm điều này sẽ phụ thuộc vào nền tảng của bạn.

Nếu bạn đã regexp()xác định một hàm, bạn có thể so khớp một số nguyên tùy ý từ danh sách được phân tách bằng dấu phẩy như sau:

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

Nhưng thực sự, có vẻ như bạn sẽ thấy mọi thứ dễ dàng hơn rất nhiều nếu bạn chuẩn hóa cấu trúc cơ sở dữ liệu của mình bằng cách thay thế các nhóm đó trong một cột đơn bằng một hàng riêng biệt cho mỗi số trong danh sách được phân tách bằng dấu phẩy. Sau đó, bạn không chỉ có thể sử dụng =toán tử thay vì biểu thức chính quy, mà còn sử dụng các công cụ quan hệ mạnh mẽ hơn như phép nối mà SQL cung cấp cho bạn.


14

Một UDF SQLite trong PHP / PDO cho REGEXPtừ khóa bắt chước hành vi trong 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;
    }
);

Công cụ usửa đổi không được triển khai trong MySQL, nhưng tôi thấy nó hữu ích nếu có nó theo mặc định. Ví dụ:

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

Nếu một trong hai $datahoặc $patternlà NULL, kết quả là NULL - giống như trong MySQL.


8

giải pháp của tôi trong python với 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()

nếu regex khớp, đầu ra sẽ là 1, ngược lại là 0.


5

Tôi không tốt khi trả lời một câu hỏi đã được đăng gần một năm trước. Nhưng tôi viết điều này cho những ai nghĩ rằng bản thân Sqlite cung cấp chức năng REGEXP .

Một yêu cầu cơ bản để gọi hàm REGEXP trong sqlite là
"Bạn nên tạo hàm của riêng mình trong ứng dụng và sau đó cung cấp liên kết gọi lại tới trình điều khiển sqlite" .
Đối với điều đó, bạn phải sử dụng sqlite_create_ Chức năng (giao diện C). Bạn có thể tìm thấy chi tiết từ đâyở đây


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

Và:

SELECT * from TableName
 WHERE YourField REGEXP 'YOUR REGEX'

4

Một mệnh đề đầy đủ or'ed where có thể làm điều đó mà không cần nối chuỗi:

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

Bao gồm bốn trường hợp khớp chính xác, cuối danh sách, đầu danh sách và giữa danh sách.

Điều này dài dòng hơn, không yêu cầu phần mở rộng regex.


4

Với python, giả sử conlà kết nối đến SQLite, bạn có thể xác định UDF bắt buộc bằng cách viết:

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

Đây là một ví dụ đầy đủ hơn:

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


Kiểm tra IMHO phải được if x not Null and y not Null and re.search(x,y)nếu không nó sẽ ném.
pholat

2

Bạn có thể sử dụng một biểu thức chính quy với REGEXP , nhưng đó là một cách ngớ ngẩn để thực hiện đối sánh chính xác.

Bạn chỉ nên nói WHERE x = '3'.


Tôi nên giải thích nó tốt hơn (xin lỗi vì tiếng Anh kém của tôi), ý tôi chỉ là một giá trị chính xác nhất định, không phải chuỗi chính xác. Dẫu sao cũng xin cảm ơn!
cody

2

Cân nhắc sử dụng cái này

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

Điều này sẽ khớp chính xác 3 khi x nằm trong:

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

Những ví dụ khác:

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

Điều này sẽ khớp vào ngày 3 hoặc ngày 13


1

Trong trường hợp nếu ai đó tìm kiếm điều kiện không phải regex cho Android Sqlite , giống như chuỗi này, [1,2,3,4,5]thì đừng quên thêm dấu ngoặc ( [] ) tương tự cho các ký tự đặc biệt khác như dấu ngoặc đơn ( {} ) trong điều kiện @phyatt

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

0

Nếu bạn đang sử dụng php, bạn có thể thêm bất kỳ hàm nào vào câu lệnh sql của mình bằng cách sử dụng: SQLite3 :: createFunction . Trong PDO, bạn có thể sử dụng PDO :: sqliteCreateFunction và triển khai preg_match hàm trong câu lệnh của mình:

Xem cách nó được thực hiện bởi Havalite ( RegExp trong SqLite sử dụng Php )


Trong hàm MySQL REGEXP, bạn không cần phải chỉ định các dấu phân cách hoặc bổ ngữ trong mẫu.
Alix Axel

0

Bạn cũng có thể cân nhắc

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

Điều này sẽ cho phép tìm số 3 trong bất kỳ chuỗi nào ở bất kỳ vị trí nào


0

Ở Julia, mô hình để làm theo có thể được minh họa như sau:

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

cho đường ray

            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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.