Nächste Nummer suchen[ERLEDIGT]

Zugriff, Engines, Konvertierung. Von ADS über DBF bis zu SQL.

Moderator: Moderatoren

Benutzeravatar
Muecke
1000 working lines a day
1000 working lines a day
Beiträge: 623
Registriert: Di, 24. Okt 2006 7:19
Wohnort: Samstagern CH
Hat sich bedankt: 3 Mal
Danksagung erhalten: 9 Mal
Kontaktdaten:

Nächste Nummer suchen[ERLEDIGT]

Beitrag von Muecke »

Hallo zusammen

Ich steh auf dem Schlauch.

Wenn ich in einer Db Pro Satz Nummern habe z.B.

100001
100002
100003
100900
100901

Wie kann ich die nächste Nummern finden die nicht vorhanden ist:
100004

Die DB hat etwa 500000 Datensätze

Kann man dies mit dbeval() lösen ?

Besten Dank für ein Vorschlag.

Gruss Thomas
Zuletzt geändert von Muecke am Mo, 10. Nov 2014 18:48, insgesamt 1-mal geändert.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von brandelh »

Du brauchst einen Index auf die Nummer, dieser muss aktiv sein.
FLOCK() setzen, OHNE FLOCK() geht es nicht sicher :!:
dbGoBottom() ist die höchste verwendete Nummer, plus 1 ...
Append Blank
replace mit neuer Nummer
unlock

Da immer nur einer einen FLOCK() erfolgreich setzen kann, kann man so sicher sein,
dass nicht zwei gleichzeitig die gleiche Nummer berechnen.

Bei einem defekten Index ist das natürlich problematisch.

Bei der FOXDBE kann man auch ein spezielles Feld dafür nutzen.
Gruß
Hubert
Benutzeravatar
Muecke
1000 working lines a day
1000 working lines a day
Beiträge: 623
Registriert: Di, 24. Okt 2006 7:19
Wohnort: Samstagern CH
Hat sich bedankt: 3 Mal
Danksagung erhalten: 9 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Muecke »

Hallo Hubert

Besten Dank, aber so komme ich auf den letzten Satz.

Ich will dazwischen ja suchen

Grus Thomas
DelUser01

Re: Nächste Nummer suchen

Beitrag von DelUser01 »

Hallo Thomas

das habe ich mir gedacht dass Du die "Lücken" suchen willst und nicht nur hochzählen.
Das wäre zu einfach...
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2824
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: Nächste Nummer suchen

Beitrag von georg »

Hallo, Thomas -


wenn Du ALLE Lücken füllen willst/musst, würde ich ein Hilfsprogramm schreiben, dass die Datei nach Nummern liest und alle "offenen" Nummern in eine Hilfsdatei schreibt. Beim Anlegen eines Satzes würde ich mich dann aus der Hilfsdatei bedienen. In Abhängigkeit von der Umgebung, wo das Programm im Einsatz ist, und der Verteilung der "offenen" Nummern kann eine Ermittlung während der normalen Verarbeitung schon mal eine ganze Weile dauern, daher würde ich einen solchen Ansatz wählen (bzw. habe es schon getan).
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Benutzeravatar
Muecke
1000 working lines a day
1000 working lines a day
Beiträge: 623
Registriert: Di, 24. Okt 2006 7:19
Wohnort: Samstagern CH
Hat sich bedankt: 3 Mal
Danksagung erhalten: 9 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Muecke »

Hallo zusammen

Habe dies so gelöst mit

da ich die Anfangsnummer habe, habe ich dies mit einem zähler verglichen.

Code: Alles auswählen

LOCAL nAn:=100000, nArrzahl := 0, nAnz := 0
::oArt->( dbEval( {|| nAnz := nAn+nArrzahl-1 }, {|| nArrzahl++,nAn+nArrzahl <> val(::oArt->an)  },{|| nAn+nArrzahl <> val(::oArt->an) } ) )  
Gruss Thomas
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Jan »

Thomas,

ich würde die Ziffer mit Softseek = .T. suchen. Wenn er die findet (und das tut er mit SOftseek immer), ein Vergleich mit dem tatsächlichen Wert aber einen Unterschied gibt, dann fehlt die Nummer.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Herbert
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1991
Registriert: Do, 14. Aug 2008 0:22
Wohnort: Gmunden am Traunsee, Österreich
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Herbert »

