使用auto_increment字段的模式和表设计不是键

时间:2011-09-27 13:28:54

标签: mysql database database-design database-schema

我有一个发票号,这个号码与特殊文件相关联。此文档有一个id,由渐进数字和当前年份组成,如此

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

每年累进的数字从1

重新开始
1-2012
2-2012
3-2012

首先,我想用invoice_n,prog_n,year创建一个表。 prog_n是AUTO_INCREMENT,每年我都会重置它。但是你不能使用不是键的AUTO_INCREMENT字段。无论如何,我要重置柜台,这不是那么值得推荐......

我无法更改id格式,我必须使用该规则。我能以某种方式获得有效的设计吗?

环境是经典的LAMP

非常感谢!

2 个答案:

答案 0 :(得分:3)

您的发票表中可以有一个单独的idauto_increment,以及使用以下公式填充prog_n的触发器:

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

这样,您的prog_n每年都会自动重置,您无需手动执行此操作。但是,如果您在表格中插入大量发票,可能会出现性能问题,但我认为这不会在实践中发生。

答案 1 :(得分:3)

扩展@Marius的答案,我会使用一个触发器让MySQL自动设置invoicenumber:

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 ;

请注意,您无法在before触发器中访问自动递增ID; 只有在after触发器中才能执行此操作,但在那里您无法更改任何值,因此需要一些小技巧。
更多的技巧用于确保我们在select查询中使用invoice_date,以便可以使用该字段的索引。

请参阅:
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