【问题标题】:How to create a relational Schema with following tables?如何使用下表创建关系模式?
【发布时间】:2010-08-15 00:20:17
【问题描述】:

目前我有三张桌子。

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 字段相关。并且Parent table和Child table都与TEL,G_COUNTER,P_COUNTER字段相关。

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

提前感谢您的帮助。

【问题讨论】:

  • 您是否需要将架构保留为三个表 - GP / P / C - 或者您是否会考虑迁移到具有自引用的单个表的架构?
  • 我需要三个表。只需要在插入记录时创建关系模式的存储过程。谢谢

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


【解决方案1】:

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

解决这个问题的方法有五个简单的部分:

  1. 将新列添加到表中。
  2. 填充主键列。
  3. 填充外键列。
  4. 添加约束。
  5. 删除枚举列。

我将使用 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 步:删除否定列

我假设 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 中讨论过了。

【讨论】:

    【解决方案2】:

    您只需要一张桌子。

    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 服务器:

    http://msdn.microsoft.com/en-us/library/ms186243.aspx

    推荐阅读:

    【讨论】:

    • 这行不通,因为我不能在一张桌子上做。我需要至少有相同数量的桌子。我需要在插入记录时创建关系的存储过程。
    • SQL Server 2008 也有一个HierarchyId 类型。
    猜你喜欢
    • 2021-11-10
    • 1970-01-01
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 2022-10-04
    • 2020-04-08
    • 2018-05-27
    相关资源
    最近更新 更多