[英]How can I do REGEXP_REPLACE in SQLAlchemy with SQLite?
[英]How to use regexp function in sqlite with sqlalchemy?
我想在“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())
我發現應該在每個線程上注冊 regexp 函數:
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 中。
我有答案..缺少一行的完整工作腳本是這樣的:
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)沒有這樣的函數:regexp ..”
也許是因為這種變化:
指定基於文件的數據庫時,方言將使用NullPool作為連接源。 此池關閉並丟棄立即返回池的連接。 SQLite基於文件的連接具有極低的開銷,因此不需要池化 。 該方案還可以防止連接在不同的線程中再次使用,並且最適合SQLite的粗粒度文件鎖定。 在0.7版中更改:默認選擇NullPool for SQLite基於文件的數據庫。 以前的版本默認為所有SQLite數據庫選擇SingletonThreadPool。
來自: http : //docs.sqlalchemy.org/en/rel_0_7/dialects/sqlite.html?highlight=isolation_level#threading-pooling-behavior
解決方法是:在'begin'事件中添加regexp 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))
...
差不多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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.