Python sqlite3 - 如何在删除某些行后重置INTEGER PRIMARY KEY id的值

时间:2014-01-15 21:54:22

标签: python sql sqlite

现在我正在开发一个带数据库的项目。当我删除一些行时,我想要它,因此ID被重置,因此它们之间没有间隙。 这是我想要的一个例子。

当前数据库。

ID: 1 Date: Date Exercise: Squat Sets: 3 Reps: 3 Weight: 3.0
ID: 2 Date: Date Exercise: Squat Sets: 3 Reps: 3 Weight: 3.0
ID: 3 Date: Date Exercise: Squat Sets: 1 Reps: 2 Weight: 3.0
ID: 4 Date: Date Exercise: Squat Sets: 1 Reps: 2 Weight: 3.0
ID: 5 Date: Date Exercise: Squat Sets: 1 Reps: 2 Weight: 3.0
ID: 6 Date: Date Exercise: Squat Sets: 1 Reps: 2 Weight: 3.0
ID: 7 Date: Date Exercise: Squat Sets: 1 Reps: 1 Weight: 4.0
ID: 8 Date: Date Exercise: Squat Sets: 1 Reps: 1 Weight: 4.0
ID: 9 Date: Date Exercise: Squat Sets: 1 Reps: 1 Weight: 4.0
ID: 10 Date: Date Exercise: Squat Sets: 1 Reps: 1 Weight: 4.0

删除第3行到第7行会产生......

ID: 1 Date: Date Exercise: Squat Sets: 3 Reps: 3 Weight: 3.0
ID: 2 Date: Date Exercise: Squat Sets: 3 Reps: 3 Weight: 3.0
ID: 8 Date: Date Exercise: Squat Sets: 1 Reps: 1 Weight: 4.0
ID: 9 Date: Date Exercise: Squat Sets: 1 Reps: 1 Weight: 4.0
ID: 10 Date: Date Exercise: Squat Sets: 1 Reps: 1 Weight: 4.0

这就是我想要的......

ID: 1 Date: Date Exercise: Squat Sets: 3 Reps: 3 Weight: 3.0
ID: 2 Date: Date Exercise: Squat Sets: 3 Reps: 3 Weight: 3.0
ID: 3 Date: Date Exercise: Squat Sets: 1 Reps: 1 Weight: 4.0
ID: 4 Date: Date Exercise: Squat Sets: 1 Reps: 1 Weight: 4.0
ID: 5 Date: Date Exercise: Squat Sets: 1 Reps: 1 Weight: 4.0

这是我目前的功能......

def delete_range(self):
        """
        Deletes a range of rows in the SQL events table. The range is determined by entries in the starting and ending
        DeleteRowEntry entries. 
        """
        starting_index = int(self.startingRowEntry.get())
        ending_index = int(self.endingRowEntry.get())

        conn = lite.connect('fit.db')
        cursor = conn.cursor()
        cursor.execute("""DELETE  FROM events WHERE(id >= (?))
                                  AND (id <= (?))""",(starting_index,ending_index))
        cursor.execute("""DELETE FROM SQLITE_SEQUENCE WHERE NAME = 'events'""")   
        conn.commit()
        conn.close

这是我正在进行操作的表的设置。

cursor.execute('''CREATE TABLE IF NOT EXISTS events( id INTEGER PRIMARY KEY , date text, exercise_id int, sets int, reps int, weight real)''')

2 个答案:

答案 0 :(得分:1)

您根据ending_indexid之间的差异更新ending_index之后的所有行,以获得新的starting_index

cursor.execute("""UPDATE events SET id=id - ? WHERE id > ?""", 
               ((ending_index - starting_index) + 1, ending_index))

不要删除events表中的SQLITE_SEQUENCE行;相反,请在上述MAX(id)之后使用events的{​​{1}}进行更新。

但你通常真的不想这样做;其他表和外部系统希望UPDATE行ID保持稳定。

如果您担心用户对事件ID中的间隙感到困惑,请不要向最终用户显示这些ID。您始终可以按顺序对GUI中的可见行进行编号,但仍然可以单独跟踪实际的数据库ID。

答案 1 :(得分:0)

这几乎肯定是一个非常糟糕的主意 - 关键的重点在于它们是一种稳定的方式来引用记录(在另一种情况下使用外键,或者在应用程序中等)。

但如果你真的想要,只需按ID顺序遍历行并将它们设置为“正确”的值,如下所示:

cursor.execute('SELECT id FROM events ORDER BY id')
inner_cursor = db.cursor()
for i, row in enumerate(cursor):
    inner.execute('UPDATE events SET id = ? WHERE id = ?', i, row[0])

您可以通过两种方式对其进行优化:

  1. 每次修改后都不要这样做,但只能在批次中的最后一次修改之后再进行。
  2. 如果您在每次修改后都这样做,只需修改ending_index之后的那些,并使用一个UPDATE将每个修改设为id - gap