我可以使用什么数据库模式来保存不同类型的计费数据?

发布于 2024-07-09 00:05:36 字数 263 浏览 6 评论 0原文

我有一个创建订单的系统,该订单可以记入公司帐户、发送货到付款 (COD) 或记入信用卡。 我创建了下表:

订单
订单 ID
billingoption_id

计费选项
billingoption_id

我不确定应如何为计费数据构建下一个表。 我应该为每种类型的计费选项(即 COD、信用卡和 House 帐户)建立一个单独的表吗? 那么我在 Orders 表上是否会有另一个外键列来引用帐单数据的记录?

I have a system that creates an order and that order can be billed to a house account, sent Cash on Delivery (COD), or charged to a credit card. I've created the following tables:

ORDERS
order_id
billingoption_id

BILLINGOPTIONS
billingoption_id

I'm unsure of how the next table should be built for the billing data. Should I build a separate table for each type of billing option (ie. COD, Credit Cards, and House Account)? Then would I have another foreign key column on the Orders table that would refer to a record for the billing data?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

单调的奢华 2024-07-16 00:05:36

您可以通过任何一种方式完成此操作:一个大的 billingoptions 表,其中包含包含所有类型的字段,对于不适用于给定类型的字段使用 NULL,或者一堆婴儿表父 billingoptions 表的“星号关闭”。 两者都有各自的优点和缺点。

对于大表来说,

  • 可以在一个表中轻松引用所有数据是件好事。
  • 跟踪外键依赖性并执行更新或插入是有效的。
  • 但是您需要更改表结构以在将来添加新的计费选项,并且可能会存储无效的数据组合(例如,在同一记录中设置信用卡类型和 COD 标志)。

对于小型表,

  • 数据被分区并密切反映程序的对象结构是件好事。
  • 很高兴您可以添加新的付款选项或更改现有的付款选项,而不必担心影响其他选项。
  • 这些关系非常明确。 您不会意外地将一笔存款与另一笔存款链接起来,因为外键要求将其与批准链接起来。
  • 但是您最终会在设计中引入大量表,这需要大量 JOIN,导航起来可能会很痛苦,并且在插入和更新时效率不高。

在工作中,我们最终选择了小婴儿桌。 它看起来像这样:

Table Orders:
--> OrderId PK
--> (Lots of Other Fields)

Table Payments:
--> PaymentId PK
--> OrderId (FK) [There may be more than one payment per order]
--> PaymentType [Restricted field contains values like 
       'PAYPAL' or 'CREDIT', you use this to know which 
       baby table to look up that can contain additional 
       information]

Table PaymentsPayPal:
--> PaymentPayPalId PK
--> PaymentId FK points to Table Payments
--> TransactionNo
--> (Other PayPal specific fields)

Table PaymentsCheck:
--> PaymentCheckId PK
--> PaymentId FK points to Table Payments
--> RoutingNo
--> (Other e-check specific fields)

+ other tables for remaining payment types....

所有付款类型共享三个与交易相关的表:

Table PaymentApprovals:
--> PaymentApprovalId PK
--> PaymentId FK points to Table Payments
--> Status [Some flag meaning 'Succeeded', 'Failed', 'Reversed', etc]
--> ProcessorMessage [Something the service sent back, like '(M) CVV2 Matched']
--> Amount
--> (Other administrative fields)

Table PaymentDeposits:
--> PaymentDepositId PK
--> PaymentApprovalId FK points to Table PaymentApprovals
--> Status
--> ProcessorMessage
--> Amount
--> (Other administrative fields)

Table PaymentRefunds:
--> PaymentRefundId PK
--> PaymentDepositId FK points to Table PaymentDeposits
--> Status
--> ProcessorMessage
--> Amount
--> (Other administrative fields)

我们所有的付款方式(信用卡、PayPal、Google Checkout、支票、现金、商店信用和汇票)都被抽象以适应此批准 - -> 存款--> 退款比喻,UI 在具有不同实现的 IPaymentIPaymentProcessor 接口上调用相同的方法(Cyber​​sourcePaymentProcessorPayPalPaymentProcessor > 等)。 在过去的一年半中,抽象在这些不同的方法中运行得很好,尽管有时 GUI 会向用户显示不同的措辞(例如,它会说“授权”和“收费”而不是“批准”和信用卡付款的“存款”,以及输入现金的屏幕一口气执行批准/存款步骤。)

希望这是有道理的。 听起来您实际上并未存储付款信息,但考虑这些信息最终会去哪里是很有用的。

