Archief - Algoritme: Uniek nummer vormen, op basis van Jaartallen probleempje.

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

orez

Legacy Member
Ok ik zit met volgende probleemstelling voor een administratief programma dat ik momenteel aan het ontwikkelen ben en zit nog met een paar kleine probleempjes, waar ik niet direct iets op kan vinden. Of weet hoe het moet gedaan worden.

(VB.NET trouwens)

Bij elke order die binnen het bedrijf binnenkomt worden er dus nieuwe velden aangemaakt met telkens een uniek nummer, momenteel heb ik het gewoon op autonummering gezet, om het programma te testen en te kijken als er eventuele bugs optreden.

Nu het unieke nummer zou moeten gevormd worden door 8 cijfers.

de eerste 2 zouden het jaartal moeten zijn dus:

04
05
06

en de volgende 6 een standaard nummering

dus bv:
04000001
04000002

Nu heb ik dus enkel: 1,2,3,4,5 ...

Telkens een nieuw jaar begint moet het nummer opnieuw opnieuw starten:

dus opnieuw
05000001
05000002
.......

die eerste 2 getallen is niet echt moeilijk das te doen met de YEAR() Functie
Voor de nieuwe nummering zou hij dus de vorige rij in de database moeten controleren elke keer bij invullen van een nieuw veld en zijn de 1ste 2 cijfers kleiner dan het huidige zou de nummering opnieuw moeten beginnen. Maar HOE laat je die nummering opnieuw beginnen. En hoe stel je in dat het uit 8 cijfers MOET bestaan...

Wordt dit het best in SQL geprogrammeerd of uiteindelijk in Visual Basic zelf, op dit probleem zit ik me al een tijdje vast te staren...

(Liefst code voorbeelden, want hoe het zou moeten gebeuren heb ik dus al uitgedoktert zoals je ziet)

Allesinds bedankt voor jullie hulp!

servi

Legacy Member
niet direct efficiënste methode, maar dit schiet me direct te binnen

SELECT x FROM y WHERE id = CONCAT(YEAR(),0001);

als SQL niets returnt, dan is teken dat er een nieuw jaar begonnen en moet je dus opnieuw met de telling beginnen.

voor te weten wat de volgende nummer is :
SELECT MAX(id) AS idnummer FROM Y WHERE id > CONCAT(YEAR(),0001);

en dan tel je 1 bij bij idnummer.

overigens zou het niet gemakkelijker zijn om apart het jaar en de id bij te houden en die dan samen te voegen bij het tonen naar scherm ?
Nu maak je het immers moeilijker voor je eigen.

met aparte velden zo het er zo uit zien :
SELECT id FROM y WHERE jaar = YEAR();
indien leeg, begin nieuwe nummering.


voor volgende nummer te weten te komen
SELECT MAX(id) AS idnummer FROM y WHERE jaar = YEAR();

en 1tje bijtellen bij idnummer.



edit : dit is niet te gebruiken als er idnummers kunnen wegvallen.

orez

Legacy Member
Is die methode met verschillende velden dan de efficientere manier of gewoon een andere oplossing?

Die indien leeg snap ik niet echt... Hij vult dus automatisch het jaartal in, als er bv vandaag een nieuwe order binnenkomt (ik zeg maar) dan is het de NOW() functie die de datum retourneert. Uit de datum zelf haal ik dan de laatste 2 cijfers van het jaartal. Dus vult hij dit telkens automatisch in bij invoeging van elke nieuwe order. Zodus kan het vorige veld toch niet leeg zijn? Of begrijp ik het verkeerd?

Je hebt me allesins al ferm geholpen, ben er al ietswat wijzer uitgeworden, had nog nooit aan de functie CONCAT gedacht.

orez

Legacy Member
nog ff nagedacht

die max id zit in een String...

If Mid(MaxID,1,2) > YEAR(Now()) Then
Nieuw ID aanmaken, door INSERT Statement op JaartalNu + 000001 Te zetten
Else
Vorige Record ID + 1
End If

Zou het zo mogelijk zijn?

zero2one

Legacy Member
allemaal mooi in theorie en als er maar 1 persoon tegelijk kan ingeven !!

wat als er 2 personen tegelijk aant ingeven zijn en er 2 dezelfde "unieke" waardes geinput worden?

als je eerst de maxid ophaalt en die +1 doet om nen nieuwe unieke nr aan te maken heb je veel kans dat dit gebeurd !!

Don Kedero

Legacy Member
surf naar google en zoek eens op transacties en database lock :woohoo:

killgore

Legacy Member
zero2one zei:
allemaal mooi in theorie en als er maar 1 persoon tegelijk kan ingeven !!

wat als er 2 personen tegelijk aant ingeven zijn en er 2 dezelfde "unieke" waardes geinput worden?
ehm, servy zen methode haalt altijd de MAX id waarde op, en om echt juist op hetzelfde moment een insert query te laten verlopen zodat ze allebei dezelfde max(id) waarden ophalen moet je al heeeel nauwkeurig zijn (dunno zelfs of dat kan).

servi

Legacy Member
bwoa dat kan, maar de kans is vrij klein, ( die id ga je uiteraard pas ophalen als je gaat inserten)

wat er zou moeten gebeuren is :

usera drukt "versturen"
usera krijgt bijvoorbeeld id 0003
userb moet op versturen drukken en moet verwerkt zijn alvorens de INSERT van usera is gedaan
userb krijgt ook id 0003
INSERT van usera gebeurt met id 0003
bijgevolg gebuert INSERT van userb ook met id 0003 => probleem


maar dat kan je vrij eenvoudig vermijden door UNIQUE als extra attribuut in te stellen.
als het 2 aparte velden zijn moet je een UNIQUE(jaar,id) maken, als het 1 veld is kan je het gewoon bij dat veld zetten.

orez

Legacy Member
PHP:
Private Function OrderID()
        Dim sqlOrderID, sqlNewOrderID As String
        Dim intYear, intYearCheck, intOrderID As Int32
        sqlOrderID = "Select Max(OrderID) As LastIDnr From tblOrders"
        Dim cmdLastID As New SqlClient.SqlCommand(sqlOrderID, conAdministratie)
        conAdministratie.Open()
        If Not IsDBNull(cmdLastID.ExecuteScalar()) Then
            intOrderID = cmdLastID.ExecuteScalar()
            intYear = Format(Now(), "yyyy")
            intYearCheck = Mid(intOrderID, 1, 4)
            If Not intYearCheck < intYear Then
                intOrderID = intOrderID + 1
            Else
                intOrderID = Format(Now(), "yyyy") & "00001"
            End If
        Else
            intOrderID = Format(Now(), "yyyy") & "00001"
        End If
        conAdministratie.Close()
        sqlNewOrderID = "INSERT INTO tblOrders(OrderID) VALUES (" & intOrderID & ")"
        Dim cmdNewID As New SqlClient.SqlCommand(sqlNewOrderID, conAdministratie)
        conAdministratie.Open()
        cmdNewID.ExecuteScalar()
        conAdministratie.Close()
    End Function

Ik heb deze functie geschreven.
En even ter verduidelijking --> Op de receptie (waar er dus ontvangen wordt vanuit de camions) zit er 1 persoon/keer, dus kan het niet zijn dat meerdere personen gegevens zullen invoeren. Toch wel bedankt om dit probleem aan te kaarten, kan ik eventueel rekening mee houden voor een volgend programma die met eenzelfde systeem zou moeten werken.

En Don't worry, deze functie is enkel om te testen, de INSERT statement hierin zal wel nog verwijderd worden en kzal wel zorgen dat deze functie enkel de waarde retourneert dat dus nodig is. En dan van hieruit de INSERT statement opmaken.

Ik werk nu ook met het volledige jaartal ipv met de 2 laatste cijfers. Dit ook om enkele probleempjes te vermijden.
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan