2016-03-28 3 views
1

ich eine einfache SQL-Anweisung eine Tabelle wie folgt zu erstellen:SQL Server Transaktion erfolgreich falsch Id

Create table tblAccountBalance 
(
    Id int, 
    AccountName nvarchar(200), 
    Balance int 
) 

insert into tblAccountBalance values (1, 'Mark', 1000); 
insert into tblAccountBalance values (2, 'Mary', 1000); 

in Resultierende

Id AccountName Balance 
----------------------- 
1 Mark  1000 
2 Mary  1000 

Dann erstelle ich eine Transaktion wie folgt aus:

begin try 
    begin transaction -- must have transaction keyword here! 
     update tblAccountBalance 
     set Balance = Balance - 100 
     where Id = 1 

     update tblAccountBalance 
     set Balance = Balance + 100 
     where Id = 2 

     commit transaction --or simply commit, but by default, it is commit WORK - thus you cannot specify transaction name, best is to put transaction 
     print 'Transaction successful!' 
end try 
begin catch 
    rollback transaction --or simply rollback, but again, it might be similar to transaction, best is to put transaction keyword 
    print 'Transaction is rolled back!' 
end catch 

Die, wenn ausgeführt, überträgt einfach 100 Einheiten Geld von Mark zu Mary:

Id AccountName Balance 
----------------------- 
1 Mark  900 
2 Mary  1100 

nun aus der oben fort - aktualisiert - Tabelle, Fehler in der Transaktion einzuführen, ändere ich die Transaktion, um die zweite Update-Anweisung nvarchar als Id wie dies mit zu machen:

begin try 
    begin transaction 
     update tblAccountBalance 
     set Balance = Balance - 100 
     where Id = 1 

     update tblAccountBalance 
     set Balance = Balance + 100 
     where Id = '24' -- note the Id here is changed 

     commit transaction 
     print 'Transaction successful!' 
end try 
begin catch 
    rollback transaction 
    print 'Transaction is rolled back!' 
end catch 

Zu meinem Überraschung, die obige Abfrage führt zu:

(1 row(s) affected) 
(0 row(s) affected) 
Transaction successful! 

Id AccountName Balance 
----------------------- 
1 Mark  800 
2 Mary  1100 

Welches ist nicht das gewünschte Ergebnis.

Aber dann, wenn ich von der unerwünschten aktualisierte Tabelle Ergebnis oben mit einer modifizierten Transaktion (wiederum in der zweiten Update Id) so weiter weiter:

begin try 
    begin transaction 
     update tblAccountBalance 
     set Balance = Balance - 100 
     where Id = 1 

     update tblAccountBalance 
     set Balance = Balance + 100 
     where Id = 'A24'  -- note the Id here is changed 

     commit transaction 
     print 'Transaction successful!' 
end try 
begin catch 
    rollback transaction 
    print 'Transaction is rolled back!' 
end catch 

Daraus ergibt sich:

(1 row(s) affected) 
(0 row(s) affected) 
Transaction is rolled back! 

Id AccountName Balance 
------------------------ 
1 Mark  800 
2 Mary  1100 

Welches ist mein gewünschtes Ergebnis. Was stimmt nicht mit der zweiten Transaktion? Warum wird das Update noch ausgeführt?

Ich verwende SQL Server 2014, wenn das von Bedeutung ist.

Antwort

3

Es ist, weil Ihr zweites Experiment tatsächlich erfolgreich ist und ausgeführt wird. Wenn eine Operation zwei verschiedene Datentypen vergleicht, führt SQL Server eine implizite Konvertierung durch. Weitere Informationen finden Sie unter Data Type Precedence. Es gibt also eine Umwandlung von id = '24' in int, so dass es schließlich id = 24 wird. Daher wird das Experiment das Guthaben von Mark abziehen und das Guthaben des Datensatzes mit id = 24 hinzufügen, aber da es keinen Datensatz mit dieser ID gibt, ändert sich nichts.

In Ihrem dritten Experiment schlägt die implizite Konvertierung fehl (A24 kann nicht in Ganzzahltyp konvertiert werden) und die Transaktion wird schließlich zurückgesetzt.

+0

Oh mein .. Ich habe es falsch wegen der impliziten Konvertierung. Danke für Ihre Erklärung. – Ian

+1

Danke für Ihre Antwort. Es ist identisch mit anderen, aber Sie sind der erste, der antwortet und einen Verweis auf die Priorität des MSDN-Datentyps hat. – Ian

1

Ihre zweite Transaktion ist erfolgreich, deshalb wurde die UPDATE noch ausgeführt. Die UPDATE Anweisung, die Sie geändert:

update tblAccountBalance set Balance = Balance + 100 where Id = '24' --note the Id here is changed 

verursachte keine Fehler. Es gab einfach keine Zeilen mit Id = '24' zurück, aber ohne Fehler.

Ihre dritte Transaktion führte zu einem Fehler, weshalb die UPDATE zurückgesetzt wird.

update tblAccountBalance set Balance = Balance + 100 where Id = 'A24' --note the Id here is changed 

Die oben wird so zu einem Fehler führen:

Fehler bei der Konvertierung, wenn der VARCHAR Wert 'A24' in dem Datentyp int umgewandelt wird.

Da Ihr Id ist INT, versucht SQL Server A24 zu konvertieren, die VARCHAR zu INT ist aber nicht so und so den Fehler zu tun.

+0

Oh mein .. Ich habe es falsch wegen der impliziten Konvertierung. Danke für Ihre Erklärung. – Ian

1

Ihr zweites Experiment war erfolgreich, weil implizit in int konvertiert werden kann. Die Zeichenfolge '24' kann in den Ganzzahlwert 24 konvertiert werden. Siehe Implicit Conversions.

+0

Oh mein .. Ich habe es falsch wegen der impliziten Konvertierung. Danke für Ihre Erklärung. – Ian

Verwandte Themen