¿Cómo puede tener dos columnas de incremento automático en una tabla?

8

Tengo una tabla MySQL que contiene información sobre las facturas de una empresa. Sin embargo, esta compañía tiene dos sucursales, y cada una de ellas tiene una secuencia de facturación única; una "Serie A" y "Serie B", por así decirlo. Sin embargo, esta es una sola compañía y no quiero crear dos tablas de facturas. Más bien, de alguna manera quiero tener dos incrementos automáticos diferentes para una tabla. Sé que esto técnicamente no es posible, pero supongo que este es un problema que otros han abordado antes, así que me gustaría saber si hay una 'solución' bien conocida para este problema.

Lo que estoy haciendo en este momento no es usar la clave primaria como número de factura (lo cual sería ideal), sino más bien usar una columna secundaria con el ID de la factura, que se incrementa manualmente (bueno, usando un script PHP, pero aún no es automático ), comprobando la última factura de esa serie en particular.

Esta es mi configuración actual:

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 la factura atrasada, ejecuto:

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

Usuario402841
fuente

Respuestas:

11

Lo que está proponiendo hacer solo se puede hacer con MySQL limpiamente bajo tres (3) condiciones

  • CONDICIÓN # 1 : Use el motor de almacenamiento MyISAM
  • CONDICIÓN # 2 : Haga que la columna auto_increment sea parte de una clave primaria compuesta
  • CONDICIÓN # 3 : Cada incremento automático para un tipo dado debe existir en su propia fila
  • Consulte la documentación de auto_increment para MyISAM

Aquí está el diseño original de su mesa

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

Basado en las tres condiciones que acabo de mencionar, aquí está el nuevo diseño de tabla propuesto:

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

Aquí hay un ejemplo a través de datos de muestra y 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;

Aquí se ejecuta:

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>

Darle una oportunidad !!!

PRECAUCIÓN: actualmente, solo el motor de almacenamiento MyISAM admite varios valores de aumento automático agrupados con otras columnas. ¡¡¡Esto no es posible con InnoDB basado en columnas auto_increment vinculadas directamente al gen_clust_index (también conocido como Clustered Index) !!!

RolandoMySQLDBA
fuente
¡Esto es TOTALMENTE INCREÍBLE! No tenía idea de que esto era posible ... ¡gracias por iluminarme!
Usuario402841
Puede hacer algo (similar) en InnoDB pero desafortunadamente no funciona como uno espera. Los números de invitación serían (1,3,5,7)y (2,4,6)para las dos ramas respectivamente :(
ypercubeᵀᴹ
¡Muy mal que no funcione para InnoDB!
Usuario402841
@user, si se necesita InnoDB (en mi caso, necesitaba una clave foránea), puede usar un disparador para simular el incremento automático de múltiples campos. Ver esta publicación
Murta
0

Utilice un activador de inserción posterior en la tabla de facturas para establecer el valor del número de factura una vez que la fila se haya insertado correctamente.

Esto significa que no tiene que hacer el cálculo en su script PHP, sino en la base de datos.

Stephen Senkomago Musoke
fuente