【问题标题】:SQLite starting rowid of 0SQLite 起始 rowid 为 0
【发布时间】:2016-05-04 18:03:33
【问题描述】:

我正在尝试设置一个 SQLite 表,其中 rowid 从 0 而不是默认的 1 开始。最终目标是能够运行第一个 INSERT 语句并将其插入 rowid 0。显式设置 rowid 为0 表示第一个 INSERT 不是一个选项。

我已经尝试了一些与 AUTOINCREMENT 相关的事情,但我没有任何运气让它干净地工作。我发现的唯一成功的方法是插入一个 rowid 为 -1 的行,然后再将其删除。这行得通,但很乱,我想找到一种更清洁的方法。我正在使用内置 sqlite3 库在 Python 2.7 中工作。

底线问题:

除了手动插入 -1 值然后稍后将其删除之外,还有更简洁的方法从 0 开始 rowid 吗?


一些辅助信息:

我在这里发现了一个类似的问题,并使用了一些 AUTOINCREMENT 设置:Set start value for AUTOINCREMENT in SQLite

sqlite_sequence 表似乎不适用于负数。我使用以下方法对其进行了测试:

import sqlite3
con = sqlite3.Connection('db.db')
cur = con.cursor()

cur.execute("CREATE TABLE test(id INTEGER PRIMARY KEY AUTOINCREMENT, val TEXT)")
cur.execute("INSERT INTO sqlite_sequence (name,seq) VALUES (?,?)", ('test',-1))
cur.execute("INSERT INTO test (val) VALUES (?)", ('testval',)) #becomes rowid 1
cur.execute("INSERT INTO test (val) VALUES (?)", ('testval',)) #becomes rowid 2
cur.execute("INSERT INTO test (val) VALUES (?)", ('testval',)) #becomes rowid 3

cur.execute("SELECT rowid, id, val FROM test")
print cur.fetchall()

将 -1 插入 sqlite_sequence 后,它应该将下一个 rowid 设置为 0,但它使用 1 代替。如果 sqlite_sequence 被初始化为正数,则 rowid 符合预期。

import sqlite3
con = sqlite3.Connection('db.db')
cur = con.cursor()

cur.execute("CREATE TABLE test(id INTEGER PRIMARY KEY AUTOINCREMENT, val TEXT)")
cur.execute("INSERT INTO sqlite_sequence (name,seq) VALUES (?,?)", ('test',10))
cur.execute("INSERT INTO test (val) VALUES (?)", ('testval',)) #becomes rowid 11
cur.execute("INSERT INTO test (val) VALUES (?)", ('testval',)) #becomes rowid 12
cur.execute("INSERT INTO test (val) VALUES (?)", ('testval',)) #becomes rowid 13

cur.execute("SELECT rowid, id, val FROM test")
print cur.fetchall()

自动增量不支持这样的负数吗?我在 SQLite 文档中找不到任何提及。

【问题讨论】:

    标签: python-2.7 sqlite auto-increment


    【解决方案1】:

    documentation 表示,使用 AUTOINCREMENT,

    为新行选择的 ROWID 至少比以前存在于同一个表中的最大 ROWID 大一个。

    因此该算法不仅会查看sqlite_sequence 表中的值,还会查看表中的最后一行,并使用这两个值中的较大者。

    当 table 为空时,最大的实际 rowid 被假定为零。这样做是为了使第一个插入的 rowid 变为 1

    因此,生成小于 1 的 rowid 的唯一方法是在表中已有另一行。

    【讨论】:

    • 感谢您提供的信息。我的印象是 sqlite_sequence 表是唯一使用的来源,但这是有道理的。
    【解决方案2】:

    我在 java 中使用 sqlite,无意中将第一行设置为 ROWID=0。

    这里是代码

        long dbid = getDbid();
        ContentValues values = new ContentValues();
        values.put(KEY_ROWID, dbId); // Line that cause ROWID == 0 when dbid == 0
        values.put(KEY_KEY, key);
        values.put(KEY_VALUE, value);
        if (dbId == 0) {
            dbId = dbase.insert(PREFERENCES_TABLE, null, values);
            map_.put(key, new Pair<>(dbId, value));
        }
        else
            dbase.update(PREFERENCES_TABLE, values, KEY_ROWID + "=" + dbId, null);
    

    目的是让零成为未初始化的值,但插入返回零。我不希望第一个 ROWID 等于 0,所以我删除了该行并插入返回一个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-09
      • 2012-01-05
      • 1970-01-01
      相关资源
      最近更新 更多