【问题标题】:How to use regexp function in sqlite with sqlalchemy?如何在带有 sqlalchemy 的 sqlite 中使用 regexp 函数?
【发布时间】:2026-02-04 12:10:01
【问题描述】:

我想在“sqlalchemy”中使用正则表达式查询以及在“python sqlite”中完成,代码如下..

未完成的沙盒脚本是这样的:

import os
import re
import sqlite3

#
# python sqlite
#

DB_PATH = __name__ + '.db'

try:
    os.remove(DB_PATH)
except:
    pass


def re_fn(expr, item):
    reg = re.compile(expr, re.I)
    return reg.search(item) is not None

conn = sqlite3.connect(':memory:')
conn = sqlite3.connect(DB_PATH)
conn.create_function("REGEXP", 2, re_fn)
cursor = conn.cursor()

cursor.execute(
    'CREATE TABLE t1 (id INTEGER PRIMARY KEY, c1 TEXT)'
)
cursor.executemany(
    #'INSERT INTO t1 (c1) VALUES (?)', [('aaa"test"',),('blah',)]
    'INSERT INTO t1 (c1) VALUES (?)', [
        ('dupa / 1st Part',), ('cycki / 2nd Part',), ('fiut / 3rd Part',)
    ]
)
cursor.execute(
    #'SELECT c1 FROM t1 WHERE c1 REGEXP ?',['2|3\w+part']
    'SELECT c1 FROM t1 WHERE c1 REGEXP ?',['\d\w+ part']
)
conn.commit()
data=cursor.fetchall()
print(data)



#
# sqlalchemy
#

import sqlalchemy as sa
import sqlalchemy.orm as orm
from sqlalchemy.ext.declarative import declarative_base

DSN = 'sqlite:///' + DB_PATH
engine = sa.create_engine(DSN, convert_unicode=True)
db = orm.scoped_session(orm.sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))

Base = declarative_base(bind=engine)
meta = Base.metadata

class T1(Base):
    __table__ = sa.Table('t1', meta, autoload=True)

print(db.query(T1).all())

我发现应该在每个线程上注册正则表达式函数:

http://permalink.gmane.org/gmane.comp.web.pylons.general/12742

但我无法对我的脚本采用链接的解决方案 + 它已被弃用。

更新

我想查询这个:

cursor.execute(
    #'SELECT c1 FROM t1 WHERE c1 REGEXP ?',['2|3\w+part']
    'SELECT c1 FROM t1 WHERE c1 REGEXP ?',['\d\w+ part']
)

但在 sqlalchemy 中。

【问题讨论】:

  • 我不明白你在做什么。你有什么错误?

标签: python regex sqlalchemy


【解决方案1】:

我已经得到了答案.. 缺少一行的完整工作脚本是这样的:

import os
import re
import sqlite3

DB_PATH = __name__ + '.db'

try:
    os.remove(DB_PATH)
except:
    pass


def re_fn(expr, item):
    reg = re.compile(expr, re.I)
    return reg.search(item) is not None

conn = sqlite3.connect(':memory:')
conn = sqlite3.connect(DB_PATH)
conn.create_function("REGEXP", 2, re_fn)
cursor = conn.cursor()

cursor.execute(
    'CREATE TABLE t1 (id INTEGER PRIMARY KEY, c1 TEXT)'
)
cursor.executemany(
    #'INSERT INTO t1 (c1) VALUES (?)', [('aaa"test"',),('blah',)]
    'INSERT INTO t1 (c1) VALUES (?)', [
        ('dupa / 1st Part',), ('cycki / 2nd Part',), ('fiut / 3rd Part',)
    ]
)
SEARCH_TERM = '3rd part'
cursor.execute(
    #'SELECT c1 FROM t1 WHERE c1 REGEXP ?',['2|3\w+part']
    'SELECT c1 FROM t1 WHERE c1 REGEXP ?',[SEARCH_TERM]
)
conn.commit()
data=cursor.fetchall()
print(data)



#
# sqlalchemy
#

import sqlalchemy as sa
import sqlalchemy.orm as orm
from sqlalchemy.ext.declarative import declarative_base

DSN = 'sqlite:///' + DB_PATH

engine = sa.create_engine(DSN, convert_unicode=True)

conn = engine.connect()
conn.connection.create_function('regexp', 2, re_fn)

db = orm.scoped_session(orm.sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))

Base = declarative_base(bind=engine)
meta = Base.metadata

class T1(Base):
    __table__ = sa.Table('t1', meta, autoload=True)

print(db.query(T1.c1).filter(T1.c1.op('regexp')(SEARCH_TERM)).all())

以上适用于 sqlalchemy=0.6.3

在 sqlalchemy=0.7.8 中出现错误:

"sqlalchemy.exc.OperationalError: (OperationalError) 没有这样的功能: 正则表达式..”

也许是因为这个变化:

当指定基于文件的数据库时,方言将使用 NullPool 作为连接的来源。 此池关闭并丢弃 立即返回池的连接。 SQLite 基于文件的连接具有极低的开销,因此池化不是 必要的。该方案还可以防止再次使用连接 在不同的线程中,最适合使用 SQLite 的粗粒度文件 锁定。 在 0.7 版更改: SQLite 的 NullPool 的默认选择 基于文件的数据库。以前的版本选择 SingletonThreadPool by 所有 SQLite 数据库的默认设置。

来自:http://docs.sqlalchemy.org/en/rel_0_7/dialects/sqlite.html?highlight=isolation_level#threading-pooling-behavior

解决方案是: 在“开始”事件中添加正则表达式 fn,如下所示:

...

conn = engine.connect()
@sa.event.listens_for(engine, "begin")
def do_begin(conn):
    conn.connection.create_function('regexp', 2, re_fn)

db = orm.scoped_session(orm.sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))

...

【讨论】:

  • 我不明白“re_fn”从哪里得到正则表达式模式?您只将您的 search_term 作为参数,但该函数要求两个。谢谢!
  • 我猜item 参数是由 SQL 引擎注入的一行。所以程序员指定正则表达式(如“\d+”),SQL 引擎注入 db 行。让这两个在re_fn 中决定是否返回特定行。
  • 哦,好的,'3rd part'expr,而不是 ìtem!谢谢
【解决方案2】:

差不多 10 年后...

它在 SQLAlchemy 1.4 中更容易工作:

stmt = select(table.c.some_column).where(
    table.c.some_column.regexp_match('^(b|c)')
)

来源:https://docs.sqlalchemy.org/en/14/core/sqlelement.html#sqlalchemy.sql.expression.ColumnElement.regexp_match

【讨论】:

    最近更新 更多