【问题标题】:SQLITE: how can I turn the rowid column into a regular columnSQLITE:如何将 rowid 列转换为常规列
【发布时间】:2018-10-14 17:16:32
【问题描述】:

假设我创建了一个表并通过以下方式插入一行:

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

如果我最初创建的表是:

CREATE TABLE people (people_id INTEGER PRIMARY KEY, first_name text NOT NULL, last_name text NOT NULL );

我会从一开始就拥有我正在寻找的那种桌子。

在 people_id 列中维护 rowid 值很重要。例如,假设 John Doe 在 people 中排在第 47 位。转换后,John Doe 的 people_id 需要为 47。

我想我可以简单地将数据从一个表复制到另一个表,但我想知道是否有更好或标准的方法来完成这种转换。

【问题讨论】:

    标签: sqlite primary-key alter-table


    【解决方案1】:

    Shawn 的回答是正确的(我已经赞成),但我将提供一个我认为稍微简洁的变体,因为新表不会以带引号的架构结束:

    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;
    

    【讨论】:

      【解决方案2】:

      您必须创建一个新表,复制所有内容,删除旧表,然后重命名新表:

      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;
      

      【讨论】:

      • 有没有办法保证来自 people 的 rowid 值会保留在副本中?假设 John Doe 在人中排在第 47 位。如何确保 John Doe 的 people_id 在复制后是 47?
      • @ericg 我应该想到这一点。查看其他答案。
      【解决方案3】:

      只要不改变表的实际存储格式,就可以用一个极度危险的backdoor来改变表定义:

      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
      

      【讨论】:

        猜你喜欢
        • 2011-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-27
        • 1970-01-01
        • 1970-01-01
        • 2010-12-03
        相关资源
        最近更新 更多