存储数据的理想方式可能是 PostgreSQL 中的几种可能性之一?
Ideal way to store data that can be one of a few possibilities in PostgreSQL?
我不太确定这种数据是否有专门的术语,但这个概念类似于 C++ std::variant
(但也许在 PostgreSQL 中使用类变体结构)。
例如,假设我有一个 table purchases
,它有一些列:
CREATE TABLE purchases (
purchaseid bigserial,
buyerid bigint,
name text,
...
);
每次购买都将通过少数几种可能性之一进行支付,例如支票或比特币。每种可能性都有需要保存的不同关联字段。
支票付款需要保存支票号码和银行名称,比特币付款需要保存发件人的比特币地址和 return 比特币地址。
由于字段不同,将支票支付和比特币支付放在不同的 table 中似乎是明智的(我对 PostgreSQL 知之甚少)。
如果我知道每次购买只能由[支付],那么存储此类数据(并将它们与 purchases
中的每一行相关联)的理想方式是什么? =26=]或者检查或比特币,但不检查两者?
我在这种情况下采取的方法确实如您所建议的那样:您需要一个不同的 table 来获取支票详细信息、比特币详细信息等。这些 tables 必须包括购买 ID 和购买table 必须有付款类型 ID。
然后当希望查看购买和详细信息时,您需要进行左连接。这里的技巧是在视图中有一个 case 语句,这样根据 paymenttypeid,您 select 从当前左侧加入 table。在执行此操作时,您需要确保 select 来自详细信息 table 的列数相同,并对类型进行适当调整。
所以你得到类似的东西:
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
虽然这是基于左连接,但我们知道在实践中它总是会成功,因为 case 语句是基于 paymenttypeid 的。这意味着我们总是 select 从正确的细节 table 开始。详细信息必须出现在记录 selected 的详细信息 table 中,因为它与付款类型 ID 匹配。
我不太确定这种数据是否有专门的术语,但这个概念类似于 C++ std::variant
(但也许在 PostgreSQL 中使用类变体结构)。
例如,假设我有一个 table purchases
,它有一些列:
CREATE TABLE purchases (
purchaseid bigserial,
buyerid bigint,
name text,
...
);
每次购买都将通过少数几种可能性之一进行支付,例如支票或比特币。每种可能性都有需要保存的不同关联字段。
支票付款需要保存支票号码和银行名称,比特币付款需要保存发件人的比特币地址和 return 比特币地址。
由于字段不同,将支票支付和比特币支付放在不同的 table 中似乎是明智的(我对 PostgreSQL 知之甚少)。
如果我知道每次购买只能由[支付],那么存储此类数据(并将它们与 purchases
中的每一行相关联)的理想方式是什么? =26=]或者检查或比特币,但不检查两者?
我在这种情况下采取的方法确实如您所建议的那样:您需要一个不同的 table 来获取支票详细信息、比特币详细信息等。这些 tables 必须包括购买 ID 和购买table 必须有付款类型 ID。 然后当希望查看购买和详细信息时,您需要进行左连接。这里的技巧是在视图中有一个 case 语句,这样根据 paymenttypeid,您 select 从当前左侧加入 table。在执行此操作时,您需要确保 select 来自详细信息 table 的列数相同,并对类型进行适当调整。
所以你得到类似的东西:
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
虽然这是基于左连接,但我们知道在实践中它总是会成功,因为 case 语句是基于 paymenttypeid 的。这意味着我们总是 select 从正确的细节 table 开始。详细信息必须出现在记录 selected 的详细信息 table 中,因为它与付款类型 ID 匹配。