![]() |
Datenbank: MSDE • Zugriff über: ADO
Und gleich nochmal MAX(), diesmal mit MSSQL.
Guten Abend zusammen !
Es geht schon wieder um Rechnungsnummern. Ja, gesucht hab ich genug! :wall: Vorab: Was ist die bessere (=schnellere) Formulierung ?
SQL-Code:
oder
Select Top 1 Nummer from Nummern where Datum is null order by Nummer
SQL-Code:
Warum warum liefert diese Formulierung einen Syntaxfehler ?
Select MAX(Nummer) from Nummern where Datum is null
SQL-Code:
Wie krieg ich die grösste Nummer in eine lokale Variable ?
SET @Nummer = Select MAX(Nummer) as MaxNr FROM Nummern
Gibt es im SQL sowas wie einen "Aktuellen Datensatz" ? Bei Triggern gibts ja DELETED und INSERTED. In einer professionellen Warenwirtschaft hab ich auch herumgestöbert. Da wird ein Cursor deklariert und mit Fetch werden die Feldwerte in lokale Variablen geholt. Kurzer Ausschnitt:
SQL-Code:
Geht das nicht einfacher ?
DECLARE cAdressen CURSOR FOR SELECT Mandant,Adresse,Telefon,Mobilfunk FROM Inserted
OPEN cAdressen IF @@Cursor_Rows<>0 BEGIN FETCH NEXT FROM cAdressen INTO @Mandant,@Adresse,@Telefon,@Mobilfunk WHILE (@@FETCH_STATUS = 0) BEGIN .... END END CLOSE cAdressen DEALLOCATE cAdressen Viele Fragen an die SQL-Gurus. THX im Vorraus ! :lol: |
Re: Und gleich nochmal MAX(), diesmal mit MSSQL.
Moin,
ich würde diese Formulierung bevorzugen...
SQL-Code:
Select MAX(Nummer) from Nummern where Datum is null
Zitat:
SQL-Code:
SET @Nummer = (Select MAX(Nummer) as MaxNr FROM Nummern)
Zitat:
Zitat:
Meinst du das in einer SQL-Anweisung, Prozedur, Funktion, Trigger,... Was genau möchtest du machen? MfG Thorsten |
Re: Und gleich nochmal MAX(), diesmal mit MSSQL.
Auch dir einen guten Abend.
Zitat:
Zitat:
SQL-Code:
declare @Nummer int
set @Nummer = (select max(Nummer) from Nummern) Zitat:
Zitat:
Freundliche Grüße vom marabu |
Re: Und gleich nochmal MAX(), diesmal mit MSSQL.
@Omata, @Marabu: Danke für die schnellen Antworten !
JaJa - die Klammern - bin schon ganz verwirrt ! :wall: Jetzt läufts ! :cheers: |
Re: Und gleich nochmal MAX(), diesmal mit MSSQL.
nochwas:
SQL-Code:
So würde ich das machen.
select @Nummer = max (Nummer) from Nummern where Datum is null
Nun zu Deiner Frage:
SQL-Code:
scheint etwas (aber wirklich nur etwas) besser zu sein, als
select top 1 Nummer from Nummern where Datum is null order by nummer desc
SQL-Code:
aber nur unter der Voraussetzung, das Nummern und Datum indiziert ist. Ohne das näher zu analysieren würde ich annehmen, das der clustered Index auf dem 'Datum' liegen muss, damit die beiden Versionen identisch sind.
select max (Nummer) from Nummern where Datum is null
Ansonsten ist Variante 1 (also MAX) eindeutig besser, ohne Index ca. 10x schneller. Mit einfachen Indizes ca 3x. Ich denke, das liegt am Sortieren. Ich hab das rudimentär mit einer 100.000 Tabelle getestet, da tut das Sortieren natürlich weh. ORDER BY wird nur bei clustered indexen ignoriert, denn da liegen die Daten schon richtig sortiert vor. Unabhängig davon ist es blasphemisch, die nächste Rechnungsnummer so zu erzeugen (finde ich). Denn der Server wird überflüssigerweise mit Arbeit zugeballert (außer, die Indexe stimmen). Stell Dir einfach vor, es wären 100.000.000 Rechnungen (na ja, wer hat die schon, aber egal). Ich arbeite gerade am gleichen Problem und verwende einen Zähler. Ich habe eine Tabelle mit Rechnungen, die nun fakturiert werden sollen. Ich erzeuge eine temporäre Tabelle über dynamisches SQL, und zwar mit zwei Spalten ('IDRechnung' und 'RechnungsNr'). Die RechnungsNr wird als Identity deklariert, der Seed wird auf die nächste freie Rechnungsnummer gesetzt. Das geht mit plain SQL nicht, also erzeuge ich mir das folgende Statement als String und führe es einfach mit EXEC aus:
SQL-Code:
Die Tabelle erzeugt also automatisch neue Rechnungsnummern, sobald die Tabelle gefüllt wird, und zwar so:
CREATE TABLE #Foo (
IDRechnung int, 'ü RechnungsNr int identity (12345,1) )
SQL-Code:
Damit habe ich optimal schnell und garantiert fortlaufend alle Rechnungsnummern erzeugt. Danach kopiere ich die Rechungsnummern in die Rechnungstabelle zurück:
insert into #Foo (IDRechnung)
select IDRechnung from Rechnungen where Status='Offen'
SQL-Code:
Zum Schluss nur noch die neue maximal Rechnungsnummer in meine Zählertabelle eintragen und fertig.
Update Rechnungen
set RechnungsNr = #Foo.RechnungsNr From #Foo Where Rechungen.RechungsNr = #Foo.RechungsNr
SQL-Code:
Update Counters Set Counter = (select max (RechnungsNr)+1 from #Foo) where cntID = 2
|
Re: Und gleich nochmal MAX(), diesmal mit MSSQL.
Hi !
Zitat:
ausserdem sind's nur ~2000 Nummern pro Jahr. Zitat:
Zwischenzeitlich folgendes:
SQL-Code:
Fehlermeldung: Prozedur gibt keine Datensätz zurück.
Alter Procedure "NewAN" (@NewOnr int Output)
As IF EXISTS (Select MAX(Nummer) FROM dbo.AN where Datum is null) begin DECLARE @Datum DateTime select @Datum = cast(GetDate() as int) select @NewOnr = max (Nummer) from dbo.AN where Datum is null UPDATE dbo.AN SET Datum = @Datum where Nummer = @NewOnr end SELECT * FROM dbo.AN where Nummer = @NewOnr Das Datum wird aber geändert. Kommentiere ich die Zeile mit dem Update aus, werden Datensätze zurückgegeben. Dann wird das Datum natürlich nicht geändert, soll aber. Was mach ich nun schon wieder falsch!? :wall: Letztstand:
SQL-Code:
Das UPDATE funktioniert, das INSERT nicht.
Alter Procedure NewAN (@NewOnr int Output)
As declare @Datum DateTime declare @MaxDt DateTime select @Datum = cast(GetDate() as int) /* nur das Datum extrahieren, Uhrzeit killen */ select @MaxDt = max(Datum) from dbo.AN /* grösstes Datum suchen */ IF Year(@Datum)<>Year(@MaxDt) /* Jahressprung ? */ begin SET @NewOnr=Year(@Datum)*10000+1 /* Erste Nummer des Jahres generieren, Format yy0001 */ INSERT dbo.AN ("Nummer", "Datum") VALUES (@NewOnr, @Datum) end ELSE IF EXISTS (Select min(Nummer) FROM dbo.AN where Datum is null) /* Lücke vorhanden ? */ begin select @NewOnr = min (Nummer) from dbo.AN where Datum is null /* Lücke auffüllen */ UPDATE dbo.AN SET Datum = @Datum where Nummer = @NewOnr end else begin select @NewOnr = max (Nummer) from dbo.AN /* letzte Nummer */ SET @NewOnr = @NewOnr + 1 /* incrementieren */ INSERT dbo.AN ("Nummer", "Datum") VALUES (@NewOnr, @Datum) end SELECT * FROM dbo.AN where Nummer = @NewOnr Gibt, nach wie vor, keine Datensätze zurück - is ja auch noch nix verändert worden. |
Re: Und gleich nochmal MAX(), diesmal mit MSSQL.
Wie rufst Du die Prozedur denn auf? Machst Du das in einer Query? Dann erwartet die natürlich irgend eine Tabelle.
Mach es mit einem TADOCommand oder einer TADOStoredProc und rufe statt Open einfach ExecProc oder Execute (oder wie das heisst) auf. Das 'blasphemisch' bezieht sich nur auf diese Prämisse: Zitat:
|
Re: Und gleich nochmal MAX(), diesmal mit MSSQL.
@alzaimar: Ich mach das mit TADOStoredProc.ExecProc
Setze ich TADOStoredProc.Active auf true, kommt die Fehlermeldung. Nochmal: Warum gibt diese StoredProcedure keine Datensätze zurück ?
SQL-Code:
:wall: Ich bräuchte einen Smiley der auf'm Schlauch steht.
Alter Procedure Test2
As update TestTable set Datum=GetDate() where Datum is null select * from TestTable |
Re: Und gleich nochmal MAX(), diesmal mit MSSQL.
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:55 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz