目前我有三张表。
GrandParent( tel int, G_Counter int, GField varchar(10));
Parent( tel int, G_Counter int, P_counter int, PField Varchar(5));
Child(tel int, G_counter int, P_counter int, C_Counter int, CField Varchar(3));这些桌子都是扁平的桌子。并且这些表自身循环,并且该循环由计数器确定。我需要删除这些计数器,并使用PK和FK创建一个关系模式。
样本数据是
GrandParent:
TEL    G_COUNTER  GField
 t1      1          ga
 t2      1          gb
 t2      2          gc
 t3      1          gd父级:
TEL     G_COUNTER   P_COUNTER  PFIELD
 t1        1           1         pa
 t1        1           2         pb
 t1        1           3         pc
 t2        1           1         pd
 t3        1           1         pe孩子:
TEL     G_COUNTER   P_COUNTER  C_COUNTER  CFIELD
 t1        1           1          1         ca
 t1        1           1          2         cb
 t1        1           1          3         cc
 t2        1           1          1         cd
 t2        1           1          2         ce
 t3        1           1          1         cdGrandParent循环上的数据和G_COUNTER递增1。对于TEL t2,G_COUNTER是1和2。父表上的数据也会循环。P_COUNTER会相应地递增,子表上的数据也会循环。GrandParent表和父表与TEL和G_COUNTER字段相关联。父表和子表与TEL、G_COUNTER、P_COUNTER字段相关联。
现在我想删除这些计数器,并将其替换为主键和外键,以关联GrandParent表、父表和子表。现在我该怎么做呢?
提前感谢您的帮助。
发布于 2010-08-15 16:17:44
因此,您有复合键和可能的隐式关系,您希望用适当的主键列和外键替换它们。
实现这一点的方法可以分为五个简单的部分:
将新列添加到主键和外键列中。constraints.
我将使用Oracle语法来解决这个问题,但同样的原则也适用于SQL Server。
SQL> select * from grandparent
  2  /
TE  G_COUNTER GF
-- ---------- --
t1          1 ga
t2          1 gb
t2          2 gc
t3          1 gd
SQL> select * from parent
  2  /
TE  G_COUNTER  P_COUNTER PF
-- ---------- ---------- --
t1          1          1 pa
t1          1          2 pb
t1          1          3 pc
t2          1          1 pd
t3          1          1 pe
SQL> select * from child
  2  /
TE  G_COUNTER  P_COUNTER  C_COUNTER CF
-- ---------- ---------- ---------- --
t1          1          1          1 ca
t1          1          1          2 cb
t1          1          1          3 cc
t2          1          1          1 cd
t2          1          1          2 ce
t3          1          1          1 cd
6 rows selected.
SQL>步骤1:添加新列
SQL> alter table grandparent
  2      add g_id number
  3  /
Table altered.
SQL> alter table parent
  2      add p_id number
  3      add g_id number
  4  /
Table altered.
SQL> alter table child
  2      add c_id number
  3      add p_id number
  4  /
Table altered.
SQL>步骤2:填充主键
SQL> update grandparent
  2      set g_id = rownum
  3  /
4 rows updated.
SQL> update parent
  2      set p_id = rownum
  3  /
5 rows updated.
SQL> update child
  2      set c_id = rownum
  3  /
6 rows updated.
SQL>步骤3:填充外键
SQL> update parent p
  2      set g_id = ( select g_id
  3                   from grandparent g
  4                   where g.tel = p.tel
  5                   and   g.g_counter = p.g_counter)
  6  /
5 rows updated.
SQL> update child c
  2      set p_id = ( select p_id
  3                   from parent p
  4                   where p.tel = c.tel
  5                   and   p.g_counter = c.g_counter
  6                   and   p.p_counter = c.p_counter)
  7  /
6 rows updated.
SQL>步骤4:添加约束
SQL> alter table grandparent
  2      modify g_id not null
  3      add constraint g_pk primary key (g_id) using index
  4  /
Table altered.
SQL> alter table parent
  2      modify p_id not null
  3      add constraint p_g_fk foreign key (g_id)
  4          references grandparent (g_id)
  5      add constraint p_pk primary key (p_id) using index
  6  /
Table altered.
SQL> alter table child
  2      modify c_id not null
  3      add constraint c_p_fk foreign key (p_id)
  4          references parent (p_id)
  5      add constraint c_pk primary key (c_id) using index
  6  /
Table altered.
SQL>步骤5:删除无用的列
我假设祖父母(电话、G_COUNTER)代表某种商业密钥。因此,我建议您添加一个唯一的约束来强制执行规则,而不是删除它们。对于父对象(G_ID,P_COUNTER)和子对象(G_ID,C_COUNTER)可能也是如此。你比我更了解你的数据。因此,以下语句表示您可能想要做的事情;请根据您的需要进行调整。
SQL> alter table grandparent
  2      add constraint g_uk unique (tel, g_counter) using index
  3  /
Table altered.
SQL> alter table parent
  2      add constraint p_uk unique (g_id, p_counter) using index
  3  /
Table altered.
SQL> alter table parent
  2      drop column tel
  3  /
Table altered.
SQL> alter table parent
  2      drop column g_counter
  3  /
Table altered.
SQL> alter table child
  2      drop column tel
  3  /
Table altered.
SQL> alter table child
  2      drop column g_counter
  3  /
Table altered.
SQL> alter table child
  2      drop column p_counter
  3  /
Table altered.
SQL> alter table child
  2      add constraint c_uk unique (p_id, c_counter) using index
  3  /
Table altered.
SQL>让我们检查一下表格:
SQL> select * from grandparent
  2  /
TE  G_COUNTER GF       G_ID
-- ---------- -- ----------
t1          1 ga          1
t2          1 gb          2
t2          2 gc          3
t3          1 gd          4
SQL> select * from parent
  2  /
 P_COUNTER PF       P_ID       G_ID
---------- -- ---------- ----------
         1 pa          1          1
         2 pb          2          1
         3 pc          3          1
         1 pd          4          2
         1 pe          5          4
SQL> select * from child
  2  /
 C_COUNTER CF       C_ID       P_ID
---------- -- ---------- ----------
         1 ca          1          1
         2 cb          2          1
         3 cc          3          1
         1 cd          4          4
         2 ce          5          4
         1 cd          6          5
6 rows selected.
SQL>在不同风格的DBMS中,维护主键需要不同的技术。Oracle使用序列,SQL Server使用自动增量。这是一个单独的问题,我们已经在SO中进行了讨论。
发布于 2010-08-15 08:28:43
您所需要的只是一张表。
create table Family
(
member_id,
parent_id references member_id,
level, --not strictly necessary, but may save you time later
any_other_column
) Oracle:
select 
    lpad(' ',2*(level-1)) || to_char(member_id) s
from 
    Family
start with parent_id is null
connect by prior member_id = parent_id ;SQL Server:
http://msdn.microsoft.com/en-us/library/ms186243.aspx
推荐阅读:
https://stackoverflow.com/questions/3485688
复制相似问题