簡體   English   中英

SQLAlchemy在查詢中獲取子字符串

[英]SQLAlchemy getting substring in a query

我有一個帶SQLite的dev數據庫(也可以運行該單元測試),一個帶MySQL的prod數據庫。

我需要使用SQLAlchemy編寫查詢,該查詢在WHERE語句中使用子字符串。 我試圖使用func ,但是它無需修改即可對特定的數據庫引擎進行翻譯。

我的查詢是:

MyTable.field == func.substring_index(OtherTable.other_field, ":", 1)

因此,我基本上想用“:”分割一個值並采用第一部分。

問題是它是用substring_index轉換為SQLite的,這是不正確的。 有沒有辦法在WHERE子句中使用子字符串?

您可以檢查數據庫方言名稱,然后根據該名稱創建子字符串。 例如:

def substring(column, delimeter):
    if session.bind.dialect.name == 'sqlite':
        return func.substr(column, 1, func.instr(column, delimeter) - 1)
    elif session.bind.dialect.name == 'mysql':
        return func.substring_index(column, delimeter, 1)

然后將您的過濾條件替換為:

MyTable.field == substring(OtherTable.other_field, ":")

SQLAlchemy支持自定義SQL構造和編譯擴展以及注冊命名函數 通過這些,您可以將substring_index()注冊為具有SQLite特殊處理功能的函數:

from sqlalchemy.sql.functions import GenericFunction
from sqlalchemy.types import String
from sqlalchemy.ext.compiler import compiles

class substring_index(GenericFunction):
    type = String

@compiles(substring_index, 'sqlite')
def compile_substring_index_sqlite(element, compiler, **kw):
    s, delim, count = element.clauses

    # This assumes that count is a `bindparam`, produced from passing
    # literal integer to `func.substring_index()`.
    assert count.value == 1, "INSTR(X, Y) only supports first occurrence"

    s = compiler.process(s, **kw)
    delim = compiler.process(delim, **kw)

    return f"substr({s}, 1, instr({s}, {delim}) - 1)"

另一個選擇是將Python函數在SQLite中注冊substring_index()

from sqlalchemy import event

def sqlite_substring_index(s, delim, count):
    parts = s.split(delim)

    if count > 0:
        parts = parts[:count]

    else:
        parts = parts[count:]

    return delim.join(parts)

# In your SQLite branch, before anything else DB related is performed:
@event.listens_for(engine, 'connect')
def create_functions(dbapi_connection, connection_record):
    dbapi_connection.create_function('substring_index', 3, sqlite_substring_index)

有了該函數,您可以像在MySQL中一樣調用它。


至於為什么它不是現成的SQLAlchemy庫的一部分,由於不同的DBMS支持完全不同的功能,這將是一場無盡的戰斗。 例如,某些三角函數的名稱各相同,而SQLite根本沒有提供它們 在單個代碼庫中支持不同的SQL DBMS並非易事,而且常常不僅僅值得這樣做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM