【问题标题】:Change datatype of primary key of all tables in database更改数据库中所有表的主键数据类型
【发布时间】:2020-03-17 00:37:57
【问题描述】:

考虑拥有一个包含 50 多个表的数据库,并且具有中等数量的外键关系。 数据库中的每个表都有数字数据类型作为主键列。鉴于数据库保持不变并且所有外键关系也保持不变,有什么方法可以将所有主键列的数据类型从数字更改为 VARCHAR。

注意:- Postgresql 用作 RDBMS。

【问题讨论】:

  • 出于好奇:为什么要从 numeric 更改为 varchar?如果有的话,我会从 numeric 更改为 bigint。
  • 其实不是varchar,要使用UUID
  • 那你应该写那个;)
  • 是的,这是真的

标签: database postgresql foreign-keys primary-key sqldatatypes


【解决方案1】:

这将非常复杂,因为您需要为每个现有的 PK 值生成一个新的 UUID。我建议分几个步骤进行:

  1. 为每个表添加一个uuid 列(请不是 varchar!)作为非空值,并使用生成uuid 的默认值。
  2. 为每个“新 pk”列创建唯一索引
  3. 为那些引用其他表的表创建新的 uuid 类型的 FK 列(还没有 FK)。
  4. 对于引用刚刚创建的 UUID 的每个表,使用 UPDATE 语句将生成的 PK 值存储在新的 uuid 外键列中
  5. 删除旧的主键和外键约束
  6. 使用 using index 选项重新创建主键,指定在步骤 2 中创建的唯一索引
  7. 重新创建指向新 uuid 列的外键
  8. 删除旧的数字(pk 和 fk)列
  9. 将新列重命名为旧列的名称

类似于以下内容:

设置示例表并插入数据:

create table one (id integer primary key);
create table two (id integer primary key);
create table three (id integer primary key, one_id integer references one);
create table four (id integer primary key, two_id integer references two);
create table five (id integer primary key, three_id integer references three);

insert into one values (1),(2),(3);
insert into two values (10),(20),(30);
insert into three (id, one_id) values (100,1),(200,2),(300,3);
insert into four (id, two_id) values (1000, 10), (2000, 20), (3000, 30);
insert into five (id, three_id) values (10000, 100), (20000, 200), (30000, 300);

添加新的uuid 列并通过默认值填充新的PK 列。

alter table one 
  add column new_id uuid not null default uuid_generate_v4();
create unique index one_new_pkey on one (new_id);  

alter table two add column new_id uuid not null default uuid_generate_v4();
create unique index two_new_pkey on two (new_id);  

alter table three add column new_id uuid not null default uuid_generate_v4(), 
                  add column new_one_id uuid;
create unique index three_new_pkey on three (new_id);  

alter table four add column new_id uuid not null  default uuid_generate_v4(), 
                 add column new_two_id uuid;
create unique index four_new_pkey on four (new_id);  

alter table five add column new_id uuid not null default uuid_generate_v4(), 
                 add column new_three_id uuid;
create unique index five_new_pkey on five(new_id);

使用生成的 ID 更新新的外键列

update three 
  set new_one_id = one.new_id
from one 
where one.id = three.one_id;

update four 
  set new_two_id = two.new_id
from two
where two.id = four.two_id;

update five 
  set new_three_id = three.new_id
from three
where five.three_id = three.id;

替换旧的主键(删除任何外键)

alter table one drop constraint one_pkey cascade;
alter table one add primary key using index one_new_pkey;

alter table two drop constraint two_pkey cascade;
alter table two add primary key using index two_new_pkey;

alter table three drop constraint three_pkey cascade;
alter table three add primary key using index three_new_pkey;

alter table four drop constraint four_pkey cascade;
alter table four add primary key using index four_new_pkey;

alter table five drop constraint five_pkey cascade;
alter table five add primary key using index five_new_pkey;

创建新的外键

alter table three add constraint fk_three_one 
   foreign key (new_one_id)
   references one;

alter table four add constraint fk_four_two
   foreign key (new_two_id)
   references two;

alter table five add constraint fk_five_three
   foreign key (new_three_id)
   references three;

摆脱不再需要的旧列

alter table one drop column id; 
alter table one rename column new_id to id;

alter table two drop column id; 
alter table two rename column new_id to id;

alter table three drop column id, drop column one_id; 
alter table three rename column new_id to id;
alter table three rename column new_one_id to one_id;

alter table four drop column id, drop column two_id; 
alter table four rename column new_id to id;
alter table four rename column new_two_id to two_id;

alter table five drop column id, drop column three_id; 
alter table five rename column new_id to id;
alter table five rename column new_three_id to three_id;

如果您有一致的命名约定,则可以使用动态 SQL 自动执行此操作

【讨论】:

  • 感谢您的回答。实际上有 50 多张桌子。如果脚本可以通过循环或类似的方式来完成,而不仅仅是一种幼稚的方法,那就更容易了。
  • 好吧,使用这个想法并创建那个脚本。使用动态 SQL 或生成必要的语句,例如从编程语言中。这不是别人能为你做的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-17
  • 2017-04-05
相关资源
最近更新 更多