SQL Server 2008-Problem mit SCOPE_IDENTITY()
Mein code nicht aktualisieren Sie die thread-Feld. Es ist null. Jemand irgendwelche Ideen?
INSERT INTO [Messages]([Sender], [Receiver], [Job_Number], [Subject], [MessageText], [DateSent])
VALUES(@Sender, @Receiver, @Job_Number, @Subject, @MessageText, @DateSent)
SET @ThreadID = SCOPE_IDENTITY()
UPDATE [Messages]
SET Thread = @ThreadID
WHERE MessageID = @ThreadID
EDIT:
Es scheint die UPDATE-routine wird nicht ausgeführt, an alle. Ich auch Hinzugefügt, den folgenden code an das Ende der sproc, aber nichts wird aktualisiert.
UPDATE Comments
SET SomeField = @ThreadID
where SCID = 33
EDIT:
/****** Object: Table [dbo].[Messages] Script Date: 04/09/2010 12:08:55 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Messages](
[MessageID] [int] IDENTITY(1,1) NOT NULL,
[Sender] [varchar](30) NOT NULL,
[Receiver] [varchar](30) NOT NULL,
[Job_Number] [varchar](20) NULL,
[Subject] [varchar](200) NULL,
[MessageText] [varchar](max) NULL,
[DateSent] [datetime] NULL,
[Thread] [int] NULL,
CONSTRAINT [PK_Messages] PRIMARY KEY CLUSTERED
(
[MessageID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Messages] ADD CONSTRAINT [DF_Messages_DateSent] DEFAULT (getdate()) FOR [DateSent]
GO
EDIT:
Wenn ich die gespeicherte Prozedur ausführen von Management Studio das update funktioniert einwandfrei. Das problem ist das in meiner app, wenn ich es nennen mit SQLHelper:
SqlHelper.ExecuteNonQuery(ConfigurationManager.ConnectionStrings["Conn"].ConnectionString,
"spMessagesInsert",
0,
message.Sender,
message.Receiver,
message.Job_Number,
message.Subject,
message.MessageText,
message.DateSent
);
EDIT: Schließlich änderte ich das Programm code zum aufrufen der gespeicherten Prozedur mithilfe von Linq-to-sql anstelle von SqlHelper. Dies schien das Problem zu beheben.
- Sind Sie sicher, dass es eine identity-Spalte angegeben, die auf der Nachrichten-Tabelle?
- Ja auf jeden Fall.
- Dann sind Sie sicher, dass der INSERT erfolgreich ist? Möchten Sie vielleicht, um Fehler zu überprüfen oder überprüfen
@@ROWCOUNT
zu sehen, ob es tatsächlich einsetzen, würde alles, was updateSCOPE_IDENTITY
- Es gibt keine Trigger im Spiel zu löschen und das Einfügen erfolgreich ist. Ich sehe die Zeile eingefügt wird.
- Genauer gesagt, ist die MessageID der identity-Spalte? Im moment sieht es aus wie Sie sind, kopieren Sie die neue ID in eine andere Spalte (Thread) in der gleichen Zeile, das sinnlos scheint.
- Ja, MessageID ist die Identity-Spalte. Ich mache das, um die Nachrichten der Gruppe - es ist nicht sinnlos.
- Können Sie nach Ihren genauen scripted DDL für die Tabelle?
- Doch wie kann man die Nachrichten der Gruppe, wenn es auf der Grundlage der Tabelle die eindeutige ID-Spalte und daher ist einzigartig für jede Nachricht? +1 für den DDL
- Was bekommen Sie, wenn Sie "Select @ThreadId" gleich nachdem du es auf
SCOPE_IDENTITY
? Wenn Sie einen Wert, was Sie bekommen, wenn Sie die Abfrage für die es (d.h. Select * From Messages Where MessageId = @ThreadId). - Ich benutze es, um die Nachrichten der Gruppe, wenn mehrere Zeilen haben die gleiche ThreadID (das ist wirklich die messageID der ersten Zeile). Bitte hört auf zu Fragen über die Gültigkeit, wie es ist neben dem Punkt.
- Tun die Deklarationen für @Sender @Receiver @Jobnummer, @Thema, @Nachrichtentext und @DateSent denen entsprechen, die für die Struktur der Tabelle? Es sieht jetzt aus wie eventuell ein Fehler in der INSERT verursacht, der rest nicht zu laufen. 30 Zeichen scheint Recht kurz für Sender und Empfänger
- Ah, jetzt bekomme ich die Gruppierung 🙂
- Die Erklärungen alle übereinstimmen. Die insert-Anweisung erfolgreich ausgeführt wird, jedes mal. 30 char max ist in Ordnung - kein abschneiden von Daten geschieht.
- Ist der erste Teil laufen alle innerhalb einer gespeicherten Prozedur? Beginnt Sie mit SET NoCount On?
- Es ist alles ein Geschäft, proc.
- Der plot verdickt. Ok, also die SQL-code ordnungsgemäß funktioniert. Ist Ihr Aufruf von ExecuteNonQuery-eingewickelt in eine Transaktion oder ein TransactionScope-das wird immer zurückgesetzt?
- Hmm, Clutching at straws ein bisschen hier, aber es könnte nicht eine weitere Kopie von spMessagesInsert in einem anderen schema als dbo?
- keine transactioning. Ich wünschte, es war so einfach.
- Führen Sie SQL Profiler. Es wird sich zeigen, ob Sie noch etwas anderes aktualisieren, der Aufzeichnung oder, wenn für eine Transaktion ein Rollback ausgeführt werden (inklusive Rollback Tran abgeschlossen).
- Ich bin sicher, es gibt keine andere Kopie der sproc anderswo.
- Ich, die zweite Thomas-profiler Vorschlag. Hoffentlich etwas wird klar werden, wenn man sich die Spur.
- Ablaufverfolgung jetzt. Ja, wenn ich meinen code mit SqlHelper, wird der Datensatz eingefügt wird erfolgreich, aber der Thread-Spalte ist null.
- Wenn das der Fall ist, dann, was Sie wahrscheinlich suchen, ist etwas anderes schreiben eine null in dieser Spalte.
- keine Transaktion, kein rollback, keine Aktualisierung des Feldes auf null, wird keine Aktualisierung des thread-Bereich an allen... 🙁
- Mit SQL Profiler, Sie sollten in der Lage sein wählen Sie die Anweisungen, die ausgeführt wurden, das kompilieren wird Ihnen in der unteren Hälfte des Bildschirms. Kopieren Sie und fügen Sie Sie in Management Studio. Dies wird Ihnen ermöglichen, zu injizieren und Debuggen von code in Ergebnisse um zu testen, für den Thread-Spalte.
- Das problem ist die Update-Abfragen nicht gefunden werden in der Profiler!
- Es ist wohl nur zu zeigen, den Aufruf einer gespeicherten Prozedur. Im profiler, klicken Sie auf ""Alle Ereignisse Anzeigen" und achten Sie darauf, dass
SQL:StmtCompleted
ausgewählt ist. Dies sollte zeigen Sie alle Schritte ausgeführt, einschließlich derjenigen innerhalb der stored procs. - OK, es kann nichts falsch mit dem code (loosk vernünftig!) und es ist die SCOPE_IDENTITY/Parallelität bug. Siehe meine Antwort bitte
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gibt es nur eine Handvoll von Möglichkeiten, wenn wir davon ausgehen, dass keine Fehler vorhanden sind:
Set @ThreadId = SCOPE_IDENTITY()
@@TRANCOUNT
vor und nach der Update-Anweisung.@@ROWCOUNT
direkt nach der Update-Anweisung. Wenn er null ist, dann bleibt nur die Möglichkeit, dass der Datensatz nicht mehr existiert. Wenn es 1 ist, dann ist klar, dass die Aktualisierung erfolgreich war. Direkt nach der Update-Anweisung, Sie sollten in der Lage sein zu rufenSelect * From Messages Where MessageId = @ThreadId And Thread Is Not Null
- und ein Rekord. Das heißt, wenn später in Ihrem code die Null ist wieder etwas anderes hatte Sie verändert.Versuchen Sie Folgendes:
BEARBEITEN
Eine andere ungemein hilfreiches Werkzeug bei der Beseitigung dieser Art von Problemen ist die SQL Server Profiler. Zum Beispiel, können Sie sagen, es zu zeigen
Rollback Tran completed
oderCommit Tran completed
Veranstaltungen zusammen mit den anderen SQL-Anweisungen und sehen, ob etwas rollt die Transaktion zurück.Könnte man unglücklich ist und auf den (in)berühmten Identität/Parallelität bug gemeldet auf MS Connect, die jetzt einen KB-Artikel zu auf SQL Server 2005 und 2008.
Ist, ist der zurückgegebene Wert für SCOPE_IDENTITY ist falsch. Der code OK Aussehen, und viele Leute haben schon einen Blick auf Sie, also was ist, wenn der Wert falsch ist? Dies würde die gleichen Symptome wie du berichtest.
Versuchen
OPTION (MAXDOP 1)
auf die legen Sie wie vorgeschlagen in den ArtikelIch habe gesehen, das passiert mir selbst, dass es nicht Abstrakt oder selten.
Überprüfen Sie die Nachrichten, die Tabelle für Trigger.
Tut es das drucken, was Sie erwarten?
Ich habe das exakt gleiche problem vor. Die Lösung war, um auf NOCOUNT an der Spitze der gespeicherten Prozedur-code (vorausgesetzt es verursacht keine unerwünschten Nebenwirkungen für Sie):
SET NOCOUNT ON
Alternativ können Sie set nocount on von SQLHelper für die Verbindung Ihres mit.
Habe ich nicht alle details darüber, warum das funktionierte, andere, als wenn nocount off (ie. Zeilen gezählt werden) scheint es so zu "verwirren" die folgende update-Anweisung (wenn ich weitere details werde ich update meine Antwort später). Die gleiche Sache, die Sie beschreiben passiert...die folgende UPDATE-Anweisung nie ausgeführt, und noch mehr, die gespeicherte Prozedur unerwartet beendet (basierend auf dem, was aufgezeichnet wurde, in die SQL-Profiler).