Wie können Sie zwei automatisch inkrementelle Spalten in einer Tabelle haben?

8

Ich habe eine MySQL-Tabelle, die Informationen zu Rechnungen eines Unternehmens enthält. Dieses Unternehmen verfügt jedoch über zwei Niederlassungen, von denen jede eine eindeutige Rechnungsreihenfolge aufweist. eine "Serie A" und "Serie B" sozusagen. Dies ist jedoch eine einzelne Firma, und ich möchte nicht zwei Rechnungstabellen erstellen. Vielmehr möchte ich irgendwie zwei verschiedene automatische Inkremente für eine Tabelle haben. Ich weiß, dass dies technisch nicht möglich ist, aber ich denke, dies ist ein Problem, das andere bereits angegangen sind. Ich würde gerne wissen, ob es für dieses Problem eine bekannte „Lösung“ gibt.

Was ich gerade mache, ist nicht die Verwendung des Primärschlüssels als Rechnungsnummer (was ideal wäre), sondern eine sekundäre Spalte mit der Rechnungs-ID, die manuell inkrementiert wird (naja, mit einem PHP-Skript, aber es ist immer noch nicht automatisch ), indem Sie die neueste Rechnung für diese bestimmte Serie überprüfen.

Dies ist mein aktuelles Setup:

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

Um die Lateset-Rechnung zu überprüfen, führe ich Folgendes aus:

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

User402841
quelle

Antworten:

11

Was Sie vorschlagen, kann nur mit MySQL unter drei (3) Bedingungen sauber gemacht werden

Hier ist Ihr ursprüngliches Tabellenlayout

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

Basierend auf den drei Bedingungen, die ich gerade erwähnt habe, ist hier das neue vorgeschlagene Tabellenlayout:

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

Hier ist ein Beispiel über Beispieldaten und 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;

Hier wird es ausgeführt:

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>

Versuche es !!!

CAVEAT: Derzeit unterstützt nur die MyISAM Storage Engine mehrere auto_increment-Werte, die mit anderen Spalten gruppiert sind. Dies ist nicht möglich, wenn InnoDB darauf basiert, dass auto_increment-Spalten direkt mit dem gen_clust_index (auch bekannt als Clustered Index) verknüpft sind !!!

RolandoMySQLDBA
quelle
Das ist total toll! Ich hatte keine Ahnung, dass dies möglich ist ... danke, dass du mich aufgeklärt hast !!
User402841
Sie können eine (ähnliche) Sache in InnoDB machen, aber leider funktioniert es nicht so, wie man es sich erhofft. Die Invicenumbers wären (1,3,5,7)und (2,4,6)für die beiden Zweige :(
ypercubeᵀᴹ
Wirklich schade, dass es bei InnoDB nicht funktioniert!
User402841
@user, wenn InnoDB benötigt wird (in meinem Fall für Fremdschlüssel), können Sie einen Trigger verwenden, um das automatische Inkrementieren mehrerer Felder zu simulieren. Siehe diesen Beitrag
Murta
0

Verwenden Sie einen After-Insert-Trigger für die Rechnungstabelle, um den Wert der Rechnungsnummer festzulegen, sobald die Zeile erfolgreich eingefügt wurde.

Dies bedeutet, dass Sie die Berechnung nicht in Ihrem PHP-Skript, sondern in der Datenbank durchführen müssen.

Stephen Senkomago Musoke
quelle