Hallo Thomas
Warum denn so kompliziert eine Nummer suchen? Lass doch die Lücke einfach stehen. Die stört doch keinen.
Zumal SQL solche Aufgaben selber übernehmen kann.
Grüsse Herbert
Immer in Bewegung...
Benutzeravatar
Muecke
1000 working lines a day
1000 working lines a day
Beiträge: 623
Registriert: Di, 24. Okt 2006 7:19
Wohnort: Samstagern CH
Hat sich bedankt: 3 Mal
Danksagung erhalten: 9 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Muecke »

Hallo Herbert
Ja würde ich ja, nur habe ich das Problem, dass ich nur 6 stellige Nummern habe.

Wenn ich immer neue Artikel einlese und ich die nicht mehr brauche, habe ich in kürze diese 6 stellige Nummer aufgebraucht.

Gibt es eine schönere Lösung als SQL ??

Gruss Thomas
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Tom »

Ich wüsste nicht, warum das mit SQL leichter oder schwerer sein sollte als mit ISAM. Du hast eine Tabelle, in der es einen Schlüssel gibt, der auf ein eindeutiges Nummernfeld verweist, beginnend bei 100000. Du suchst jetzt die nächste freie Nummer, wobei Du entweder eine Lücke finden willst - oder eine neue Nummer. Dafür gibt es m.E. nur einen vernünftigen Weg, nämlich diesen hier:

Code: Alles auswählen

FUNCTION FindNextNumber()
LOCAL nStartNumber := 99999, lFound := .F.
DO WHILE !lFound
  nStartNumber ++
  SEEK nStartNumber
  lFound := !Eof()
ENDDO
RETURN nStartNumber
Das Problem: Wenn die Nummernfolge konsistent ist und tatsächlich 500.000 Datensätze vorliegen, sucht das 500.000 Mal. Ich würde das SQL-Statement, das das schlauer macht, gerne sehen. Bis dahin schließe ich mich Herbert an: Es ist nicht sehr klug, so vorzugehen. In diesem Zusammenhang stellt sich auch die Frage, wie die Lücken entstehen können. Wenn es um Rechnungsnummern geht, muss es für die Löschungen Erklärungen geben, z.B. Stornos. Bei Kunden-/Debitorennummern aber auch.
Herzlich,
Tom
DelUser01

Re: Nächste Nummer suchen

Beitrag von DelUser01 »

Hallo Thomas

vor dem Problem "Lücken" füllen zu müssen stehe ich auch bald.
Die Lösung die schon weiter vorn genannt wurde - regelmäßig eine DB mit freien Nr. zu erstellen - ist vermutlich die derzeit Praktikabelste um wirklich alle Lücken zu finden und zu füllen.
Vielleicht hast Du bzw. Dein Kunde bei der betreffenden Nummerierung auch erst weiter oben angefangen mit Zählen - z.B. bei 20000. Dann könntest Du einfach von 20000 herunterzählen. Zumindest bis die bessere "Lücken-Füller-Lösung" vorliegt.
Benutzeravatar
Herbert
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1991
Registriert: Do, 14. Aug 2008 0:22
Wohnort: Gmunden am Traunsee, Österreich
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Herbert »

Tom, es ist nicht ein SQL-Statement, sondern der Feldtyp "Auto increment". In MS SQL ist dies der Typ IDENTITY. Nummern werden von selbst aufsteigend ausgefüllt. Wenn ein Eintrag physisch gelöscht worden ist, wird die fehlende Nummer automatisch wieder ersetzt. In Windev (pardon, Manfred) existiert dazu der Feldtyp Automatic ID mit genau denselben Eigenschaften.
Grüsse Herbert
Immer in Bewegung...
Benutzeravatar
Herbert
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1991
Registriert: Do, 14. Aug 2008 0:22
Wohnort: Gmunden am Traunsee, Österreich
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Herbert »

Muecke hat geschrieben:Hallo Herbert
Ja würde ich ja, nur habe ich das Problem, dass ich nur 6 stellige Nummern habe.
Thomas, du kannst ja noch Minuszahlen bis -99999 dazu nehmen... :angel8:
Grüsse Herbert
Immer in Bewegung...
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Tom »

Hallo, Herbert.

Es geht, wenn ich das richtig verstehe, nicht um das korrekte Zählen. Sondern darum, dass inzwischen Nummern wieder freigeworden sind, die vorher schon vergeben waren, was übrigens mit einem AutoIncrement-Feld unmöglich wäre. :wink:

Insofern wäre eine Hilfstabelle schon eine gute Wahl, die alle bislang vergebenen Nummern enthält und beispielsweise ein logisches Feld für "frei". Und dann sucht man einfach nach dem ersten Datensatz, der auf "frei" steht, feddisch. Voraussetzung: Die Pflege der Hilfstabelle funktioniert ordentlich.
Herzlich,
Tom
Benutzeravatar
Herbert
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1991
Registriert: Do, 14. Aug 2008 0:22
Wohnort: Gmunden am Traunsee, Österreich
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Herbert »

Tom, nein, nicht unbedingt. Laut Beschreibung steht da: "a unique value will be added automatically", was nicht unbedingt ein nächst Höheres heissen muss.
Grüsse Herbert
Immer in Bewegung...
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Tom »

Hallo, Herbert.

Hab's gerade ausprobiert, eine Tabelle in einer MS-SQL-Datenbank erzeugt, Feld "Nummer" vom Typ "Auto Increment", zehn Datensätze angelegt (1 bis 10), Eintrag 5 gelöscht. Nächster neuer Eintrag: Nummer 11. :wink:
Herzlich,
Tom
DelUser01

Re: Nächste Nummer suchen

Beitrag von DelUser01 »

ich denke Mal laut:

ein Ansatz wäre, eine DB(1) mit allen Zahlen zu füllen welche vorkommen können/dürfen.
Also bei sechsstellig von 1 bis 999999.
Hierauf einen Index mit einer For-Bedingung,
z.B. "for NR not in DB(2)". Damit müsste es möglich sein, dass die DB(1) mit dem Index nur die freien Zahlen der DB(2) anzeigt.
Wenn nun konsequenter Weise in einem Programm an mehreren Stellen sie sechsstellige NR verwendet wurde könnte man für jede DB (3/4/5...) einen Index aufbauen.
Ist vielleicht am Anfang eine Arbeit für den PC/Server sollte aber dann nicht viel mehr Zeit in Anspruch nehmen.

Der Ansatz ist ganz einfach der, nach etwas das nicht da ist kann ich nicht suchen, also muss ich eine Referenz aufbauen damit das Programm sieht was fehlt.

Wie gesagt, war nur Mal laut gedacht...

(Korrigiert!)
Zuletzt geändert von DelUser01 am Mo, 10. Nov 2014 13:52, insgesamt 1-mal geändert.
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Jan »

Tom hat Recht. Es wird immer der nächst höhere Wert genommen. Das ist auch so bei dem Autofeld in FOXDBE. Leere, inzwischen gelöschte Werte, werden nicht nachgeholt.

Von daher scheint mir der Vorschlag von Tom am besten zu sein, einen Satz als ungültig zu markieren. Und die Artikelnummer drin stehen zu lassen. Oder ein Feld N6 anzulegen in das bei einer "Löschung" die jetzt ungültige Artikelnummer eingetragen wird, alle anderen Felder werden geleert. Und für neue Artikel werden erstmal Sätze genommen, die einen Wert in diesem Feld haben.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Herbert
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1991
Registriert: Do, 14. Aug 2008 0:22
Wohnort: Gmunden am Traunsee, Österreich
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Herbert »

OK gebe mich geschlagen. Liess mich wohl von der Nummer des physischen Tabelleneintrags täuschen.
Grüsse Herbert
Immer in Bewegung...
Benutzeravatar
Herbert
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1991
Registriert: Do, 14. Aug 2008 0:22
Wohnort: Gmunden am Traunsee, Österreich
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Herbert »

Jan hat geschrieben:Von daher scheint mir der Vorschlag von Tom am besten zu sein, einen Satz als ungültig zu markieren. Und die Artikelnummer drin stehen zu lassen. Oder ein Feld N6 anzulegen in das bei einer "Löschung" die jetzt ungültige Artikelnummer eingetragen wird, alle anderen Felder werden geleert. Und für neue Artikel werden erstmal Sätze genommen, die einen Wert in diesem Feld haben.
Diesen Umweg verstehe ich nicht. Eine neue Tabelle soll dazu dienen, fehlende Nummern zu finden? Das gibt nur neue Synchronisationsprobleme. Wir reden ja von Netzwerkprogrammen, wo jeder User jederzeit Veränderungen produzieren kann.
Die gute alte Schlaufe ist da wirklich das beste.

Code: Alles auswählen

// index steht auf kunr
GO BOTTOM
nkunr=ads->kunr+1
if nkunr>999999
  do while .t.
    nkunr--
    if not dbseek(nkunr,.F.) then
      exit
    end
  enddo
end
return nkunr
Grüsse Herbert
Immer in Bewegung...
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Jan »

Herbert,

ich habe nicht geschrieben eine parallele Tabelle, sondern in der vorhandenen Tabelle ein zusätzliches Feld für die Markierung, das dieser Satz neu belegt werden kann. Mit einem Merker, welche Artikelnummer das sein wird, ohne erst groß danach suchen zu müssen.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Tom »

Hallo, Herbert.

Wenn man sauber arbeitet, funktioniert das. Ich nehme an, es geht um Kunden. Bei der Neueingabe wird eine neue Nummer vergeben, beim Löschen oder Archivieren eine alte freigegeben - mehr Funktionalitäten wird es kaum geben, die das betreffen. Ich pflege parallel eine Hilfstabelle, die für jede neue Nummer einen Datensatz anlegt (bei Initialisierung einmal für alle möglichen Nummern erzeugen) und "frei" auf .F. setzt (bzw. lässt). Beim Löschen wird diese Nummer gesucht und "frei" auf .T. gesetzt. Es gibt einen Index auf Nummern und einen zweiten auf "frei". Suche ich "!frei", erhalte ich entweder Eof() bzw. Found() = .F., dann vergebe ich eine neue Nummer. Finde ich einen Datensatz, setze ich "frei" auf .F. und nehme diese Nummer.
Herzlich,
Tom
DelUser01

Re: Nächste Nummer suchen

Beitrag von DelUser01 »

Hallo Jan

bei gelöschten Records könnte man das so machen, dass die alte, verlorene NR in einem weiteren Feld "geparkt" wird um diese wieder zu verwenden.
Was aber wenn durch Benutzereingriff große Lücken entstanden sind und diese Nr.-Bereiche noch nie in Verwendung waren?
Benutzeravatar
Herbert
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1991
Registriert: Do, 14. Aug 2008 0:22
Wohnort: Gmunden am Traunsee, Österreich
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Nächste Nummer suchen

Beitrag von Herbert »

Jan hat geschrieben:ich habe nicht geschrieben eine parallele Tabelle, sondern in der vorhandenen Tabelle ein zusätzliches Feld für die Markierung, das dieser Satz neu belegt werden kann. Mit einem Merker, welche Artikelnummer das sein wird, ohne erst groß danach suchen zu müssen.
OK, verstand deine Sätze nicht ganz...
Aber besser finde ich das nicht.
Hier liegt die grosse Gefahr, dass Resteinträge übrigbleiben und mit dem auf diese Art wieder sichtbar gemachten Satz fälschlicherweise vorhanden sind. Daher sollten stets neue Sätze angelegt werden und nicht auf diese Art gebastelt werden.
Grüsse Herbert
Immer in Bewegung...
DelUser01

Re: Nächste Nummer suchen

Beitrag von DelUser01 »

Hallo Herbert
Herbert hat geschrieben:Hier liegt die grosse Gefahr, dass Resteinträge übrigbleiben und mit dem auf diese Art wieder sichtbar gemachten Satz fälschlicherweise vorhanden sind. Daher sollten stets neue Sätze angelegt werden und nicht auf diese Art gebastelt werden.
Wenn Du beim löschen des Records alle Felder zurücksetzt (leerer Record) tauschen keine alten Daten mehr auf.
Natürlich können - wenn nicht alle Einträge welche die NR referenzieren in allen Datenbanken gelöscht oder geändert wurden - tauchen diese wieder in falschem Zusammenhang auf.
Dann dürfte man aber keine bereits benutzte und gelöschte NR wiederverwenden - aber gehen wir davon aus, dass wir gut programmiert haben...
Antworten