如何提取一列数据并替换为外键?

时间:2015-10-01 03:35:18

标签: sql postgresql foreign-keys constraints database-normalization

如何将column (varchar, allows null)数据提取到新表中并用外键替换它?

我所知道的步骤:

  
      
  1. 使用递增的PK列和数据varchar创建一个新表   柱。
  2.   
  3. 使用insert-into-select将数据复制到新数据中   表。
  4.   
  5. 在原始表中更新/添加外键列???
  6.   

如何制作外键,第3步?

2 个答案:

答案 0 :(得分:2)

已存在的表t

create table t (s text);
insert into t (s) values ('a'), ('a'), ('b'), (null)

要引用的表:

create table s (
    s_id serial primary key,
    s text
)

将distinct和not null值复制到引用的表中:

insert into s (s)
select distinct s
from t
where s is not null

创建foregin key id列:

alter table t
add column s_id int

使用外键ID填充新列:

update t
set s_id = s.s_id
from s
where t.s = s.s

创建约束:

alter table t
add foreign key (s_id) references s (s_id)

删除现在不必要的列:

alter table t
drop column s

最终结果:

\d t
    Table "public.t"
 Column |  Type   | Modifiers 
--------+---------+-----------
 s_id   | integer | 
Foreign-key constraints:
    "t_s_id_fkey" FOREIGN KEY (s_id) REFERENCES s(s_id)

\d s
                        Table "public.s"
 Column |  Type   |                    Modifiers                     
--------+---------+--------------------------------------------------
 s_id   | integer | not null default nextval('s_s_id_seq'::regclass)
 s      | text    | 
Indexes:
    "s_pkey" PRIMARY KEY, btree (s_id)
Referenced by:
    TABLE "t" CONSTRAINT "t_s_id_fkey" FOREIGN KEY (s_id) REFERENCES s(s_id)

测试约束:

insert into t (s_id) values (3);
ERROR:  insert or update on table "t" violates foreign key constraint "t_s_id_fkey"
DETAIL:  Key (s_id)=(3) is not present in table "s".

示例查询:

select s_id, coalesce(s, 'null') as s
from t left join s using(s_id);
 s_id |  s   
------+------
      | null
    2 | a
    2 | a
    1 | b

答案 1 :(得分:0)

  

在步骤2中创建时将数据插入新表中确保   你没有添加重复项。您还可以添加不添加的约束   重复。

在你做3之前。

  

2a上。更改现有表格会添加一个新列,重新呈现   你的新外国桌的PK。

     

2B。通过加入现有表格和您的表格来填充新列    varchar 列上的新表,并使用ForeignTable ID进行更新。

     

2c中。删除现有表中的varchar列。

现在您已准备好在第3步添加外键。

ALTER TABLE ExistingTable
ADD CONSTRAINT yourFK
FOREIGN KEY (yourColumnNameID)
REFRENCES yourNewForeginTable(ColumnNameID)