SQLITE:如何将 rowid 列变成常规列
SQLITE: how can I turn the rowid column into a regular column
假设我创建了一个 table 并通过以下操作插入一行:
CREATE TABLE people (first_name text NOT NULL, last_name text NOT NULL );
INSERT INTO people (first_name, last_name) VALUES ('John', 'Doe');
我可以执行:
SELECT rowid as ID, first_name, last_name FROM people
并按预期取回三列数据。
但是,假设我想将自动 rowid 列变成常规列,这样行的 ID 就不会在删除时发生变化,等等。
我该怎么做?
我试过的是:
ALTER TABLE people ADD people_id INTEGER;
ALTER TABLE people ADD PRIMARY KEY (people_id);
第一个语句成功,但是第二个语句给我一个错误:
near "PRIMARY": syntax error: ALTER TABLE people ADD PRIMARY
如果我最初将 table 创建为:
CREATE TABLE people (people_id INTEGER PRIMARY KEY, first_name text NOT NULL, last_name text NOT NULL );
我会从一开始就拥有我正在寻找的那种 table。
在 people_id 列中维护 rowid 值很重要。例如,假设 John Doe 在 people 的 rowid 47 中。转换后,李四的 people_id 需要为 47.
我想我可以简单地将数据从一个 table 复制到另一个,但我想知道是否有更好或标准的方法来完成这种转换。
您必须创建一个新的 table,复制所有内容,删除旧的 table,然后重命名新的:
CREATE TABLE new_people(people_id INTEGER PRIMARY KEY
, first_name TEXT NOT NULL,
, last_name TEXT NOT NULL);
INSERT INTO new_people(first_name, last_name) SELECT first_name, last_name FROM people;
DROP TABLE people;
ALTER TABLE new_people RENAME TO people;
Shawn 的回答是合理的(我已经赞成),但我会提供一个变体,我认为它稍微简洁一些,因为新的 table 不会出现在模式中报价:
TRANSACTION;
ALTER TABLE people RENAME TO old_people;
CREATE TABLE people(people_id INTEGER PRIMARY KEY
, first_name TEXT NOT NULL,
, last_name TEXT NOT NULL);
INSERT INTO people(people_id, first_name, last_name)
SELECT rowid, first_name, last_name FROM old_people;
DROP TABLE old_people;
COMMIT;
VACUUM;
只要table的实际存储格式不变,可以用一个极度危险backdoor来改变table定义:
PRAGMA writable_schema = on;
UPDATE sqlite_master
SET sql = 'CREATE TABLE people(people_id INTEGER PRIMARY KEY, first_name text NOT NULL, last_name text NOT NULL )'
WHERE type = 'table'
AND name = 'people';
-- and now re-open the database file
假设我创建了一个 table 并通过以下操作插入一行:
CREATE TABLE people (first_name text NOT NULL, last_name text NOT NULL );
INSERT INTO people (first_name, last_name) VALUES ('John', 'Doe');
我可以执行:
SELECT rowid as ID, first_name, last_name FROM people
并按预期取回三列数据。
但是,假设我想将自动 rowid 列变成常规列,这样行的 ID 就不会在删除时发生变化,等等。
我该怎么做?
我试过的是:
ALTER TABLE people ADD people_id INTEGER;
ALTER TABLE people ADD PRIMARY KEY (people_id);
第一个语句成功,但是第二个语句给我一个错误:
near "PRIMARY": syntax error: ALTER TABLE people ADD PRIMARY
如果我最初将 table 创建为:
CREATE TABLE people (people_id INTEGER PRIMARY KEY, first_name text NOT NULL, last_name text NOT NULL );
我会从一开始就拥有我正在寻找的那种 table。
在 people_id 列中维护 rowid 值很重要。例如,假设 John Doe 在 people 的 rowid 47 中。转换后,李四的 people_id 需要为 47.
我想我可以简单地将数据从一个 table 复制到另一个,但我想知道是否有更好或标准的方法来完成这种转换。
您必须创建一个新的 table,复制所有内容,删除旧的 table,然后重命名新的:
CREATE TABLE new_people(people_id INTEGER PRIMARY KEY
, first_name TEXT NOT NULL,
, last_name TEXT NOT NULL);
INSERT INTO new_people(first_name, last_name) SELECT first_name, last_name FROM people;
DROP TABLE people;
ALTER TABLE new_people RENAME TO people;
Shawn 的回答是合理的(我已经赞成),但我会提供一个变体,我认为它稍微简洁一些,因为新的 table 不会出现在模式中报价:
TRANSACTION;
ALTER TABLE people RENAME TO old_people;
CREATE TABLE people(people_id INTEGER PRIMARY KEY
, first_name TEXT NOT NULL,
, last_name TEXT NOT NULL);
INSERT INTO people(people_id, first_name, last_name)
SELECT rowid, first_name, last_name FROM old_people;
DROP TABLE old_people;
COMMIT;
VACUUM;
只要table的实际存储格式不变,可以用一个极度危险backdoor来改变table定义:
PRAGMA writable_schema = on;
UPDATE sqlite_master
SET sql = 'CREATE TABLE people(people_id INTEGER PRIMARY KEY, first_name text NOT NULL, last_name text NOT NULL )'
WHERE type = 'table'
AND name = 'people';
-- and now re-open the database file