Как вы можете иметь два автоинкрементных столбца в одной таблице?

8

У меня есть таблица MySQL, которая содержит информацию о счетах компании. Однако у этой компании есть два филиала, и у каждого из них есть уникальная последовательность выставления счетов; «Серия А» и «Серия Б», так сказать. Однако это одна компания, и я не хочу создавать две таблицы счетов. Скорее, я как-то хочу иметь два разных автоинкремента для одной таблицы. Я знаю, что это технически невозможно, но я думаю, что это проблема, с которой ранее сталкивались другие, поэтому я хотел бы знать, есть ли известное «решение» для этой проблемы?

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

Это моя текущая настройка:

CREATE TABLE `invoices` (
  `id` mediumint unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `invoicenumber` mediumint unsigned NOT NULL,
  `branch` enum('A','B') NOT NULL,
  `date` date NOT NULL,
  `client` varchar(100) NOT NULL
) COMMENT='' ENGINE='InnoDB';

Чтобы проверить поздний счет, я запускаю:

SELECT MAX(invoicenumber+1) AS new_invoice_number FROM invoices WHERE branch = 'A'

User402841
источник

Ответы:

11

То, что вы предлагаете сделать, можно сделать с MySQL только в трех (3) случаях.

  • СОСТОЯНИЕ № 1 : Используйте механизм хранения MyISAM
  • СОСТОЯНИЕ № 2 : Сделать столбец auto_increment частью составного первичного ключа.
  • СОСТОЯНИЕ № 3 : Каждый auto_increment для данного типа должен существовать в своей собственной строке
  • См. Документацию auto_increment для MyISAM.

Вот ваш оригинальный план стола

CREATE TABLE `invoices` ( 
  `id` mediumint unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, 
  `invoicenumber` mediumint unsigned NOT NULL, 
  `branch` enum('A','B') NOT NULL, 
  `date` date NOT NULL, 
  `client` varchar(100) NOT NULL 
) COMMENT='' ENGINE='InnoDB'; 

Исходя из трех условий, которые я только что упомянул, вот новый предложенный макет таблицы:

CREATE TABLE `invoices` ( 
  `invoicenumber` mediumint unsigned NOT NULL auto_increment, 
  `branch` enum('A','B') NOT NULL, 
  `date` date NOT NULL, 
  `client` varchar(100) NOT NULL,
  PRIMARY KEY (branch,invoicenumber)
) COMMENT='' ENGINE='MyISAM'; 

Вот пример через пример данных и SQL:

drop database if exists user1162541;
create database user1162541;
use user1162541
CREATE TABLE `invoices` ( 
  `invoicenumber` mediumint unsigned NOT NULL auto_increment, 
  `branch` enum('A','B') NOT NULL, 
  `date` date NOT NULL, 
  `client` varchar(100) NOT NULL,
  PRIMARY KEY (branch,invoicenumber)
) COMMENT='' ENGINE='MyISAM'; 
INSERT INTO invoices (branch,date,client) VALUES
('A',DATE(NOW()),'John'),
('B',DATE(NOW()),'Jack'),
('A',DATE(NOW()),'Jeff'),
('B',DATE(NOW()),'Joel'),
('A',DATE(NOW()),'Jane'),
('B',DATE(NOW()),'Joan'),
('A',DATE(NOW()),'June');
SELECT * FROM invoices ORDER BY branch,invoicenumber;

Вот это выполнено:

mysql> drop database if exists user1162541;
Query OK, 1 row affected (0.01 sec)

mysql> create database user1162541;
Query OK, 1 row affected (0.02 sec)

mysql> use user1162541
Database changed
mysql> CREATE TABLE `invoices` (
    ->   `invoicenumber` mediumint unsigned NOT NULL auto_increment,
    ->   `branch` enum('A','B') NOT NULL,
    ->   `date` date NOT NULL,
    ->   `client` varchar(100) NOT NULL,
    ->   PRIMARY KEY (branch,invoicenumber)
    -> ) COMMENT='' ENGINE='MyISAM';
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO invoices (branch,date,client) VALUES
    -> ('A',DATE(NOW()),'John'),
    -> ('B',DATE(NOW()),'Jack'),
    -> ('A',DATE(NOW()),'Jeff'),
    -> ('B',DATE(NOW()),'Joel'),
    -> ('A',DATE(NOW()),'Jane'),
    -> ('B',DATE(NOW()),'Joan'),
    -> ('A',DATE(NOW()),'June');
Query OK, 7 rows affected (0.02 sec)
Records: 7  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM invoices ORDER BY branch,invoicenumber;
+---------------+--------+------------+--------+
| invoicenumber | branch | date       | client |
+---------------+--------+------------+--------+
|             1 | A      | 2012-04-21 | John   |
|             2 | A      | 2012-04-21 | Jeff   |
|             3 | A      | 2012-04-21 | Jane   |
|             4 | A      | 2012-04-21 | June   |
|             1 | B      | 2012-04-21 | Jack   |
|             2 | B      | 2012-04-21 | Joel   |
|             3 | B      | 2012-04-21 | Joan   |
+---------------+--------+------------+--------+
7 rows in set (0.00 sec)

mysql>

Попробуйте!

CAVEAT: В настоящее время только MyISAM Storage Engine поддерживает несколько значений auto_increment, сгруппированных с другими столбцами. Это невозможно с InnoDB на основе столбцов auto_increment, привязанных непосредственно к gen_clust_index (он же Clustered Index) !!!

RolandoMySQLDBA
источник
Это ПОЛНОСТЬЮ УДИВИТЕЛЬНЫЙ! Я понятия не имел, что это возможно ... спасибо, что просветили меня!
User402841
Вы можете сделать (похожую) вещь в InnoDB, но, к сожалению, она не работает, как можно надеяться. Номера счетов будут (1,3,5,7)и (2,4,6)для двух ветвей соответственно :(
ypercubeᵀᴹ
Очень жаль, что это не работает для InnoDB!
User402841
@user, если нужен InnoDB (в моем случае мне нужен внешний ключ), вы можете использовать триггер для имитации автоприращения в нескольких полях. Смотрите этот пост
Мурта
0

Используйте триггер после вставки в таблицу счетов, чтобы установить значение номера счета после успешной вставки строки.

Это означает, что вы должны выполнять вычисления не в своем скрипте PHP, а в базе данных.

Стивен Сенкомаго Мусоке
источник