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.
精彩评论