数据库设计 - 系统默认项和自定义用户项

时间:2012-01-15 00:23:21

标签: database database-design

此问题适用于任何数据库表设计,您将拥有相同类型的系统默认项和自定义用户默认值(即用户可以添加自己的自定义项/设置)。

以下是发票和付款方式的示例,默认情况下,发票可以包含DueOnReceipt,NET10,NET15,NET30的付款条件(这是所有用户的默认值!)因此您将有两个表“INVOICE”和“PAYMENT_TERM” “

INVOICE
Id
...
PaymentTermId



PAYMENT_TERM (System default)
Id
Name

现在,允许用户存储自定义“PaymentTerms”的最佳方法是什么?为什么? (即用户可以使用系统默认付款条款或用户自己创建/添加的自定义付款条件)

选项1)将UserId添加到PaymentTerm,为已添加自定义项且系统默认用户标识设置为null的用户设置userid。

INVOICE
Id
...
PaymentTermId



PaymentTerm
Id
Name
UserId (System Default, UserId=null)

选项2)向发票“IsPaymentTermCustom”添加标志并创建自定义表“PAYMENT_TERM_CUSTOM”

INVOICE
Id
...
PaymentTermId
PaymentTermCustomId
IsPaymentTermCustom (True for custom, otherwise false for system default)

PaymentTerm
Id
Name

PAYMENT_TERM_CUSTOM
Id
Name
UserId

现在通过SQL查询检查用户是否使用自定义付款条件,如果IsPaymentTermCustom = True,则表示用户使用自定义付款条款,否则为假。

选项3)????

...

5 个答案:

答案 0 :(得分:7)

作为一般规则:

  • 首选添加列以添加表格
  • 首选添加行以添加列

一般来说,考虑因素是:

添加表格的影响

  • 需要对应用进行大量更改:您正在支持一种新的“事物”
  • 需要更复杂的SQL:你必须以某种方式加入它
  • 可能需要更改其他表以添加引用新表的外键列
  • 影响性能,因为需要更多I / O来加入和读取新表

请注意,我并不是说“永不添加表格”。只知道费用。

添加列的影响

  • 如果表格很大,添加列可能会很昂贵(ALTER TABLE ADD COLUMN可能需要几个小时才能完成,在此期间表格会被锁定,从而有效地将您的网站“关闭”),但这是一次性的事情
  • 项目成本低:易于编码/维护
  • 通常只需对应用程序进行微小的更改 - 这是一件事的新方面,而不是一件新事物
  • 性能差异可以忽略不计。不会显着恶化,但可能会更快,具体取决于具体情况(如果新列避免加入或昂贵的计算)。

添加行的效果

  • 零:如果您的数据模型只需添加更多行就可以处理您的新商业创意,那么这是最佳选择

(Pedants请不要发表评论,例如“没有'零'影响”,或“但仍会有更多的磁盘用于更多行”等 - 我在谈论材料对DB /项目/代码的影响)


要回答这个问题:选项1最好(即在付款选项表中添加一列) 推理基于上述指导原则,这种情况非常适合这些指南。

此外,
我还会在相同的表中存储“标准”付款选项,但使用NULL用户ID;这样,当您真正拥有一个时,您只需要添加新的付款选项,而不是每个客户,即使他们使用标准的

这也意味着您的发票表需要更改,这是一件好事 - 这意味着对您应用的这一部分影响最小。

答案 1 :(得分:2)

选项1肯定更好,原因如下: -

正确性

  • 您可以为付款条件名称的唯一性实施数据库约束
  • 您可以从Invoice到PaymentTerm
  • 实施外键约束

易于使用

  • 进行查询会更加简单,因为您始终会从Invoice加入PaymentTerm,而不需要更复杂的加入。大多数情况下,当您选择时,您不会关心它是内置付款还是自定义付款条款。优化器将使用普通连接更容易,而不是依赖于另一列来决定加入哪个表。
  • 更容易显示来自一个表的PaymentTerms列表

我们在数据模型中使用选项1非常多。

答案 2 :(得分:1)

在我看来,只有“付款条款”和“用户”。什么是“默认”付款条款的决定是业务规则,因此最好在您的应用程序的业务层中表示。

假设您希望从一开始就在您的应用程序中提供一组预定义的“默认”付款条款,这些条款就已存在于付款条款表中。但是,我会在USERS和PAYMENT TERMS之间加入一个参考表:

USERS:
    user-id
    user_namde

USER_PAYMENT_TERMS:
    userID
    payment_term_id

PAYMENT_TERMS:
    payment_term_id
    payment_term

您的业务层应通过GUI向用户(或更可能是管理员)提供以下功能:

  1. 为特定用户(部分用户)分配0到多个付款期限选项 用户可能不希望其中一个默认值可用 示例
  2. 添加自定义付款条款,然后可以转让给一个或多个用户(但这样可以避免不同用户创建重复付款条款)
  3. 允许将自定义付款条件的定义分配给多个用户(例如,用户公司是一个独特的付款流程,要求所有用户使用其中一个默认值以外的付款条件?创建自定义条款一次,并分配给所有用户。
  4. 您的应用程序业务层将建立管理访问付款条件的规则,然后您的用户界面可以访问这些规则。

    然后,您的用户界面(再次,可能通过管理员功能)允许设置除您描述的标准之外的一个或多个付款条件,然后通过类似检查列表的内容将其提供给一个或多个用户盒子(例如) Hacked together sample (I'm using VS 2010, but you get the idea . . .)

答案 3 :(得分:1)

正如我所看到的,部分问题在于,不同的付款条件也导致不同的计算。如果我还在焊接供应业务,我想添加“2%10 NET 30”,如果在10天内全额付款,则意味着2%的折扣,否则,净30。“

不考虑这个问题,我认为支付条款的所有权是有道理的。假设用户表(未示出)包括用户“system”,例如user_id 0。

create table payment_terms (
  payment_term_id integer primary key,
  payment_term_owner_id integer not null references users (user_id),
  payment_term_desc varchar(30) not null unique,
);

insert into payment_terms values (1, 0, 'Net 10');
insert into payment_terms values (2, 0, 'Net 15');
...
insert into payment_terms values (5, 1, '2% 10, Net 30');

这样可以简化外键,并且可以在运行时轻松选择付款条件,以便在用户界面中显示。

在这里要非常小心。您可能想要将描述,而不是ID号存储在您的发票中。 (它是唯一的;您可以设置它的外键引用。)如果只存储ID号,更新用户的自定义描述可能会巧妙地破坏引用它的所有数据。

例如,假设用户创建了自定义付款条款编号5,'2%10,净30'。您将ID号5存储在发票表中。然后,用户从今天开始决定事情会有所不同,并将该描述更新为“2%10,Net 20”。现在,在所有过去的发票上,算术不再与付款条件匹配。

你的审计员会杀了你。两次。

您希望阻止普通用户删除系统用户拥有的行。有几种方法可以做到这一点。

  • 使用BEFORE DELETE触发器。
  • 添加另一个表,其中包含对系统用户拥有的行的外键引用。
  • 通过存储过程限制所有访问,以防止删除系统行。

(旗帜几乎绝不是最好的主意。)

答案 4 :(得分:0)

将数据库设计的一般规则应用于手头的问题:

  • 系统付款条款的一个表格
  • 一个用户付款条款表
  • 上述两者的加入视图

现在,您可以根据付款条款加入发票。

优点:

  • 没有标志栏
  • No nulls
  • 您将系统默认值与用户数据分开
  • db
  • 的事情变得简单