我有一个关于从数据库中删除记录的问题。数据显示在 QTableView 中并按日期排序。问题是,如果我使用 QTableView 的当前索引作为“行”,则会删除错误的记录,因为它们在数据库中的排序方式不同。例如,我单击第一行并得到 0 作为索引,但另一条记录存储在数据库中的索引 0 下。如何让它点击 QTableView 中的记录并将其删除?
我使用 Pyside6 和 Sqlite。对于数据库操作,如加载、删除、排序、插入等。我使用 QtSql 和 QSqlRelationalTableModel。我不使用 SQL 或 QtSql SQL 查询,我依赖数据模型。
谢谢!
问题是,如果我使用 QTableView 的当前索引作为“行”,则会删除错误的记录,因为它们在数据库中的排序方式不同。
简而言之,你永远不应该假设 UI 中的第 n 个对象等于数据库中的第 n 行,这种情况很少发生。
数据库中的行不是按排序存储的,它们只是存储,当处理(搜索)行时,它们根据被认为最合适的索引进行处理。这包括可能根据 ORDER BY 子句进行的检索(可以指定也可以不指定,如果未指定则根据查询优化器决定)。
通常,
rowid
或其别名是典型的索引。 rowid
的别名将在以下情况下存在/创建:-
对于作为
rowid
别名的列,如果在插入行时未分配值或分配 NULL
值,则该值将由 SQLite 生成。对于第一行,这样的值将为 1,或者比以下值大 1:-
rowid
的最高记录(曾经存在)值。在这种情况下
rowid
那么除非强制,否则该值永远不会是0。
因此,您的点击很可能使用呈现给 UI 的列表中的索引(位置),该索引很可能不是
rowid
或其别名,因此,如果使用 UI 索引值,则不会删除预期的行但会删除另一行或不删除任何行。
您应该做的是从单击的 UI 索引处的数据(对象)中提取一个或多个值,该索引可用于唯一标识相关行。然后,DELETE 或 UPDATE 应使用 WHERE 子句中的一个或多个值。
也许可以考虑以下使用 SQLite 工具的演示说明:-
DROP TABLE IF EXISTS t;
CREATE TABLE IF NOT EXISTS t
(
id INTEGER PRIMARY KEY, /* will be an alias of the rowid*/
d1 whatever, /* type affinity resolved SQLite (which will be NUMERIC) */
d2 TEXT
)
;
/* Insert some data where the rowid (id is an alias of the rowid)*/
INSERT INTO t (d1,d2) VALUES
('d1-01','d2-01'),('d1-02','d2-02'),('d1-03','d2-03')
;
/* insert some additional data BUT this time specifying a value for the rowid alias (id column)*/
INSERT INTO t (id,d1,d2) VALUES
(10,'d1-04','d2-04'),(null,'d1-05','d2-05'),
(-100 /* yes rowid can be negative*/,'d1-06','d2-06'),
(null,'d1-07','d2-07') ,
(0,'d1-08','d2-08') /* Only way to have an id of 0 is to force 0 by specifying it (SQLite will not generate a value of 0)*/
/* .... */
;
/* SELECT DATA however SQLite determines (probably according to the primary key)*/
/* NOTE that even though -100 id value was inserted as the 6th row is is the 1st row selected */
SELECT * FROM t;
/* Data selected according to the ORDER BY extracts in a different order */
/* NOTE that due to the d1 column adhereing to the sequence of insertion that the order is therefore now according to the insertion*/
SELECT * FROM t ORDER BY d1;
/* clean up the demo environment*/
DROP TABLE IF EXISTS t;
现在考虑两个输出(选择)。
第一次提取:-
假设图像就是 UI 所呈现的内容:-
如果这是驱动 UI,则第一行(UI 索引 0)将具有唯一标识该行的 id 为 -100。如果 UI 索引 0 用于驱动更新,则显示
-100 d1-06 and d2-06
的数据实际上会删除包含数据 0 d1-08 and d2-08
的行。
如果使用 UI 索引 5(“10 d1-01 和 d204”),则由于没有 id 为 5 的行,因此不会删除任何行。
第二次提取:-
如果这是驱动 UI,则第一行(UI 索引 0)将具有唯一标识该行的 id 为 -1。如果 UI 索引 0 用于驱动更新,则显示
1 d1-01 and d2-01
的数据实际上会删除包含数据 0 d1-08 and d2-08
的行。
如果使用 UI 索引 5('-100 d1-06 和 d2-06'),则由于没有 id 为 5 的行,因此不会删除任何行。