有一个 ID类型为SERIAL,即输入数据后数字自动递增。还有第二列,例如名称(varchar)。
名称对数据的唯一性有限制。
CREATE TABLE IF NOT EXISTS users (
ID SERIAL PRIMARY KEY,
Name varchar(150) NOT NULL UNIQUE);
假设该表是:
| ID | Name |
| 1 | Pavel|
然后我尝试输入我知道不符合限制的数据。
INSERT INTO users (Name) VALUES ('Pavel');
将出现唯一性错误并且不会输入数据。
接下来,我输入新的相关数据。
INSERT INTO users (Name) VALUES ('Kristina');
该表如下所示:
| ID | Name |
-----------------
| 1 | Pavel |
| 3 | Kristina |
问题的本质是:尝试输入数据失败后,自动增量增加了ID值,当输入新数据时,ID会跳序(跳过值为2的ID)。
当然,这在很大程度上只是一个美观问题,但我想知道是否有足够的方法以标准或非 sql 方式修复此问题。
我在项目中使用python的方式,竟然成为解决问题的“拐杖”,但我对此并不满意。
def setval():
cur.execute("SELECT ID, Name FROM users ORDER BY id;")
data = cur.fetchall()
cur.execute("DELETE FROM users;")
for index, row in enumerate(data):
cur.execute("""
INSERT INTO users (ID, Name)
VALUES (%s, %s)
""", (index + 1, row[1]))
cur.execute("""SELECT setval('users_ID_seq', (SELECT MAX(id) FROM users));""")
adb.commit()
小串行、串行和大串行类型使用序列,它们在序列中留下间隙是正常的。文档是这么说的。
它还说这样做是有原因的,有正当理由的,强调为“谨慎”。特别是对于多线程处理和插入数据时避免阻塞。常见问题解答中还提供了更多信息。
因此,如果问题只是美观,那么最好保持原样,以免在数据库的性能和操作中产生问题。
否则,如果有必要,您当然可以使用触发器、计算值、生成标识符的表、函数。同时,尝试自己解决这将导致的问题。
UPD
例如,同一常见问题解答中使用序列表的解决方案,这会导致stackoverflow 问题。
让我们创建一个函数,从表中提取 ID 并更新它们。
我们创建一个表并使用该函数。
或者您可以找到其他无间隙序列的解决方案,例如: https: //www.postgresql.org/message-id/ [email protected]
或者尝试 max(id) + 1