Como você pode ter duas colunas de incremento automático em uma tabela?


8

Eu tenho uma tabela MySQL que contém informações sobre faturas de uma empresa. No entanto, esta empresa possui duas filiais e cada uma delas possui uma sequência de faturamento exclusiva; uma "Serie A" e "Serie B", por assim dizer. No entanto, esta é uma empresa única e não quero criar duas tabelas de faturas. Em vez disso, de alguma forma, quero ter dois incrementos automáticos diferentes para uma tabela. Sei que isso tecnicamente não é possível, mas acho que esse é um problema que outras pessoas já enfrentaram antes, então gostaria de saber se existe uma 'solução' conhecida para esse problema?

O que estou fazendo agora não é usar a chave primária como número da fatura (o que seria ideal), mas usar uma coluna secundária com o ID da fatura, que é incrementado manualmente (bem, usando um script PHP, mas ainda não é automático ), verificando a fatura mais recente para essa série específica.

Esta é a minha configuração atual:

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';

Para verificar a fatura do conjunto de dados, eu corro:

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

Respostas:


11

O que você está propondo a fazer só pode ser feito com o MySQL de forma limpa sob três (3) condições

  • CONDIÇÃO Nº 1 : Use o mecanismo de armazenamento MyISAM
  • CONDIÇÃO 2 : Tornar a coluna auto_increment parte de uma chave primária composta
  • CONDIÇÃO 3 : Cada incremento automático para um determinado tipo deve existir em sua própria linha
  • Veja a documentação de auto_increment para MyISAM

Aqui está o layout original da tabela

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'; 

Com base nas três condições que acabei de mencionar, aqui está o novo layout de tabela proposto:

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'; 

Aqui está um exemplo via dados de amostra e 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;

Aqui é executado:

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>

De uma chance !!!

CAVEAT: No momento, apenas o MyISAM Storage Engine suporta vários valores de incremento automático agrupados com outras colunas. Isso não é possível com o InnoDB baseado em colunas de auto_increment vinculadas diretamente ao gen_clust_index (também conhecido como Índice de Cluster) !!!


Isso é TOTALMENTE IMPRESSIONANTE! Eu não tinha ideia de que isso era possível ... obrigado por me esclarecer !!
usar o seguinte código

Você pode fazer uma coisa (semelhante) no InnoDB, mas infelizmente não funciona como se espera. Os invicenumbers seriam (1,3,5,7)e (2,4,6)para os dois ramos, respectivamente :(
ypercubeᵀᴹ

Muito ruim, não funciona para o InnoDB!
User402841

@user, se o InnoDB for necessário (no meu caso, eu precisava de chave estrangeira), você pode usar um gatilho para simular o incremento automático de vários campos. Veja este post
Murta

0

Use um gatilho após inserção na tabela de faturas para definir o valor do número da fatura depois que a linha for inserida com sucesso.

Isso significa que você não precisa fazer a computação no seu script PHP, mas no banco de dados.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.