你好朋友,我仍然在这里尝试在这个数据库中前进,现在我发现自己有一个新的担忧,因为事实证明我决定用一个帐户来扩展我的购买数据库,好吧,我没有寻找类似的东西在网上但我找不到任何东西可以帮助我解决这个问题,首先我解释一下我添加的表。在我的商店数据库中,客户可以有一个帐户,但至少有两种类型的客户我的国家,这些是(个人和法人)。嗯,自然人是任何人和机构或类似的东西都是法人实体。
考虑到简要介绍,我将解释一下情况。
我想以 College 的名义注册一个帐户,在本例中为 ( Legal ),但每个合法客户都有一名法定代表,这就是为什么我将Legal与natural_person表相关联,该表包含一个人的属性和从而避免必须添加法定代表人的姓名、姓氏等属性。到目前为止,至少对我来说似乎没问题,但现在最大的问题是以机构的名义开具发票!. 根据我的模型是不可能的,因为我只有与发票相关的客户,并且发票应该以机构的名义而不是法定代表人的名义出去,我对是否添加属性存在疑问(Name , Ruc_o_cedula) 这样在开票的时候通过法定代表人获取机构的数据并插入到发票表中,不知道这样对不对。
好吧,朋友们,这就是问题所在,我想补充一点,在我在论坛上提问之前,我去了我学习的学校的一位前 IT 老师,看看他是怎么想的,他建议不要分段很多客户实体将简单地加载所有类似这样的属性......
然后在那张表中,如果是自然客户,我正常注册,但如果是合法的,在name属性中,输入机构名称,在ruc_o_cedula中,输入 RUC 等。等离开姓氏等属性为空... ...这是他向我提出的解决方案,但我认为这是错误的,因为如果我将属性留空,我已经违反了规范化规则...希望您有耐心和可以帮助我。问候。
让我们澄清一下概念:
每张发票都以客户的名义开具。客户可以是自然人或法人。此外,每个法人都有一个相关的法律代表,他是自然人。
在对象设计中,最自然的事情似乎是创建一个包含两种类型的人的抽象:假设 PERSONA(抽象),自然人和法律人是其中的后代。
现在,(至少)有三种方法可以在关系数据库中实现继承,每种方法都有其缺点。
在这种情况下(在大多数情况下)最简单的事情似乎是“ 整个层次结构的单个表”策略,这相当于拥有一个
persona
包含两种特定类型的所有必要字段的单个表,加上一个区分列 (tipo_persona
) 告诉我它是法人还是自然人。它不是很优雅/高效/规范化(有些字段将是空白的,我必须允许 NULL),但优点是查询和修改简单。它与该论坛上向您提出的建议没有太大区别,但对我来说,表中未实施这种抽象似乎更可取
cliente
,因为法人和自然人的概念更广泛,其他“不是客户的人”(例如:供应商)。在表中cliente
,我只会引用persona
. 此外,该字段persona.representante_legal
(仅在tipo
对应于法人时使用)将引用同一表的另一条记录persona
(但这次它应该对应于自然人)。如果您觉得舒服,您可以定义一个视图(比如说:),该视图
cliente_con_nombre
具有提取用于打印发票的名称的逻辑。如果您有兴趣(并想学习),我将解释其他替代实现:
每个具体类一个表 我有两个表用于两种类型的人(如您的原始设计),在表中
cliente
我有两个引用cliente.id_persona_natural
和cliente.id_persona_juridica
(一个且只有一个将为 NULL)。缺点:它不是很规范化,查询有点复杂,如果我必须在另一个表中引用“人”(通用),我必须重复所有内容。每个具体类一个表,带有鉴别器(前一个的变体)。而不是两个引用,我只有一个
cliente.id_persona
加一个区分列cliente.tipo_persona
,告诉我它是合法的还是自然的。缺点:引用可以指向不同的表,不正统,妨碍我使用引用完整性;查询更加复杂每个类一个表,包括 abstract。我添加了一个
persona
除了 PK 之外只有公共字段的表(在这种情况下没有?);表persona_juridica
并persona_natural
添加一个引用persona
“父”的列。每条记录persona
都有一个且只有一个记录(合法的或自然的)指向它。该表cliente
仅对persona.id
. 缺点:虽然是最标准化的,但是查询和修改也是最复杂的。我补充说,当具体类的数量很大时,这些替代方案(尤其是最后一个)更具吸引力,或者将来可能会增加。这似乎不是这里的情况,这将是更喜欢“一张桌子”解决方案的原因。
我会告诉你,阻碍你的主要问题是表的设计
cliente
,尤其是它的主键idpersona
。这种设计使您无法定义客户可以是法人。实际上,在您的模型中可以看到 tablecliente
和 table之间没有线juridico
。那是不对的。您需要做的是为表分配一个不同的主键,该主键
cliente
仅用于标识表中的一条记录cliente
。然后分开,您在同一个表中定义 2 列,idpersona
并idjuridico
使用它们各自表的外键(persona_natural
和juridico
)。这个想法是,对于表中的每条记录,您为 2 个字段之一(或)cliente
分配一个值,以确定它是什么类型的客户。idpersona
idjuridico
例子:
如有必要,您可以定义一个触发器以确保您一次只能有一个
idpersona
值idjuridico
。通常,这是通过 a 完成的check constraint
,但它们不适用于 MySQL。由于对必须有条件地与其他表连接的表进行查询存在一些复杂性
cliente
,因此值得将这种复杂性隐藏在视图中。像这样的东西:另一点是 table
cuenta
应该有一个字段idcliente
而不是cliente_idpersona
(与 table 相同factura
)。此外,我认为表格cuenta
不应该有 fieldtipo_cliente
。如果有的话,也许你可以把它移到 tablecliente
,它可以作为一个鉴别器,但这不是绝对必要的,特别是如果你使用我上面提出的已经包含鉴别器的视图。这是一个测试脚本,用于演示如何将上述几点付诸实践: