2017-08-26 40 views
0

我不太确定这类数据是否有特殊术语,但概念类似于C++ std::variant(但可能在PostgreSQL中使用类似变体的结构并不理想)。在PostgreSQL中存储可能是几种可能性之一的数据的理想方式?

作为一个例子,假设我有一个表purchases具有一些列:

CREATE TABLE purchases (
    purchaseid bigserial, 
    buyerid bigint, 
    name text, 
    ... 
); 

每单会通过小数目的可能性,例如一个支付支票或比特币。每种可能性都有不同的关联字段,需要保存。

通过支票支付需要保存支票号码和银行名称,比特币支付需要保存发件人的比特币地址和返回比特币地址。

由于不同的字段,看起来明智的(用我对PostgreSQL的一点了解)将支票支付和比特币支付存放在不同的表中。

什么是存储这些数据(以及它们与每行中purchases),如果我知道,每单要么检查比特币支付的理想方式,但不能

+0

对于最灵活的存储,我会使用JSONB。 https://stackoverflow.com/questions/22654170/explanation-of-jsonb-introduced-by-postgresql –

+0

@David我不认为我需要“灵活的存储”。更重要的是(我认为)是一个或者构造的表示(和/或强制),但是JSONB并没有完全做到这一点。 – Bernard

回答

2

我为这种情况采取的方法确实如您所说:您需要一个不同的表格来查看详细信息,比特币详细信息等。这些表格必须包含购买ID,购买表格必须包含paymenttypeid。 然后,当希望查看与细节一起的购买,你需要做一个左连接。这里的诀窍是在视图中有一个case语句,以便根据paymenttypeid从当前左连接表中选择。在这样做时,您需要确保从细节表中选择相同数量的列,对类型进行适当调整。虽然这是基于左联接,我们知道在实践中,它会永远成功,因为case语句是基于paymenttypeid

SELECT p.purchasedate, 
     p.otherfields, 
     pt.description, 
     case p.paymenttype 
      WHEN 1 
       THEN bd.DetailField1 -- cast if necessary 
      WHEN 2 
       THEN cd.DetailField1 -- cast if necessary 
      END AS Detail1, 
     case p.paymenttype 
      WHEN 1 
       THEN bd.DetailField2 -- cast if necessary 
      WHEN 2 
       THEN cd.DetailField2 -- cast if necessary 
      END AS Detail2 
     FROM purchases p 
     inner join paymenttypes pt 
      on p.paymenttypeid = pt.id 
     left join bitcoindetails bd 
      on bd.purchaseid = p.id 
     left join chequedetails cd 
      on cd.purchaseid = p.id 

所以你喜欢的东西。这意味着我们总是从正确的细节表中进行选择。详情必须存在于所选记录的详细信息表中,因为它与paymenttypeid匹配。

+0

这似乎是唯一的方法,如果没有真正强制执行任何一种逻辑(即PostgreSQL禁止数据库在检查和比特币表中包含相同的'purchaseid')。对于查询,我认为不使用'CASE'会更好,但只需在单独的列中选择这些字段(对于其他类型的付款,这将是“NULL”)。与比特币相比,这将允许我保留原始类型的列,并允许不同数量的列进行检查。 (感觉银行ID奇怪,并返回比特币地址分享一列,你不觉得吗?) – Bernard

+0

@Bernard取决于你如何显示数据。我经常这样做。只要标题清楚表明数据是可变的。你的选择有缺点,你需要更多的专栏。最后“你付钱,并选择你的选择” –

+0

我想明确标题就足够了,如果有人直接读取数据库输出,你的方法会更好。但对我的使用而言,数据是由Web服务器请求的,该服务器将向用户输出精心设计的HTML,所以更多的列并不是真正的问题(除非有一些列的限制我不知道)。传输数据的大小不应该太大(只需要更多的NULL),并且Web服务器从另一列读取数据也很容易。感谢您的建议,使用不同的表和paymenttypeid - 我想我会去这个设计。 – Bernard

相关问题