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

迁移至MariaDB后Django查询变为大小写敏感的问题排查

Django迁移MariaDB后查询大小写敏感问题的原因与解决方法

问题原因

Django针对MySQL/MariaDB数据库,使用__contains查询时,会自动在生成的SQL语句中添加BINARY关键字,强制进行大小写敏感匹配,这会覆盖数据库排序规则(utf8mb3_general_ci)的不区分大小写特性。而你手动执行的SQL没有BINARY修饰,因此能正常利用排序规则实现不区分大小写查询,这就是代码查询和交互式查询结果不一致的核心原因。

解决方法

方法1:使用__icontains替换__contains

__icontains是Django专门提供的不区分大小写包含查询,生成的SQL不会添加BINARY关键字,完全利用数据库的_ci排序规则实现不区分大小写匹配,是最直接的解决方式。修改后的代码如下:

def get_queryset(self):
    query = self.request.GET.get('query')

    if query:
        query = " ".join(query.split())

        if query.isdigit():
            qs = Patient.objects.filter(Q(full_name__icontains=query) | Q(patient_id__icontains=query)).order_by('patient_id')
        else:
            qs = Patient.objects.filter(Q(full_name__icontains=query) | Q(patient_id__icontains=query)).order_by(Lower('full_name'))
    else:
        qs = Patient.objects.order_by(Lower('full_name'))

    return qs

方法2:指定模型字段的排序规则

如果希望继续使用__contains,可以在模型的对应字段上显式指定db_collation参数,确保模型层与数据库层的排序规则一致(即使你已设置数据库排序规则,显式指定字段级规则能避免潜在的不匹配问题):

class Patient(models.Model):
    full_name = models.CharField(max_length=255, db_collation='utf8mb3_general_ci')
    patient_id = models.CharField(max_length=50, db_collation='utf8mb3_general_ci')
    # 其他字段定义...

修改后需要生成并执行数据库迁移,更新字段的排序规则。

内容的提问来源于stack exchange,提问作者Andy Walldorff

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 03:55:03