【问题标题】:If two Table's data are independant, but they have relationship (one Main, another Sub). What is the best way to link them?如果两个表数据是独立的,但它们有关系(一个主,另一个子)。链接它们的最佳方式是什么?
【发布时间】:2021-10-19 12:19:45
【问题描述】:

目前我正在设计一个客户管理系统,其中包括客户的公司信息及其联系人。

我的设计在下面的照片中。

https://i.stack.imgur.com/FecUU.png

在这张照片中,您可以看到 客户 ID、公司名称、地址行、公司电话、传真、支付条款和一组联系人、电话、电子邮件LabelTextBox .

在我过去的设计中,我创建了一个表来存储所有数据,并将组命名为多个列contact_1, tel_1, email_1, contact_2, ... email_8。这种设计让我可以轻松查询数据,但在数据绑定方面不好。所以我觉得我应该为此做一个新的设计。

我的新设计是将联系人、电话、电子邮件组分开到另一个表中。这样该列表将保留客户 ID、公司名称、地址行、公司电话、传真和支付条款。此页面设计中显示了列表(没有 AddressLine1 ... AddressLine4)。

https://i.stack.imgur.com/7OINI.png

左栏是我用于编辑操作的id 栏(在编辑窗口中使用SELECT columns FROM customer_list WHERE id='id'id(this.CustomerDataGrid.SelectedItem as DataRowView)["id"] 获得)。我已将Visibility.Collapsed 设置为隐藏C# 代码中的id 列以便更好地查看。

但是,由于我不应该在 Table 中创建 Table,Contact、Tel、Email(客户联系人列表)的数据将在另一个 Table 中为 INSERTcontact, tel, email 列。然后我必须想办法将客户联系人列表的表格链接到客户列表。

由于现阶段没有创建数据,我想如果我能找到客户列表数据的id列序列的last_value,那么我可以创建一个与客户列表数据相关的客户联系人列表。

我找到的解决方案是使用SELECT last_value FROM customer_list_id_seq 获取last_value。查询后,我创建一个变量current_value = last_value + 1 来获取下一个序列值。有了这个值,我可以创建一个表customer_contact_list_@current_value,它与未创建的客户列表的数据“相关”。

我知道我可以先保存非客户联系人列表数据,然后通过SELECT id FROM customer_list ORDER BY id DESC LIMIT 1获取customer_listlastid值。我担心的是:如果我必须添加更多联系人,我仍然可以进行新设计,将 Contact、Tel、Email 的 Group 转换为 DataGrid in WPF。 p>

由于我是编程新手,我的思维方式和设计知识还处于初级阶段。
在这个设计中,数据被分隔在两个 Table 中,这意味着它们没有关系

我必须使客户联系人列表的表名称与 customer_list.id 相关,以使他们喜欢建立关系。此外,在这个设计中,我必须为每个客户列表的数据(行)创建一个新的客户联系人列表表。

我想知道这种设计是否有更好的方法。

我的另一个设计是在 customer_list 表中添加三列。但是我的查询会很复杂,因为我必须重复“客户 ID、公司名称、地址行、公司电话、传真、支付条款”并尝试过滤它们。即使我将其他 7 的行重复值设置为 null,表格也会看起来很难阅读。

【问题讨论】:

  • 看来我需要的是了解数据库规范化。我不应该为 customer_list 中的每一行创建一个新表。我应该创建一个customer_contact_list,其中的列是外键和对customer_list(customer_id)的REFERENCES

标签: c# postgresql


【解决方案1】:

好吧,您正在使用创建外键的最后一条评论。所以我们在客户和联系人之间建立了关系。然而,悬而未决的问题变成了 Customer:Contact 关系的类型是什么?

  • 一对一 (1:1) -> 每个客户都有一个联系人,一个联系人是一个客户。
  • 一对多 (1:M) -> 每个客户有多个联系人,一个联系人是一个客户。
  • 多对多 (M:M) -> 每个客户都有多个联系人,每个联系人都针对多个客户。

根据您的描述,以 1:1 的比例丢弃。对于 1:M,您将客户 PK 包括在联系表中。对于 M:M,您实际上创建了另一个表,其中包含来自 Customer 和 Contact 的 PK。
至于生成 ids 甚至不要尝试获取 最后一个 并增加它(通常称为 MAX+1)。在多用户环境中,这是您将获得副本的虚拟保证。只需为每个表创建一个sequencegenerated identity,Postgres 就会处理它。

用于 1:M、Postgres v10 及更高版本的表

create table customers( cust_id    integer generated always as identity  
                      , address    text
                      , tel        text
                      , fax        text
                      , pay_terms  text
                      , constraint cust_pk primary key (cust_id)
                      ) 
                      
 create table contacts( cont_id    integer generated always as identity 
                      , cust_id    interger 
                      , tel        text
                      , email      text
                      , constraint cont_pk primary key (cont_id)
                      , constraint cont_2_cust_fk 
                                   foreign key (cust_id)
                                   references customers(cust_id) 
                      );

M:M、Postgres v10 及更高版本的表定义

create table customers( cust_id    integer generated always as identity  
                      , address    text
                      , tel        text
                      , fax        text
                      , pay_terms  text
                      , constraint cust_pk primary key (cust_id)
                      ) 
                      
create table contacts( cont_id    integer generated always as identity 
                     , cust_id    interger 
                     , tel        text
                     , email      text
                     , constraint cont_pk primary key (cont_id)
                     );
                      
create table customer_contacts( cust_id integer
                              , cont_id integer
                              , constraint cust_cont_pk 
                                           primary key (cust_id, cont_id)
                              , constraint cust_cont_2_cust_fk 
                                           foreign key (cust_id)
                                           references customers(cust_id)  
                              , constraint cust_cont_2_cont_fk 
                                           foreign key (cont_id)
                                           references contacts(cont_id)
                              );

对于 v10 之前的 Postgres 版本,将 integer generated always as identity 替换为 serial

【讨论】:

  • 感谢您的回复。我想知道使用 nextval(seq) 创建序列 seq 是否更好或只使用 SERIAL。
  • 它们完全一样。 SERIAL 实际上并不是看起来的数据类型。这是一个快捷方式:它创建一个序列和一个整数数据类型,并使 nextval(seq) 成为默认值。如果您事后查看它,则无法判断它是串行定义还是独立定义。 BIGSERIAL 也是如此,只是它创建了一个 bigint 数据类型。
猜你喜欢
  • 2021-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
相关资源
最近更新 更多