开发者

schema and table design with auto_increment field that is not a key

I've an invoice number, this number is associated to a spec开发者_如何学JAVAial document. This document has an id, formed by a progressive number and the current year, like this

222-2011
223-2011
224-2011
...

every year the progressive number restart from 1

1-2012
2-2012
3-2012

In the first place I thought to make a table with invoice_n, prog_n, year. prog_n is AUTO_INCREMENT and every year I'll reset it. But you cant use an AUTO_INCREMENT field that isn't a key. Anyway I'm going to reset the counter, and this is not so recommendable...

I can't change the id format, I have to use that rule. Can I have an efficient design in some way?

the environment is a classic LAMP

many thanks!


Expanding on @Marius answer, I'd use a trigger to have MySQL set the invoicenumber automatically like so:

DELIMITER $$

CREATE TRIGGER bi_invoices_each BEFORE INSERT ON invoices FOR EACH ROW
BEGIN
  DECLARE lastest_invoice_number VARCHAR(20);
  DECLARE numberpart INTEGER;

  -- find lastest invoicenumber in the current year.
  SELECT COALESCE(max(invoicenumber),0) INTO lastest_invoice_number 
  FROM invoice 
  WHERE invoice_date >= MAKEDATE(YEAR(NEW.invoice_date)  ,1) 
    AND invoice_date <  MAKEDATE(YEAR(NEW.invoice_date)+1,1);

  -- extract the part before the '-'
  SET numberpart = SUBSTRING_INDEX(lastest_invoice_number,'-',1)

  SET NEW.invoicenumber = CONCAT(numberpart+1,'-',YEAR(NEW.invoice_date));
END $$

DELIMITER ;

Note that you cannot access an auto-incrementing id in a before trigger;
Only in the after trigger can you do this, but there you cannot change any values, so a little trickery is required.
More trickery was used to make sure we use invoice_date as is in the select query so that an index on that field can be used.

See:
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_substring-index
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_makedate


You can have a separate id column with auto_increment in your invoices table, and a trigger which fills in prog_n with the following formula :

prog_n = id - select max(id) from invoices where year = current_year - 1

This way, your prog_n resets automatically each year and you don't need to do it manually. However, it might be a performance issue if you insert a lot of invoices in your table, but I don't think that will happen in practice.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