ฉันจะใช้ regex ในแบบสอบถาม SQLite ได้อย่างไร


105

ฉันต้องการใช้นิพจน์ทั่วไปใน sqlite แต่ฉันไม่รู้วิธี

ตารางของฉันมีคอลัมน์ที่มีสตริงดังนี้: "3,12,13,14,19,28,32" ตอนนี้ถ้าฉันพิมพ์ "โดยที่ x LIKE '3'" ฉันจะได้แถวที่มีค่าเช่น 13 หรือ 32 ด้วย แต่ฉันต้องการรับเฉพาะแถวที่มีค่า 3 ในสตริงนั้นเท่านั้น

ไม่มีใครรู้วิธีแก้ปัญหานี้?


คำตอบนี้ดีที่สุดสำหรับการเพิ่มฟังก์ชัน REGEXP ลงใน sqlite ใน c # stackoverflow.com/a/26155359/5734452
hubaishan

คำตอบ:


74

SQLite3 รองรับตัวดำเนินการ REGEXP:

WHERE x REGEXP <regex>

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


3
ฉันพบวิธีง่ายๆ: มันเป็นเพียงแค่ \ bx \ b โดยที่ x คือค่าที่จะค้นหาในสตริง :)
cody

12
@ DanS: คุณจะเพิ่มregex()ฟังก์ชันเพื่อสนับสนุนตัวREGEXPดำเนินการได้อย่างไร? โดยค่าเริ่มต้นจะไม่มีการเพิ่มฟังก์ชันผู้ใช้
SK9

48
ตามเอกสาร Sqlite: ตัวดำเนินการ REGEXP เป็นไวยากรณ์พิเศษสำหรับฟังก์ชันผู้ใช้ regexp () ไม่มีการกำหนดฟังก์ชันผู้ใช้ regexp () โดยค่าเริ่มต้นดังนั้นการใช้ตัวดำเนินการ REGEXP โดยปกติจะทำให้เกิดข้อความแสดงข้อผิดพลาด หากมีการเพิ่มฟังก์ชัน SQL ที่กำหนดโดยแอปพลิเคชันชื่อ "regexp" ในขณะรันไทม์ฟังก์ชันนั้นจะถูกเรียกเพื่อใช้ตัวดำเนินการ REGEXP ( sqlite.org/lang_expr.html#regexp )
radicand

สำหรับพวกเราที่ได้รับข้อผิดพลาดเมื่อคุณลองทำเช่นนี้โปรดดูการตอบกลับด้านล่างstackoverflow.com/a/18484596/1585572ฉันใส่รหัสในไฟล์และนำเข้าในฟังก์ชันที่ผู้ใช้กำหนดในตัวจัดการ Firefox sqlite ของฉัน คุณต้องเรียกมันให้แตกต่างกันเล็กน้อยดังนี้: SELECT * FROM table WHERE column regexp ("myregexp")
Tristan

นี่เป็นคำตอบที่ยอมรับได้อย่างไร? โปรดดูคำตอบในอันดับที่สูงขึ้น mivk ด้านล่างstackoverflow.com/a/8338515/828885
akhan

114

ดังที่คนอื่น ๆ ได้กล่าวไว้แล้ว REGEXP เรียกฟังก์ชันที่ผู้ใช้กำหนดซึ่งจะต้องกำหนดและโหลดลงในฐานข้อมูลก่อน บางทีการแจกแจง sqlite หรือเครื่องมือ GUI บางอย่างรวมไว้โดยค่าเริ่มต้น แต่การติดตั้ง Ubuntu ของฉันไม่ได้ วิธีแก้ปัญหาคือ

sudo apt-get install sqlite3-pcre

ซึ่งใช้นิพจน์ทั่วไป Perl ในโมดูลที่โหลดได้ใน /usr/lib/sqlite3/pcre.so

เพื่อให้สามารถใช้งานได้คุณต้องโหลดทุกครั้งที่คุณเปิดฐานข้อมูล:

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

หรือคุณสามารถใส่บรรทัดนั้นลงในไฟล์ ~/.sqlitercไฟล์.

ตอนนี้คุณสามารถสอบถามดังนี้:

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

หากคุณต้องการสอบถามโดยตรงจากบรรทัดคำสั่งคุณสามารถใช้-cmdสวิตช์เพื่อโหลดไลบรารีก่อน SQL ของคุณ:

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

หากคุณใช้ Windows ฉันเดาว่าไฟล์. dll ที่คล้ายกันควรมีอยู่ที่ไหนสักแห่ง


15
ตัวเลือกการโหลดอื่น: ฉันสร้างมุมมองด้วยสิ่งนี้: SELECT load_extension ('/ usr / lib / sqlite3 / pcre.so'); ด้วยวิธีนี้เมื่อฉันใช้จุดเข้าใช้ GUI กับ DB (เช่น SQLite Manager ใน Firefox) ฉันมีวิธีโหลดความสามารถ REGEXP
Paulb

30

วิธีที่แฮ็กในการแก้ปัญหาโดยไม่ใช้ regex คือ where ',' || x || ',' like '%,3,%'


1
ใช่ฉันคิดแบบนั้น แต่ไม่มีผู้นำหรือตาม "," ทุกครั้ง ขอบคุณต่อไป :-)
cody

ฉันไม่ได้สะดุดกับปัญหาที่นี่ - ฉันสงสัยว่ามันทำงานเป็น x เป็นชื่อคอลัมน์หรือไม่ ...
cody

3
คุณควรใช้',' || x || ','
บารุค

22

SQLite ไม่มีฟังก์ชันนิพจน์ทั่วไปตามค่าเริ่มต้น

กำหนดตัวREGEXPดำเนินการ แต่จะล้มเหลวด้วยข้อความแสดงข้อผิดพลาดเว้นแต่คุณหรือกรอบงานของคุณจะกำหนดฟังก์ชันผู้ใช้ที่เรียกว่าregexp()ที่เรียกว่าวิธีที่คุณทำจะขึ้นอยู่กับแพลตฟอร์มของคุณ

หากคุณมีไฟล์ regexp()ฟังก์ชันที่กำหนดไว้คุณสามารถจับคู่จำนวนเต็มโดยพลการจากรายการที่คั่นด้วยจุลภาคดังนี้:

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

แต่จริงๆแล้วดูเหมือนว่าคุณจะพบว่าสิ่งต่างๆง่ายขึ้นมากหากคุณทำให้โครงสร้างฐานข้อมูลของคุณเป็นมาตรฐานโดยการแทนที่กลุ่มเหล่านั้นภายในคอลัมน์เดียวด้วยแถวแยกต่างหากสำหรับแต่ละหมายเลขในรายการที่คั่นด้วยจุลภาค จากนั้นคุณไม่เพียงสามารถใช้ตัว=ดำเนินการแทนนิพจน์ทั่วไปได้ แต่ยังใช้เครื่องมือเชิงสัมพันธ์ที่มีประสิทธิภาพมากขึ้นเช่นการรวมที่ SQL จัดเตรียมไว้ให้คุณ


14

SQLite UDF ใน PHP / PDO สำหรับREGEXPคีย์เวิร์ดที่เลียนแบบพฤติกรรมใน 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;
    }
);

uปรับปรุงไม่ได้ดำเนินการใน MySQL แต่ผมพบว่ามันมีประโยชน์ที่จะมีมันไปโดยปริยาย ตัวอย่าง:

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

ถ้าอย่างใดอย่างหนึ่ง$dataหรือ$patternเป็นโมฆะผลลัพธ์จะเป็นโมฆะเช่นเดียวกับใน MySQL


9

วิธีแก้ปัญหาของฉันใน python ด้วย 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()

หาก regex ตรงกันผลลัพธ์จะเป็น 1 หรือไม่ก็ 0


5

