You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Flask-SQLAlchemy调用split_part报错:SQLite无该函数

问题原因与解决方案

错误核心原因

  1. SQLite不支持split_part()函数:split_part是PostgreSQL等数据库的专属函数,SQLite原生未实现该函数,直接调用会抛出no such function错误。
  2. 索引参数错误:即使在支持split_part的数据库中,该函数的第三个参数是1-based索引(从1开始计数),你代码中写的0会返回空字符串,根本无法匹配'30:20'这类格式的字符串。

解决方案一:用SQLite原生函数实现过滤

直接使用SQLite自带的instr(查找字符位置)和substr(截取字符串)函数组合,实现冒号前部分的提取与比较:

from sqlalchemy import and_, func

check_already_added = db.session.query(allocations).filter(
    and_(
        allocations.name == "Filiday",
        # 截取冒号前的部分并转为整数,和30比较
        func.cast(
            func.substr(
                allocations.room_number,
                1,
                func.instr(allocations.room_number, ':') - 1
            ),
            db.Integer
        ) == 30
    )
).first()

if check_already_added is None:
    print(check_already_added)

逻辑说明:

  • instr(allocations.room_number, ':')获取冒号在字符串中的位置
  • substr(..., 1, 位置-1)截取从开头到冒号前的子串
  • cast(..., db.Integer)将子串转为整数,避免字符串比较的潜在问题

解决方案二:给SQLite注册自定义split_part函数

如果想保留原有代码的风格,可以给SQLite注册一个自定义的split_part函数,让SQLAlchemy可以直接调用:

  1. 定义自定义函数逻辑:
import sqlite3

def split_part(s, sep, index):
    # 处理空值或不存在的索引
    if not s:
        return ''
    parts = s.split(sep)
    # 转换为1-based索引(和SQL函数规则保持一致)
    index = int(index) - 1
    return parts[index] if 0 <= index < len(parts) else ''
  1. 在Flask应用初始化时注册该函数(需在数据库连接初始化完成后执行):
# 假设你的db是Flask-SQLAlchemy的实例
with db.engine.connect() as conn:
    conn.connection.create_function('split_part', 3, split_part)
  1. 修改原代码的索引参数为1(符合SQL函数的1-based规则):
from sqlalchemy import and_, func

check_already_added = db.session.query(allocations).filter(
    and_(
        allocations.name == "Filiday",
        func.split_part(allocations.room_number, ':', 1) == '30'
    )
).first()

内容的提问来源于stack exchange,提问作者John Paul K.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 19:40:21