在PostgreSQL 9.1.3中需要更清洁的更新方法

时间:2014-08-11 03:13:18

标签: postgresql postgresql-9.1 triggers

使用PostgreSQL 9.1.3我有一个像这样的points表(这里显示表的正确方法是什么?)

| Column |     Type          |            Table Modifiers                          | Storage
|--------|-------------------|-----------------------------------------------------|----------|
| id     | integer           | not null default nextval('points_id_seq'::regclass) | plain    |
| name   | character varying | not null                                            | extended |
| abbrev | character varying | not null                                            | extended |
| amount | real              | not null                                            | plain    |

在另一个表中,orders我有一堆列,其中列的名称通过缩写列存在于points表中,以及total_points

| Column       | Type   | Table Modifiers    |
|--------------|--------|--------------------|
| ud           | real   | not null default 0 |
| sw           | real   | not null default 0 |
| prrv         | real   | not null default 0 |
| total_points | real   | default 0          |

所以在orders我有sw列,在points我现在有一个amount,它会在abbrev =的列中显示SW

我在points表中有大约15列,现在我想设置一个触发器,这样当我在points表中创建/更新一个条目时,我会计算总分。基本上只有这三个显示我可以像这样长手:

UPDATE points
SET total_points =
    ud * (SELECT amount FROM points WHERE abbrev = 'ud') +
    sw * (SELECT amount FROM points WHERE abbrev = 'sw') +
    prrv * (SELECT amount FROM points WHERE abbrev = 'prrv')  
WHERE .... 

但这只是简单的丑陋和重复,就像我说的那样,其中有15个(现在......)。我希望有更复杂的方法来解决这个问题。

一般来说,orders表中的每个愚蠢名称都代表了与订单相关的一种工作,而且每种类型都有一个“成本”,它存储在{{1}中}表。如果有更清洁的设置,我不会嫁给这个结构。

1 个答案:

答案 0 :(得分:0)

"序列化"订单成本:

CREATE TABLE order_cost (
   order_cost_id serial PRIMARY KEY
 , order_id      int NOT NULL REFERENCES order
 , cost_type_id  int NOT NULL REFERENCES points
 , cost          int NOT NULL DEFAULT 0  -- in Cent
);

对于单行:

UPDATE orders o
SET    total_points = COALESCE((
   SELECT sum(oc.cost * p.amount) AS order_cost
   FROM   order_cost oc
   JOIN   points p ON oc.cost_type_id = p.id
   WHERE  oc.order_id = o.order_id
   ), 0);
WHERE  o.order_id =  $<order_id>   -- your order_id here ...

从不将有损类型real用于货币数据。使用完全类型,例如moneynumericinteger - 其中整数应该以Cent为单位存储金额。

这个密切相关的例子提供了更多建议: