如何使用以下表创建关系模式?

时间:2010-08-15 00:20:17

标签: sql-server oracle relational-database foreign-key-relationship

目前我有三张桌子。

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创建关系模式。

示例数据是

祖父母:

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         cd

GrandParent循环和G_COUNTER上的数据增加1.例如。对于TEL t2,G_COUNTER是1和2。 Parent上的数据也循环P_COUNTER相应地递增,Child表上的数据也循环。 GrandParent表和Parent表与TEL和G_COUNTER字段相关。父表和子表与TEL,G_COUNTER,P_COUNTER字段相关。

现在我想删除这些计数器并将其替换为主键和外键以关联GrandParent,Parent和Child表。现在我该怎么做?

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

您只需要一张桌子。

create table Family
(
member_id,
parent_id references member_id,
level, --not strictly necessary, but may save you time later
any_other_column

) 

甲骨文:

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

推荐阅读:

答案 1 :(得分:1)

因此,您有复合键和可能是隐式关系,您希望用适当的主键列和外键替换它们。

接近这个问题的方法有五个简单的部分:

  1. 将新列添加到表中。
  2. 填充主键列。
  3. 填充外键列。
  4. 添加约束。
  5. 放下顽固的柱子。
  6. 我将使用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:放下nugatory列

    我假设GRANDPARENT(TEL,G_COUNTER)代表某种商业密钥。因此,我建议您添加一个唯一约束来强制执行规则,而不是删除它们。对于PARENT(G_ID,P_COUNTER)和CHILD(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使用AUTO INCREMENT。这是一个单独的问题,已经被SO所涵盖。