如何实现SQLite单表三字段拼接后插入另一表?(PyQt5)
实现details表到view表的数据同步与全名拼接
首先得提个小细节:你创建的view表字段名full name带空格,这在SQL操作里很容易触发语法错误,建议改成full_name(如果非要保留空格,后续SQL语句里得用双引号/反引号把字段名包裹起来)。
下面给你两种实用的实现方案,按需选择:
方案一:保存数据时手动同步(适合简单场景)
直接修改你的save_data方法,在把数据插入details表之后,拼接全名并同步到view表:
def save_data(self): title = self.title_combo.currentText() first_name = self.first_name_line.text() last_name = self.last_name_line.text() mobile = self.mobile_line.text() designation = self.desig_line.text() # 先插入details表 r = self.emp_model.record() r.setValue("title", title) r.setValue("first_name", first_name) r.setValue("last_name", last_name) r.setValue("mobile", mobile) r.setValue("designation", designation) if self.emp_model.insertRecord(-1, r): self.emp_model.select() # 拼接全名,用strip()去掉多余空格(比如title为空时的开头空格) full_name = f"{title} {first_name} {last_name}".strip() # 同步到view表 query = QSqlQuery() # 这里用修改后的full_name字段,若坚持用full name,改成"full name" query.prepare('INSERT INTO view (full_name, mobile, designation) VALUES (?, ?, ?)') query.addBindValue(full_name) query.addBindValue(mobile) query.addBindValue(designation) if not query.exec_(): print(f"同步view表失败: {query.lastError().text()}") # 更新view表的显示 self.view_model.select() else: print(f"插入details表失败: {self.emp_model.lastError().text()}")
别忘了把创建view表的SQL语句同步修改:
query.exec_("CREATE TABLE IF NOT EXISTS view(full_name TEXT, mobile TEXT, designation TEXT)")
方案二:用SQLite触发器自动同步(推荐,更省心)
这种方式不需要在Python代码里维护同步逻辑,直接让数据库自动处理。当details表有插入、更新、删除操作时,view表会自动同步,非常适合需要实时同步的场景。
修改你初始化数据库的代码,添加触发器:
if db.open(): query = QSqlQuery() query.exec_("CREATE TABLE IF NOT EXISTS details(title TEXT, first_name TEXT, last_name TEXT, mobile TEXT, designation TEXT)") # 给view表加details_id字段,关联details表的记录,方便后续更新/删除 query.exec_("CREATE TABLE IF NOT EXISTS view(full_name TEXT, mobile TEXT, designation TEXT, details_id INTEGER)") # 插入触发器:details新增记录时,自动同步到view query.exec_(''' CREATE TRIGGER IF NOT EXISTS sync_details_insert AFTER INSERT ON details BEGIN INSERT INTO view (full_name, mobile, designation, details_id) VALUES ( TRIM(NEW.title || ' ' || NEW.first_name || ' ' || NEW.last_name), NEW.mobile, NEW.designation, NEW.rowid ); END; ''') # 更新触发器:details记录更新时,自动更新view对应记录 query.exec_(''' CREATE TRIGGER IF NOT EXISTS sync_details_update AFTER UPDATE ON details BEGIN UPDATE view SET full_name = TRIM(NEW.title || ' ' || NEW.first_name || ' ' || NEW.last_name), mobile = NEW.mobile, designation = NEW.designation WHERE details_id = NEW.rowid; END; ''') # 删除触发器:details记录删除时,自动删除view对应记录 query.exec_(''' CREATE TRIGGER IF NOT EXISTS sync_details_delete AFTER DELETE ON details BEGIN DELETE FROM view WHERE details_id = OLD.rowid; END; ''') # 后续的model初始化代码不变 self.emp_model = QtSql.QSqlTableModel() self.emp_model.setTable("details") self.emp_model.select() self.details_tableview.setModel(self.emp_model) self.view_model = QtSql.QSqlTableModel() self.view_model.setTable("view") self.view_model.select() self.full_tableview.setModel(self.view_model)
这样一来,不管你是通过UI添加数据,还是直接修改数据库文件,view表都会自动保持同步,完全不用在Python代码里额外维护同步逻辑。
几个小优化建议
- 你的UI里
tilteLabel拼写错误,应该是titleLabel,修正后更规范。 - 拼接全名时用
strip()(Python)或者SQL里的TRIM(),避免出现多余的空格(比如用户没选择title的时候)。 - 如果需要支持更新details表的记录,方案一还得额外处理更新逻辑,而方案二的触发器已经帮你搞定了,这也是推荐方案二的核心原因。
内容的提问来源于stack exchange,提问作者user3030327
相关产品推荐
相关产品推荐

