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

如何基于姓名两列实现数据库表的Qt实时搜索功能

多列搜索实现方案

方案一:SQL层面过滤(推荐,大数据量更高效)

直接在SQL语句中同时匹配firstname和surname列,从数据库层面筛选符合条件的记录,减少客户端处理的数据量,性能更优。

修改后代码示例

def on_search_text_changed(text):
    # 参数化查询避免SQL注入风险
    search_method = '''
        SELECT id_no, firstname, surname 
        FROM name_list 
        WHERE firstname LIKE ? OR surname LIKE ?
    '''
    # 构造模糊匹配参数,支持任意位置的字符匹配
    search_param = f'%{text}%'
    sql_search_method = cur.execute(search_method, (search_param, search_param)).fetchall()
    
    # 清空模型并重新填充数据
    model.clear()
    model.setHorizontalHeaderLabels(['Id_no','First Name','Surname'])
    for row_idx, (id_no, firstname, surname) in enumerate(sql_search_method):
        model.setItem(row_idx, 0, QStandardItem(id_no))
        model.setItem(row_idx, 1, QStandardItem(firstname))
        model.setItem(row_idx, 2, QStandardItem(surname))

# 绑定搜索框文本变化信号
self.ui.lineEdit.textChanged.connect(on_search_text_changed)

# 表格样式初始化
self.ui.tableView.setStyleSheet('font-size: 12px;')
self.ui.tableView.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.ui.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.ui.tableView.setModel(model)

关键说明

  • 必须使用参数化查询(?占位符),避免SQL注入安全问题
  • LIKE '%{text}%'实现模糊匹配,输入字符出现在姓名任意位置都能命中
  • 每次搜索文本变化时重新查询数据库,保证数据实时准确

方案二:Qt代理模型层面多列过滤

如果数据量较小,不想频繁请求数据库,可以先加载全量数据,通过自定义代理模型实现多列过滤。

自定义代理模型代码

from PyQt5.QtCore import QSortFilterProxyModel

class MultiColumnFilterProxyModel(QSortFilterProxyModel):
    def filterAcceptsRow(self, source_row, source_parent):
        pattern = self.filterRegExp()
        if pattern.isEmpty():
            return True
        
        source_model = self.sourceModel()
        # 检查第1列(First Name)和第2列(Surname)
        for col in [1, 2]:
            index = source_model.index(source_row, col, source_parent)
            data = source_model.data(index)
            if pattern.indexIn(data) != -1:
                return True
        return False

# 初始化全量数据模型
search_method = ''' SELECT id_no,firstname,surname FROM name_list'''
sql_search_method = cur.execute(search_method).fetchall()

model = QStandardItemModel(len(sql_search_method), 3)
model.setHorizontalHeaderLabels(['Id_no','First Name','Surname'])
for row_idx, (id_no, firstname, surname) in enumerate(sql_search_method):
    model.setItem(row_idx, 0, QStandardItem(id_no))
    model.setItem(row_idx, 1, QStandardItem(firstname))
    model.setItem(row_idx, 2, QStandardItem(surname))

# 使用自定义多列过滤代理
filter_proxy_model = MultiColumnFilterProxyModel()
filter_proxy_model.setSourceModel(model)
filter_proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)

self.ui.lineEdit.textChanged.connect(filter_proxy_model.setFilterRegExp)

# 表格样式设置
self.ui.tableView.setStyleSheet('font-size: 12px;')
self.ui.tableView.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.ui.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.ui.tableView.setModel(filter_proxy_model)

关键说明

  • 重写filterAcceptsRow方法,遍历需要过滤的列,只要任意一列匹配搜索文本就保留该行
  • 适合数据量不大的场景,避免频繁数据库请求

原代码问题修正

你原来的代码存在两处关键错误:

  • model = QStandardItemModel(len(sql_search_method), 1) 列数设为1,但实际有3列数据,需改为3
  • 循环赋值时model.setItem(row, 1, item) 只往第1列填充数据,导致其他列为空,需按对应列索引分别赋值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 16:06:42