简体   繁体   中英

updating db structure - new table or adding a field

This might sound like a silly question but here it is; I am sure it has happened to anyone around here, you build a web app with a db structure per specifications (php/mysql), but then the specs change slightly and you need to make the change in the db to reflect it, here is a short example:

Order table
->order id
->user id
->closed
->timestamp

but because the orders are paid in different currency than in the one, which is quoted in the db, I need to add the field exchange rate , which is only checked and known when closing the order, not upon insertion of the record. Thus I can either add the new field to the current table, and leave it null/blank when inserting, and then update when necessary; or I can create a new table with the following structure:

Order exchange rates
->exchange id
->order id
->exchange rate

Although I believe that the letter is better because it is a less intrusive change, and won't affect the rest of the application functionality, you could end up with insane amount of joined queries to get all the information necessary. On the other hand the former approach could mess up some other queries you have in the db, but it is definitely more practical and also logical in terms of the overall db structure. Also I don't think that it is a good practice to use the structure of insert null and update later, but that might be just my lonely opinion... Thus I would like to ask what do you think is the preferable approach.

I'm thinking of another alternative. Setup an exchange rate table like:

create table exchange_rate(
   cur_code_from varchar2(3)  not null
  ,cur_code_to   varchar2(3)  not null
  ,valid_from    date         not null
  ,valid_to      date         not null
  ,rate          number(20,6) not null
);

alter table exchange_rate 
  add constraint exchange_rate_pk 
      primary key(cur_code_from, cur_code_to, valid_from);

The table should hold data that looks something like:

cur_code_from   cur_code_to valid_from  valid_to   rate
=============  =========== ==========  ========    ====
    EUR           EUR      2014-01-01   9999-12-31  1
    EUR           USD      2014-01-01   9999-12-31  1,311702
    EUR           SEK      2014-01-01   2014-03-30  8,808322
    EUR           SEK      2014-04-01   9999-12-31  8,658084
    EUR           GBP      2014-01-01   9999-12-31  0,842865
    EUR           PLN      2014-01-01   9999-12-31  4,211555

Note the special case when you convert from and to the same currency. From a normalization perspective, you don't need valid_to since it can be computed from the next valid_from , but from a practical point of view, it's easier to work with a valid-to-date than using a sub-query every time.

Then, to convert into the customers currency you would join with this table:

select o.order_value * x.rate as value_in_customer_currency
  from orders o
  join exchange_rate_t x on(
       x.cur_code_from = 'EUR' -- Your- default currency here
   and x.cur_code_to   = 'SEK' -- The customers currency here
   and o.order_close_date between x.valid_from and x.valid_to
  )
 where o.order_id = 1234;

Here I have used the rates valid as of the order_close_date . So if you have two orders, one with a close date of 2014-02-01, then it would pick up a different rate than an order with a close date of 2014-04-05.

I think you just need to add exchange_rate_id in the order table and create a look up table Exchange_Rates with columns ex_rate_id , description , deleted , created_date .

So when an order closes you just need to update the exchange_rate_id column in order table with id and later on you can create a join with the look up table to pull records.

Keep in mind that

  1. one order have only one currency upon closing.
  2. one currency can be updated against one or many orders

It is a one to many relationship, so i don't think that you have to make a separate table for that. If you do so I think that will consider in extra normalization.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM