ordernummer tips
Heeft iemand een idee hoe ik het beste ordernummers kan genereren? Ik wil als iemand een order heeft geplaatst een ordernummer aan zijn / haar bestelling koppelen. Ik wil een ordernummer hebben dat uit 7 cijfers bestaat en dat altijd begint met de letter A, bijvoorbeeld A0000001, A0000002, A0000003 enz.
Op het moment dat een nieuwe bestelling wordt geplaatst moet op basis van het ordernummer van de voorgaande bestelling een nieuw ordernummer worden gegenereerd. Dus stel de laatste bestelling was ordernummer A0000056, dan moet de volgende bestelling ordernummer A0000057 krijgen. Moet ik dit doen door het ordernummer van de laatste rij te nemen (via database SELECT) en deze met 1 op te hogen? Is dat de juiste gedachtengang? En stel nu dat er toevallig 2 bestellingen tegelijkertijd worden geplaatst... die krijgen dan hetzelfde ordernummer. Hoe voorkom je dat?
Graag wat advies, ik hoef geen kant en klare code maar hoop dat iemand me de juiste manier kan vertellen om dit te doen.
Alvast bedankt.
nieuw order doe je de laatste order nummere pakken letter los maken +1 en letter weer vast maken...
door dat voor je insert te bepalen dat hij +1 krijgt..
ik weet niet wat er gebeurt als 100mensen in 20sec dat doen...
----------
of
2 velden
1 = letter
2 = nummer (autonummering
en dan zelf controleren als het 7 cijfers zijn (OH hij ziet 1 cijfer? dan 6 nullen er voor plakken? :P)
Tabel: OrderTypen
Code (pk) | Naam | Beschrijving
A | Automatisering | Dit is een automatiseringsproject
Z | Zomaar | Dit is zomaar een voorbeeld projecttype
Tabel: Orders
Volgnummer (pk, auto_increment) | ProjectType (fk naar OrderTypen)| overigevelden
1 | A | overigeinhoud
2 | Z | zomaarinhoud
De tabel OrderTypen is strict gezien niet noodzakelijk maar wel zeker zeer aan te raden.
Wil je per se vanuit de database ordernummers selecteren dan kan je vervolgens een view gebruiken:
CREATE VIEW OrderWithOrderNumbers AS SELECT CONCAT(ProjectType,LPAD(Volgnummer, 7, 0)) AS OrderNummer, anderekolommen FROM Orders;
Als je het op deze manier doet heb je automatisch gegenereerde ordernummers, met juiste aantal nullen. Kan je makkelijk selecteren en je hebt er met inserten geen omkijken naar. Het enige wat je moet doen is bij de insert het projecttype mee te geven (de prefix zeg maar). Bovendien is alles genormaliseerd. Zo zou ik het dus doen.
Edit: "SELECT OrderNummer, anderekolommen FROM OrderWithOrderNumbers" zou dan dit teruggeven:
A0000001 | anderekolominhoud
Z0000002 | anderekolominhoud
Gewijzigd op 22/12/2010 02:13:45 door The Force
Tabel genaamd seq:
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
mysql> desc seq;
+-------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| name | varchar(20) | NO | PRI | | |
| val | int(10) unsigned | NO | | | |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
+-------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| name | varchar(20) | NO | PRI | | |
| val | int(10) unsigned | NO | | | |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
de functie in MySQL
Code (php)
1
2
3
4
5
2
3
4
5
mysql> CREATE FUNCTION seq(seq_name char(20)) returns int
begin
UPDATE seq SET val=last_insert_id(val+1) WHERE name=seq_name;
RETURN last_insert_id();
end);
begin
UPDATE seq SET val=last_insert_id(val+1) WHERE name=seq_name;
RETURN last_insert_id();
end);
Ophalen van het ordernummer in je php programma:
Dit voorkomt bijvoorbeeld het ophalen van het laatste id uit je ordertabel.
De letter die je ervoor wilt hebben A en de voorloopnullen plaats je nadat je het ordernummer hebt opgehaald.
Gewijzigd op 22/12/2010 09:33:04 door John D
Als ik nu in de databasetabel het ordernummer een auto increment geef, gaat dat dan goed? En kan ik die dusdanig instellen dat het 7 cijfers zijn? Dus dat ie begint met 0000001, of is dat iets wat je in de code moet doen? Dus stel het ordernummer is 1, dat ie dan in de code daar 0000001 van maakt (zo ja, is daar een php fucntie voor)?
SELECT CONCAT(LPAD(Id, 7, 0)) AS OrderNummer
en ik zou toch maar 1 veldje erbij maken en daar de A inzetten. Altijd makkelijk voor later, beter dan in je code.
Edit:
Kortom, volg de reactie van The Force in zijn geheel op! Is een prima oplossing.
Kortom, volg de reactie van The Force in zijn geheel op! Is een prima oplossing.
Gewijzigd op 22/12/2010 10:29:56 door John D
Maak inderdaad geen gebruik van een function hiervoor. Auto increment gaat altijd goed. Je hebt er geen omkijken naar en met de view heb je precies wat je wilt: het ordernummer met genoeg nullen.
CONCAT(LPAD(Id, 7, 0))
Qua gebruik van de functie of autoincrement:
Er zijn voor en nadelen: Bij gebruik van de functie heb je het ordernummer meteen in je code beschikbaar en kan je het tonen aan de klant. Bij autoincement heb je het niet meteen beschikbaar en moet je het na de insert nog een keer ophalen uit de tabel. Deze tabel is altijd groter dan de seq tabel die door de functie benaderd wordt en kost dus meer tijd.
Ik moet dan eerst het laatste ordernummer ophalen via SELECT CONCAT(LPAD(Id, 7, 0)) AS OrderNummer en daarna een nieuwe invoegen?
Nee, wacht ff... dat hoeft natuurlijk niet want het is auto increment.
Dus gewoon een order toevoegen, en om m dan terug te krijgen moet ik die SELECT CONCAT(LPAD(Id, 7, 0)) AS OrderNummer gebruiken? Maar hoe weet ik dan of het de laatst ingevoegde is?
Ozzie PHP op 22/12/2010 10:58:06:
Dat is dus het nadeel van de autoincement maar het klopt allemaal, en om die laatste terug te halen heb je tijdens het opvoeren van de order toch wel gegevens beschikbaar zoals klantnummer? select CONCAT(LPAD(max(Id), 7, 0)) AS OrderNummer from ordertabel where klantnummer = $klantnummer of anders als je niet met klantnummers werkt andere gegevens die de klant zojuist heeft meegegeven en waarmee je de order aan de klant kan koppelen. In principe hoort in de ordertabel een klantid waarmee de klant weer te indentifceren is in de klanttabel.Dus gewoon een order toevoegen, en om m dan terug te krijgen moet ik die SELECT CONCAT(LPAD(Id, 7, 0)) AS OrderNummer gebruiken? Maar hoe weet ik dan of het de laatst ingevoegde is?
Als iemand iets bestelt heb ik z'n naam en adresgegevens (geen klant id). Kan ik niet op een of andere manier iets inserten en tegelijkertjid de id terugkrijgen? Of bestaat zoiets niet?
Lees het volgende eens door:
- CONCAT: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_concat
- LPAD: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_lpad
- VIEWS: http://dev.mysql.com/doc/refman/5.0/en/view-syntax.html
Als je mijn voorbeeld (zie eerste reactie van mij) volgt dan hoef je nergens druk om te maken:
Wil je de code weten dan gebruik je LAST_INSERT_ID() (via MySQL query zie http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html of via PHP: http://php.net/manual/en/function.mysql-insert-id.php). Je krijgt dan de auto increment waarde. Je weet in je code waar je insert al welk OrderType het is (bijv. 'A') en je kan met PHP (str_pad()) ook automatisch de juiste aantal aan nullen genereren. Zo kan je dus meteen het ordernummer teruggeven. Als je de VIEW gebruikt zoals ik die liet zien kan je ook gewoon op ordernummer selecteren.
The Force op 22/12/2010 11:55:18:
Je hebt het nu over een klant id en zonet nog over een ordernummer.
Nee hoor, ik heb het nog steeds uitsluitend over een ordernummer. Thanks voor de info tot zover. Kan ik hopelijk wel even mee vooruit. Wat betreft die last inserted id, is dat een "veilige" oplossing?
Stel je dit voor (even heel simplistisch):
1) iemand heeft spullen in z'n winkelmandje geplaatst
2) hij drukt op 'bestelling plaatsen'
3) de bestelling wordt in de database gezet en krijgt een ordernummer
4) ik vraag het last inserted id op en toon die aan de gebruiker "Bedankt voor uw bestelling. Uw ordernummer is A0000034.
Zou het nu zo kunnen zijn dat tussen punt 3 en 4 iemand anders een bestelling plaatst en ik het last inserted id van die bestelling terugkrijg?
The Force op 22/12/2010 11:55:18:
Wil je de code weten dan gebruik je LAST_INSERT_ID() (via MySQL query zie http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html of via PHP: http://php.net/manual/en/function.mysql-insert-id.php).
LAST_INSERT_ID() via MySQL, deze is niet aan je transctie gebonden die die geeft ook het laatste id wanneer een andere klant heeft ge-insert.
Beter: mysql_insert_id() als PHP functie
Zie: http://php.net/manual/en/function.mysql-insert-id.php
Deze geeft het laatste id dat bij transactie hoort.
@OZZIE: Geen klanttabel ? Geen klant_id in je order tabel? Je hebt ook waarschijnlijk geen tabel orderregel_tabel? Je hebt nog een lange weg te gaan voor een webshop.
Gewijzigd op 22/12/2010 13:12:10 door John D
Die mysql_insert_id lijkt me een goede... ff zoeken of die ook in PDO bestaat...
Zie
http://www.phphulp.nl/php/tutorial/overig/pdo-verbinden-met-verschillende-databases/534/uitvoeren-van-queries/1366/ (bij Voorbeeld 9)
Gewijzigd op 22/12/2010 12:58:54 door Kris Peeters
Ozzie PHP op 22/12/2010 12:54:42:
OK, dan moet het gaan lukken! Suc6John, het is ook een vrij simplistische webshop dus no worries ;)
Gewijzigd op 22/12/2010 13:02:32 door Ozzie PHP
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
<?php
$oInsert = mysql_query("INSERT INTO tabelnaam (veldnaam) VALUES ('waarde')");
if ($oInsert)
{
$iInsertedID = mysql_insert_id();
echo 'U heeft bestelnummer: A'. str_pad($iInsertedID, 7, 0, STR_PAD_LEFT);
}
?>
$oInsert = mysql_query("INSERT INTO tabelnaam (veldnaam) VALUES ('waarde')");
if ($oInsert)
{
$iInsertedID = mysql_insert_id();
echo 'U heeft bestelnummer: A'. str_pad($iInsertedID, 7, 0, STR_PAD_LEFT);
}
?>
Volstaat dat niet gewoon? Dan kun je nog een functie maken die a.d.h.v. een order_id een fraaie bestelnummer maakt (van bijv. '123' naar 'A0000123').
Ja, volgens mij is dat inderdaad wel de basis.