Benutzer mit den meisten Antworten
Hochzählen per gespeicherter Prozedur

Frage
-
Hi,
ich möchte, dass beim ausführen einer gespeicherten Prozedur ein Tabellenwert um eins (1) erhöht wird.
Hier mein Ansatz:
ALTER procedure [dbo].[web_Autopilotaktiv] @kundenId int, @neuesDatum date, @Text nvarchar(max) as declare @Zaehler int = (SELECT AutopilotStatus From Kundenliste Where ID_Kunde = @kundenId) UPDATE Kundenliste SET Nachverfolgung = @neuesDatum, AutopilotStatus = convert(int,@Zaehler) + 1 Where ID_Kunde = @kundenId
Die Tabellenspalte AutopilotStatus ist eine INT Spalte. Das Problem ist, dass maximal bis zur Nummer zwei hochgezählt wird. Ab einem Wert von zwei bleibt es bei zwei. Besitzt AutopilotStatus den Wert 3, wird der Wert bei Ausführung sogar auf zwei herabgestuft...
Im Vorfeld hatte ich es auch schon probiert mit:
SET Nachverfolgung = @neuesDatum, AutopilotStatus = AutopilotStatus + 1
Kann mir jemand dieses Verhalten erklären und Abhilfe schaffen?
.::datekk::.
Antworten
-
Hi,
ich kann das nicht reproduzieren. Hier mal ein funktionierendes Beispiel mit einer Tabellenvariablen.
DECLARE @Kunden TABLE ( ID_Kunde int, AutopilotStatus int, Nachverfolgung date ) INSERT INTO @Kunden ( ID_Kunde, AutopilotStatus ) VALUES ( 1, 3 ), ( 2, 49 ), ( 3, 101 ) DECLARE @KundenId int = 3; DECLARE @Zaehler int = ( SELECT AutopilotStatus From @Kunden Where ID_Kunde = @KundenId ); UPDATE @Kunden SET Nachverfolgung = GETDATE(), AutopilotStatus = CONVERT( int, @Zaehler ) + 1 WHERE ID_Kunde = @kundenId SELECT * FROM @Kunden
Auch die andere Variante klappt problemlos:
DECLARE @Kunden TABLE ( ID_Kunde int, AutopilotStatus int, Nachverfolgung date ) INSERT INTO @Kunden ( ID_Kunde, AutopilotStatus ) VALUES ( 1, 3 ), ( 2, 49 ), ( 3, 101 ) DECLARE @KundenId int = 1; UPDATE @Kunden SET Nachverfolgung = GETDATE(), AutopilotStatus = AutopilotStatus + 1 WHERE ID_Kunde = @kundenId UPDATE @Kunden SET Nachverfolgung = GETDATE(), AutopilotStatus = AutopilotStatus + 1 WHERE ID_Kunde = @kundenId UPDATE @Kunden SET Nachverfolgung = GETDATE(), AutopilotStatus = AutopilotStatus + 1 WHERE ID_Kunde = @kundenId SELECT * FROM @Kunden
Poste bitte mal deine Tabellendefinition als CREATE TABLE Statement und schreib bitte die genaue Versionsnummer deiner SQL Server Instanz (SELECT @@VERSION) dabei.
Ich tippe auf einen Trigger, der den Wert wieder runtersetzt, wenn größer 2 oder evtl. einen Check Constraint, der Werte > 2 verhindert.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport
- Bearbeitet Stefan FalzModerator Freitag, 7. Juni 2019 08:16
- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 11. Juni 2019 06:11
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Freitag, 28. Juni 2019 13:17
-
Hallo Datekk,
warum so kompliziert und nicht in einem Statement. Deine Lösung kann bei hoher Concurrency zu falschen Ergebnissen führen. Wenn Prozess 1 die Prozedur ausführt und die ersten Anweisung gelesen hat (aber noch nicht geschrieben hat!), kommt Prozess 2 und liest genau den gleichen Wert. Somit hast Du eigentlich 2 Updates - es wird aber nur ein Update gezählt.
Entweder Du serialisierst den Prozess (würde ich aber nicht machen) oder aber Du kombinierst das Update in einem Statement:
CREATE TABLE dbo.Customers ( Id INT NOT NULL IDENTITY (1, 1) PRIMARY KEY CLUSTERED, Name VARCHAR(255) NOT NULL, AutoPilot INT NOT NULL DEFAULT (1) ); GO -- Ein paar Daten eintragen ... -- UPDATE-Statement UPDATE dbo.Customers SET Name = 'Test', AutoPilot = AutoPilot + 1 WHERE Id = 10; GO
Uwe Ricken (Blog | Twitter)
Microsoft Certiied Master - SQL Server 2008
Microsoft Certified Solution Master - CHARTER Data Platform
Microsoft Certified Solution Expert - Data Platform
db Berater GmbH
Microsoft SQL Server Blog (german only)- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Donnerstag, 20. Juni 2019 13:34
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Freitag, 28. Juni 2019 13:17
-
Ich habe den Fehler tatsächlich in meiner Anwendung gefunden. Die Proc wurde vom Programm aufgerufen, davor wurde aber AutopilotStatus auf 1 gesetzt....
.::datekk::.
- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 11. Juni 2019 06:11
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Freitag, 28. Juni 2019 13:17
Alle Antworten
-
Hi,
ich kann das nicht reproduzieren. Hier mal ein funktionierendes Beispiel mit einer Tabellenvariablen.
DECLARE @Kunden TABLE ( ID_Kunde int, AutopilotStatus int, Nachverfolgung date ) INSERT INTO @Kunden ( ID_Kunde, AutopilotStatus ) VALUES ( 1, 3 ), ( 2, 49 ), ( 3, 101 ) DECLARE @KundenId int = 3; DECLARE @Zaehler int = ( SELECT AutopilotStatus From @Kunden Where ID_Kunde = @KundenId ); UPDATE @Kunden SET Nachverfolgung = GETDATE(), AutopilotStatus = CONVERT( int, @Zaehler ) + 1 WHERE ID_Kunde = @kundenId SELECT * FROM @Kunden
Auch die andere Variante klappt problemlos:
DECLARE @Kunden TABLE ( ID_Kunde int, AutopilotStatus int, Nachverfolgung date ) INSERT INTO @Kunden ( ID_Kunde, AutopilotStatus ) VALUES ( 1, 3 ), ( 2, 49 ), ( 3, 101 ) DECLARE @KundenId int = 1; UPDATE @Kunden SET Nachverfolgung = GETDATE(), AutopilotStatus = AutopilotStatus + 1 WHERE ID_Kunde = @kundenId UPDATE @Kunden SET Nachverfolgung = GETDATE(), AutopilotStatus = AutopilotStatus + 1 WHERE ID_Kunde = @kundenId UPDATE @Kunden SET Nachverfolgung = GETDATE(), AutopilotStatus = AutopilotStatus + 1 WHERE ID_Kunde = @kundenId SELECT * FROM @Kunden
Poste bitte mal deine Tabellendefinition als CREATE TABLE Statement und schreib bitte die genaue Versionsnummer deiner SQL Server Instanz (SELECT @@VERSION) dabei.
Ich tippe auf einen Trigger, der den Wert wieder runtersetzt, wenn größer 2 oder evtl. einen Check Constraint, der Werte > 2 verhindert.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport
- Bearbeitet Stefan FalzModerator Freitag, 7. Juni 2019 08:16
- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 11. Juni 2019 06:11
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Freitag, 28. Juni 2019 13:17
-
Ich habe den Fehler tatsächlich in meiner Anwendung gefunden. Die Proc wurde vom Programm aufgerufen, davor wurde aber AutopilotStatus auf 1 gesetzt....
.::datekk::.
- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 11. Juni 2019 06:11
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Freitag, 28. Juni 2019 13:17
-
Hallo Datekk,
warum so kompliziert und nicht in einem Statement. Deine Lösung kann bei hoher Concurrency zu falschen Ergebnissen führen. Wenn Prozess 1 die Prozedur ausführt und die ersten Anweisung gelesen hat (aber noch nicht geschrieben hat!), kommt Prozess 2 und liest genau den gleichen Wert. Somit hast Du eigentlich 2 Updates - es wird aber nur ein Update gezählt.
Entweder Du serialisierst den Prozess (würde ich aber nicht machen) oder aber Du kombinierst das Update in einem Statement:
CREATE TABLE dbo.Customers ( Id INT NOT NULL IDENTITY (1, 1) PRIMARY KEY CLUSTERED, Name VARCHAR(255) NOT NULL, AutoPilot INT NOT NULL DEFAULT (1) ); GO -- Ein paar Daten eintragen ... -- UPDATE-Statement UPDATE dbo.Customers SET Name = 'Test', AutoPilot = AutoPilot + 1 WHERE Id = 10; GO
Uwe Ricken (Blog | Twitter)
Microsoft Certiied Master - SQL Server 2008
Microsoft Certified Solution Master - CHARTER Data Platform
Microsoft Certified Solution Expert - Data Platform
db Berater GmbH
Microsoft SQL Server Blog (german only)- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Donnerstag, 20. Juni 2019 13:34
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Freitag, 28. Juni 2019 13:17