CREATE UNIQUE INDEX IF NOT EXISTS 仍会在第二次迭代中创建新索引

问题描述 投票:0回答:1

我正在使用数据库来存储从 API 获取的一些数据,然后需要每 5 分钟更新一次数据库(仍然不起作用)。问题是,每次我再次执行代码时,表都会正确更新,没有任何重复项,但索引从 1,2,3,4,.. 到 3000,3001,3002,...(表有 ~3000行,这就是原因)。

这是我正在使用的代码:

import sqlite3

#opening a (new) database
connection = sqlite3.connect("databases/database.db")
cursor = connection.cursor()

#creating table
cursor.execute('''CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY, name TEXT, 
avg24hPrice TEXT, updated TEXT, types TEXT, lastLowPrice TEXT, changeLast48hPercent TEXT, 
iconLink TEXT, wikiLink TEXT,width TEXT, height TEXT, receivedFromTasks TEXT, usedInTasks TEXT,
sellFor TEXT)''')

# Create the unique index if it doesn't exist
cursor.execute('''CREATE UNIQUE INDEX IF NOT EXISTS idx_items_name ON items (name)''')

################################################################
#ALSO TRIED THIS WITHOUT SUCCESS
cursor.execute("PRAGMA INDEX_INFO(idx_items_name)")
index_info = cursor.fetchall()
print("Index_Info: \n", index_info)
if not index_info:
    print("Creating Indexes")
    cursor.execute("DROP INDEX IF EXISTS idx_items_name")
    cursor.execute('''CREATE UNIQUE INDEX IF NOT EXISTS idx_items_name ON items (name)''')
################################################################

#iterating trough a dictionary of items i need to add to the database
for itm in result:
    cursor.execute('''REPLACE INTO items (name, avg24hPrice, updated, types, lastLowPrice,
                      changeLast48hPercent, iconLink, wikiLink, width, height, 
                      receivedFromTasks, usedInTasks, sellFor) 
                      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                   ''',(str(itm["name"]), str(itm["avg24hPrice"]), str(itm["updated"]), 
                       str(itm["types"]), str(itm["lastLowPrice"]),str(itm["changeLast48hPercent"]), 
                       str(itm["iconLink"]), str(itm["wikiLink"]), str(itm["width"]), 
                       str(itm["height"]), str(itm["receivedFromTasks"]), str(itm["usedInTasks"]), 
                       str(itm["sellFor"])))

connection.commit()
#closing database & cursor
cursor.close()
connection.close()
python sqlite sqlite3-python
1个回答
0
投票

当我们说索引从 1,2,3.... 3000 ... 当行数少于 3000 时,这就是它的工作原理。

索引,实际上是行的唯一标识符(rowidid列是其别名)比表中最高的*id大1。

当您替换一行并且它不是具有最高 id 的行时,将删除被替换的行并插入新行,因此 id 将比最高 id 大 1,因此对于每个替换,除非是id最高的行,否则最高id会大于表的行数

按照

当发生 UNIQUE 或 PRIMARY KEY 约束违规时,REPLACE 算法会在插入或更新当前行之前删除导致约束违规的预先存在的行,并且命令继续正常执行。如果发生 NOT NULL 约束冲突,则 REPLACE 冲突解决方案会将 NULL 值替换为该列的默认值,或者如果该列没有默认值,则使用 ABORT 算法。如果发生 CHECK 约束或外键约束违规,则 REPLACE 冲突解决算法的工作方式与 ABORT 类似。

当 REPLACE 冲突解决策略删除行以满足约束时,当且仅当启用递归触发器时,删除触发器才会触发。

id 与您创建的索引完全无关,它们是单独的索引;所有表都存在 rowid 索引,除非该表是使用 NOT ROWID 定义的或者是虚拟表。 name 列上的索引是用户定义的索引。但是,名称列上的 UNIQUE 冲突才是 REPLACE 的触发器,因为您没有为 id 列提供值。

请注意,如果您编码了自动增量(并且不建议您这样做),则行为会略有不同。也就是说,最高的 idrowid的别名)存储在系统表 sqlite_sequence 中,然后 id 将比记录/保存的 id 的较高者大 1。因此,如果替换具有最高 id 的行,则 id 将大 1(如果不使用 AUTOINCRMENT,则不会)。

您不妨参考

https://www.sqlite.org/autoinc.html,其中也涵盖了rowid列。

© www.soinside.com 2019 - 2024. All rights reserved.