2015-12-23 4 views
1

Немного предыстории для выпуска:DB Комплексные Возрастающие Счетчики

В Венесуэле существует закон, который определяет, как специальный документ под названием удерживаемое Получение(выдается, когда компания, назначенная налоговой администрация, удержана налоги, объявляемые компанией, а не клиентом, действительно запутывающие юридические вещи) будет идентифицироваться и информация, которую она представит. Он говорит, что это должно быть пронумеровано в следующем формате:

YYYYMMXXXXXXXX

Где YYYY представляет год, MM месяц и XXXXXXXX представляют порядковый номер (ширину до 8 цифр), который будет обновляться (начало от 0 снова), если он переполнен.

Я мог бы использовать простую ванилью AUTO_INCREMENT, чтобы решить эту загадку, однако настоящая проблема начинается здесь.

По словам агентов налоговой администрации, инкрементная нумерация автоматически обновляется каждый месяц, то есть квитанция № 20151200000001 и № 20160100000001 могут существовать в базе данных и не сталкиваться.

Это означает, что невозможно использовать поле AUTO_INCREMENT, так как его значение будет сбрасываться до 0 каждый месяц.

Какие варианты могут быть использованы для решения этой головоломки? Использование, конечно, только функций базы данных.

PS: Может быть в любой базе данных (включая No-SQL).
PS2: год и месяц могут быть полями на столе/документе/объекте.

Редактировать

Я сделал некоторые исследования на MySQL, основанный на @Gordon Linoff ответ, вот рабочий пример

CREATE TABLE IF NOT EXISTS test (
    id int(11) NOT NULL AUTO_INCREMENT, 
    invoice_no varchar(12) NOT NULL, 
    year int(11) NOT NULL, 
    month int(11) NOT NULL, 
    identifier int(11) DEFAULT NULL, 
    PRIMARY KEY (id) 
) ENGINE=InnoDB; 


DELIMITER // 
CREATE TRIGGER ins_tr BEFORE INSERT ON test 
FOR EACH ROW BEGIN 
    SET @maxID = (SELECT COALESCE(MAX(identifier), 0) 
     FROM test 
     WHERE CONCAT(year, lpad(month, 2, '0')) = CONCAT(NEW.year, lpad(NEW.month, 2, '0')) 
    ); 
    SET NEW.identifier = @maxID +1; 
END 
// 
DELIMITER ; 

INSERT INTO test (invoice_no, year, month) VALUES (1, 2015, 12), (2, 2015, 12), (3, 2016, 1), (4, 2016, 1); 

Результат:

+----+------------+------+-------+------------+ 
| id | invoice_no | year | month | identifier | 
+----+------------+------+-------+------------+ 
| 1 | 1   | 2015 | 12 |   1 | 
| 2 | 2   | 2015 | 12 |   2 | 
| 3 | 3   | 2016 |  1 |   1 | 
| 4 | 4   | 2016 |  1 |   2 | 
+----+------------+------+-------+------------+ 

В исследовании на пути для MongoDB или любого механизма NoSQL.

ответ

0

Во-первых, не делайте это своим основным ключом.

Во-вторых, сохраните текущий номер где-нибудь. Когда вы используете его, увеличиваем его на 1.

Наконец, на первом из месяца или когда он достигает определенного значения, сбросить его в 1.

+0

Я действительно думал об этом выборе, но я неохотно делаю это программно, там должен быть движок db с этой функцией где-то! – josegomezr

+1

С достаточным воображением вы можете поместить всю логику программирования в один триггер. Вы все-таки сказали любую базу данных. –

1

Вы бы осуществить это в реляционной базе данных с помощью триггера , Триггер будет реализовывать логику, такие как:

select new.TaxReceiptNumber := concat(date_format(curdate(), '%Y%m', 
             lpad(coalesce(max(right(TaxReceiptNumber, 8) + 0), 0), 8, '0') 
from t 
where left(TaxReceiptNumber, 6) = date_format(curdate(), '%Y%m'); 

Я мог бы возникнуть соблазн сохранить порядковый номер и даты поступления в разных колонках. Однако, учитывая, что вам нужно работать с налоговыми органами, лучше всего просто указать номер в виде одного столбца.

+0

Кажется перспективным, в 'lpad (coalesce (max (right (TaxReceiptNumber, 8), 0), 8, '0')' shouln't be'lpad (coalesce (max (right (TaxReceiptNumber, 8), 0) + 1, 8, '0') ', чтобы увеличить его на 1? – josegomezr

Смежные вопросы