ฉันไม่ควรตอบคำถามที่โพสต์ไว้เมื่อเกือบหนึ่งปีก่อน แต่ฉันกำลังเขียนสิ่งนี้สำหรับผู้ที่คิดว่า Sqlite มีฟังก์ชันREGEXP REGEXP

หนึ่งในความต้องการพื้นฐานในการเรียก REGEXP ฟังก์ชั่นใน SQLite เป็น
"คุณควรสร้างฟังก์ชั่นของคุณเองในโปรแกรมแล้วให้เชื่อมโยงการติดต่อกลับไปยังโปรแกรมควบคุม SQLite"
สำหรับสิ่งนั้นคุณต้องใช้ sqlite_create_function (อินเตอร์เฟส C) คุณสามารถดูรายละเอียดได้จากที่นี่และที่นี่


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

และ:

SELECT * from TableName
 WHERE YourField REGEXP 'YOUR REGEX'

4

ที่ละเอียดถี่ถ้วนหรือที่ซึ่งประโยคสามารถทำได้โดยไม่ต้องต่อสายอักขระ:

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

รวมสี่กรณีที่ตรงกันทุกประการจุดสิ้นสุดของรายการจุดเริ่มต้นของรายการและกลางรายการ

นี่เป็นรายละเอียดมากกว่าไม่ต้องใช้ส่วนขยาย regex


4

ด้วย python สมมติว่าconเป็นการเชื่อมต่อกับ SQLite คุณสามารถกำหนด UDF ที่ต้องการได้โดยเขียน:

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

นี่คือตัวอย่างที่สมบูรณ์ยิ่งขึ้น:

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


ควรตรวจสอบ IMHO if x not Null and y not Null and re.search(x,y)มิฉะนั้นจะโยน
pholat

2

คุณสามารถใช้นิพจน์ทั่วไปกับREGEXPแต่นั่นเป็นวิธีโง่ ๆ ในการจับคู่แบบตรงทั้งหมด

WHERE x = '3'คุณก็ควรจะพูด


ฉันควรจะอธิบายได้ดีกว่านี้ (ขออภัยสำหรับภาษาอังกฤษที่ไม่ดีของฉัน) ฉันหมายถึงค่าที่แน่นอนเท่านั้นไม่ใช่สตริงที่แน่นอน ขอบคุณต่อไป!
cody

2

ลองใช้สิ่งนี้

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

สิ่งนี้จะตรงกับ 3 ทุกประการเมื่อ x อยู่ใน:

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

ตัวอย่างอื่น ๆ :

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

สิ่งนี้จะตรงกับวันที่ 3 หรือ 13


1

ในกรณีที่มีคนมองหาเงื่อนไขที่ไม่ใช่ regex สำหรับAndroid Sqliteชอบสตริงนี้[1,2,3,4,5]อย่าลืมใส่วงเล็บ ( [] ) เหมือนกันสำหรับอักขระพิเศษอื่น ๆ เช่นวงเล็บ ( {} ) ในเงื่อนไข @phyatt

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

0

หากคุณกำลังใช้ PHP คุณสามารถเพิ่มฟังก์ชั่นใด ๆ กับคำสั่ง SQL ของคุณโดยใช้: SQLite3 :: createFunction ใน PDO คุณสามารถใช้PDO :: sqliteCreateFunctionและใช้ฟังก์ชันpreg_matchภายในคำสั่งของคุณ:

ดูว่า Havalite ทำอย่างไร ( RegExp ใน SqLite โดยใช้ Php )


ในฟังก์ชัน MySQL REGEXP คุณไม่จำเป็นต้องระบุตัวคั่นหรือตัวปรับแต่งในรูปแบบ
Alix Axel

0

คุณอาจพิจารณาด้วย

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

สิ่งนี้จะช่วยให้สามารถค้นหาหมายเลข 3 ในสตริงใด ๆ ที่ตำแหน่งใดก็ได้


0

ใน Julia โมเดลที่จะติดตามสามารถแสดงได้ดังนี้:

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.