Come puoi avere due colonne auto-incrementali in una tabella?


8

Ho una tabella MySQL che contiene informazioni sulle fatture di un'azienda. Tuttavia, questa azienda ha due filiali e ognuna di esse ha una sequenza di fatturazione unica; una "Serie A" e "Serie B", per così dire. Tuttavia, questa è un'unica azienda e non voglio creare due tabelle di fatture. Piuttosto, in qualche modo voglio avere due diversi incrementi automatici per una tabella. So che tecnicamente non è possibile, ma immagino che questo sia un problema che altri hanno già affrontato, quindi mi piacerebbe sapere se esiste una "soluzione" ben nota per questo problema?

Quello che sto facendo in questo momento non è usare la chiave primaria come numero di fattura (che sarebbe l'ideale), ma piuttosto usare una colonna secondaria con l'ID fattura, che viene incrementato manualmente (bene, usando uno script PHP, ma non è ancora automatico ), controllando l'ultima fattura per quella particolare serie.

Questa è la mia configurazione attuale:

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

Per controllare la fattura di Lateset, corro:

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

Risposte:


11

Quello che stai proponendo di fare può essere fatto in modo pulito con MySQL solo in tre (3) condizioni

  • CONDIZIONE N. 1 : utilizzare il motore di archiviazione MyISAM
  • CONDIZIONE # 2 : Rendi la colonna auto_increment parte di una chiave primaria composta
  • CONDIZIONE # 3 : ogni incremento automatico per un determinato tipo deve esistere nella propria riga
  • Consulta la documentazione di auto_increment per MyISAM

Ecco il layout originale della tabella

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

Sulla base delle tre condizioni che ho appena menzionato, ecco il nuovo layout di tabella 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'; 

Ecco un esempio tramite dati di esempio 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;

Qui viene eseguito:

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>

Provaci !!!

CAVEAT: Attualmente, solo il motore di archiviazione MyISAM supporta più valori di incremento automatico raggruppati con altre colonne. Questo non è possibile con InnoDB basato su colonne auto_increment legate direttamente a gen_clust_index (aka Clustered Index) !!!


Questo è TOTALMENTE FANTASTICO! Non avevo idea che ciò fosse possibile ... grazie per avermi illuminato !!
Utente 402841

Puoi fare una cosa (simile) in InnoDB ma sfortunatamente non funziona come si spera. Gli invicenumbers sarebbero (1,3,5,7)e (2,4,6)per i due rami rispettivamente :(
ypercubeᵀᴹ

Davvero un peccato che non funzioni per InnoDB!
Utente 402841

@utente, se InnoDB è necessario (nel mio caso avevo bisogno di chiave esterna), è possibile utilizzare un trigger per simulare l'incremento automatico a più campi. Vedi questo messaggio
Murta,

0

Utilizzare un trigger after insert sulla tabella delle fatture per impostare il valore del numero di fattura una volta che la riga è stata inserita correttamente.

Ciò significa che non è necessario eseguire il calcolo nello script PHP, ma nel database.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.