添加主键更改列类型

Posted

技术标签:

【中文标题】添加主键更改列类型【英文标题】:Adding primary key changes column type 【发布时间】:2012-02-28 23:59:46 【问题描述】:

我们的数据库目前没有在任何表上定义主键。所有id 列都是唯一索引。我正在删除这些索引并用适当的主键替换它们。

我的问题:在 Postgres 8.4.7 中,当我将主键添加到表时,一个表的数据类型从 bigint 更改为 integer

我有以下表格定义:

psql=# \d events
                                         Table "public.events"
        Column         |           Type           |                      Modifiers                      
-----------------------+--------------------------+-----------------------------------------------------
 id                    | bigint                   | not null default nextval('events_id_seq'::regclass)
 [more columns omitted]

Indexes:
    "events_id_unique_pk" UNIQUE, btree (id)
Foreign-key constraints:
    "events_clearing_event_ref_fk" FOREIGN KEY (clearing_event_id) REFERENCES events(id)
    "events_event_configs_id_fk" FOREIGN KEY (event_config_id) REFERENCES event_configs(id)
    "events_pdu_circuitbreaker_id_fk" FOREIGN KEY (pdu_circuitbreaker_id) REFERENCES pdu_circuitbreaker(id)
    "events_pdu_id_fk" FOREIGN KEY (pdu_id) REFERENCES pdus(id) ON DELETE CASCADE
    "events_pdu_outlet_id_fk" FOREIGN KEY (pdu_outlet_id) REFERENCES pdu_outlet(id)
    "events_sensor_id_fk" FOREIGN KEY (sensor_id) REFERENCES sensors(id)
    "events_user_id_fk" FOREIGN KEY (clearing_user_id) REFERENCES users(id)
Referenced by:
    TABLE "events" CONSTRAINT "events_clearing_event_ref_fk" FOREIGN KEY (clearing_event_id) REFERENCES events(id)
    TABLE "event_params" CONSTRAINT "events_params_event_id_fk" FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE
Triggers:
    event_validate BEFORE INSERT OR UPDATE ON events FOR EACH ROW EXECUTE PROCEDURE event_validate()

会发生这样的事情:

psql=# ALTER TABLE events ADD PRIMARY KEY (id);
NOTICE:  ALTER TABLE / ADD PRIMARY KEY will create implicit index "events_pkey" for table "events"
ALTER TABLE
psql=# \d events
                                         Table "public.events"
        Column         |           Type           |                      Modifiers                      
-----------------------+--------------------------+-----------------------------------------------------
 id                    | integer                  | not null default nextval('events_id_seq'::regclass)
 [more columns omitted]

Indexes:
    "events_pkey" PRIMARY KEY, btree (id)
    "events_id_unique_pk" UNIQUE, btree (id)
Foreign-key constraints:
    "events_clearing_event_ref_fk" FOREIGN KEY (clearing_event_id) REFERENCES events(id)
    "events_event_configs_id_fk" FOREIGN KEY (event_config_id) REFERENCES event_configs(id)
    "events_pdu_circuitbreaker_id_fk" FOREIGN KEY (pdu_circuitbreaker_id) REFERENCES pdu_circuitbreaker(id)
    "events_pdu_id_fk" FOREIGN KEY (pdu_id) REFERENCES pdus(id) ON DELETE CASCADE
    "events_pdu_outlet_id_fk" FOREIGN KEY (pdu_outlet_id) REFERENCES pdu_outlet(id)
    "events_sensor_id_fk" FOREIGN KEY (sensor_id) REFERENCES sensors(id)
    "events_user_id_fk" FOREIGN KEY (clearing_user_id) REFERENCES users(id)
Referenced by:
    TABLE "events" CONSTRAINT "events_clearing_event_ref_fk" FOREIGN KEY (clearing_event_id) REFERENCES events(id)
    TABLE "event_params" CONSTRAINT "events_params_event_id_fk" FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE
Triggers:
    event_validate BEFORE INSERT OR UPDATE ON events FOR EACH ROW EXECUTE PROCEDURE event_validate()

我考虑了一些解决方法,但我真的很想知道为什么会这样。还有一些其他表也使用bigint,所以我不想仅仅破解一个解决方案。

这是使用 Liquibase 编写的,但它也直接在 Postgres 控制台中进行。


更新

另外两点:

我可以使用bigint id 和id 上的唯一索引创建一个简单的表,添加主键,列类型保持不变。 在执行时所有表都是空的。

这可能与约束有关吗?

【问题讨论】:

我很难相信添加主键约束会改变列的类型,但让我们暂时假设这是一个错误。更新到最新的次要版本并再次测试。 @MilenA.Radev 这是控制台的文字输出,这三个命令是按顺序输入的。无论如何,我们正在从 Postgres 8.4 升级到 9.1。我可以在几天内对此进行测试。 【参考方案1】:

这很有趣。我无法用 9.1.0 版重现它(是的,我也应该升级!)。但是我并不清楚原始表和序列是如何创建的。

此页面似乎暗示了 SERIAL 和 INTEGER 之间的类型自动更改:http://grover.open2space.com/content/migrate-data-postgresql-and-maintain-existing-primary-key

可能类似于使用 SERIAL 而不是 BIGSERIAL 创建表,然后将类型强制为 BIGINT?序列和主键操作之间的某些东西可能会重置它。

【讨论】:

【参考方案2】:

我无法在第二天重现它,即使在它第一次发生时与目击者多次重现它之后也是如此。我把它归结为小精灵。

【讨论】:

以上是关于添加主键更改列类型的主要内容,如果未能解决你的问题,请参考以下文章

SQL中改变列的数据类型

Mysql增加主键或者更改表的列为主键的sql语句

在 impala 中更改表:使列成为主键

SQL:向数据库表添加新的主键列

我们可以将现有列作为主键吗?

MySQL修改表结构