You can do it either way: a big honking billingoptions table that has fields that encompasses all of the types, with NULLs for fields that don't apply to a given type, or a bunch of baby tables that "star off" of a parent billingoptions table. Both have their advantages and disadvantages.

For the big honking table,

  • It's nice that all data can easily be referenced in a single table.
  • Tracking foreign key dependencies and performing updates or inserts is efficent.
  • BUT you need to alter the table structure to add new billing options in the future, and there's the possibility of invalid combinations of data being stored (for example, both a credit card type and a COD flag being set in the same record).

For the small baby tables,

  • It's nice that the data is partitioned and reflects your program's object structure closely.
  • It's nice that you can add new payment options or alter existing ones without worrying about affecting the others.
  • The relationships are VERY explicit. You can't accidentally link a deposit with another deposit, since the foreign key will require that it be linked with an approval.
  • BUT you end up introducing a lot of tables into the design, which require lots of JOINs, can be a pain to navigate, and aren't as efficient when it comes to inserts and updates.

At work, we ended up going with small baby tables. It looks something like this:

Table Orders:
--> OrderId PK
--> (Lots of Other Fields)

Table Payments:
--> PaymentId PK
--> OrderId (FK) [There may be more than one payment per order]
--> PaymentType [Restricted field contains values like 
       'PAYPAL' or 'CREDIT', you use this to know which 
       baby table to look up that can contain additional 
       information]

Table PaymentsPayPal:
--> PaymentPayPalId PK
--> PaymentId FK points to Table Payments
--> TransactionNo
--> (Other PayPal specific fields)

Table PaymentsCheck:
--> PaymentCheckId PK
--> PaymentId FK points to Table Payments
--> RoutingNo
--> (Other e-check specific fields)

+ other tables for remaining payment types....

All of the payment types share three transaction related tables:

Table PaymentApprovals:
--> PaymentApprovalId PK
--> PaymentId FK points to Table Payments
--> Status [Some flag meaning 'Succeeded', 'Failed', 'Reversed', etc]
--> ProcessorMessage [Something the service sent back, like '(M) CVV2 Matched']
--> Amount
--> (Other administrative fields)

Table PaymentDeposits:
--> PaymentDepositId PK
--> PaymentApprovalId FK points to Table PaymentApprovals
--> Status
--> ProcessorMessage
--> Amount
--> (Other administrative fields)

Table PaymentRefunds:
--> PaymentRefundId PK
--> PaymentDepositId FK points to Table PaymentDeposits
--> Status
--> ProcessorMessage
--> Amount
--> (Other administrative fields)

All of our payment methods (Credit Card, PayPal, Google Checkout, Check, Cash, Store Credit, and Money Order) are abstracted to fit into this Approval --> Deposit --> Refund metaphor, and the UI calls the same methods on an IPayment and IPaymentProcessor interfaces with different implementations (CybersourcePaymentProcessor, PayPalPaymentProcessor, etc). The abstraction has worked pretty well over the past year and a half across these disparate methods, although sometimes the GUI will display different verbiage to the user (for example, it'll say "Authorize" and "Charge" instead of "Approve" and "Deposit" for credit card payments, and the screen for entering cash performs the Approve/Deposit step in one fell swoop.)

Hope that makes sense. It sounds like you're not actually storing payment information, but it's useful to think about where these things can end up.

冷情 2024-07-16 00:05:36

专注于事物。 实际的事情。 首先尝试用自然语言简单、直接地描述事物。

然后,当您寻求设计指导时,您可以提供定义。 在某些情况下,编写定义的行为将使设计具体化。

订单就是事物。 订单有哪些属性? 客户、产品、付款/计费选项。

结算选项(几乎)是事物。 显然,您可以定义和识别它们。 (我不确定我可以。从你的问题来看,你似乎可以。但是如果没有一句话总结,我不确定 Billion Options 是怎么回事。

什么是“账单数据?”什么?这是什么东西?它有什么属性(或属性)?

“账单数据”与订单有何关系?

请随意更新每个事物的定义。

Focus on things. Actual things. Try to describe things simply, directly, and in natural language first.

Then, when you ask for design guidance, you can provide definitions. In some cases, the act of writing definitions will make the design crystalize.

Orders are things. What are the attributes of an order? Customer, Product, Payment/Billing options.

Billing Options are (almost) things. You can, apparently, define and identify them. (I'm not sure I could. From your question, it appears that you might be able to. But without a one-sentence summary, I'm not sure what's going on with Billion Options.

What's a "billing data?" What kind of thing is this? What attributes (or properties) does it have?

How does a "Billing Data" relate to an Order? How does it relate to a Billing Option?

Feel free to update the question with definitions for each thing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文