SQLite:在保留数据的同时将带有主键的列添加到现有 table

SQLite: Add column with primary key to existing table whilst persisting data

在 SQLite 的上下文中。

我有一个现有的 table,目前填充了多行数据。

我正在尝试向此 table 添加一个新的主键列,同时保留原始数据。

如下所示,我尝试了以下

  1. 向现有的 table 添加一个新列(Id INTEGER)。
  2. 更改现有名称table。
  3. 创建一个新的 table,其中包含新的主键 (Id INTEGER PRIMARY KEY)。
  4. 将重命名的 table 中的所有数据插入新创建的 table。
  5. 删除重命名的table。

我认为这可行的原因是因为根据 SQlite 文档,

A column declared INTEGER PRIMARY KEY will autoincrement.

但是我收到以下错误。

ErrorCode : 19
Message   : constraint failed
UNIQUE constraint failed: Person.Id
Result    : Constraint

这是我的代码。

--Add a new column to the existing table(Id INT).
ALTER TABLE [Person]
ADD Id INTEGER;

--Change the name of the existing table.
ALTER TABLE [Person] RENAME TO Person_temp;

--Create a new table which includes the new PK.
CREATE TABLE Person(
    Id INTEGER PRIMARY KEY,
    FirstName nvarchar(100) NULL,
    LastName nvarchar(100) NULL
);

--Insert all data from the renamed table into the new table.
INSERT INTO Person SELECT * FROM Person_temp;

--Drop the renamed table.
DROP TABLE Person_temp;

任何人都可以解释一下吗?

您的 ID 列似乎在每一行中都不包含唯一值。由于您刚刚添加了该列,因此每一行都将具有相同的值。

当您插入新行时,自动增量会有所帮助。 (您不必 select max(id),并插入 id = max+1 的新行)。它不会自动填充现有的 table 数据。

SQLite 已经有一个可以满足您需要的列。它被称为ROWID。尝试使用它而不是将其复制到您的 Id 列。

由于您没有在插入查询中声明列名,因此列顺序取决于 它们在创建/添加位置的顺序。尝试指定列名。无论如何,这通常是一个很好的做法

--Insert all data from the renamed table into the new table.
INSERT INTO Person(Id, FirstName, LastName) SELECT Id, FirstName, LastName FROM Person_temp;

顺便说一下,您可能不需要在第一个 table 中添加 Id 列:

--Insert all data from the renamed table into the new table.
INSERT INTO Person(FirstName, LastName) SELECT FirstName, LastName FROM Person_temp;

Id 的隐式空值将被自动增量

替换