Dlaczego funkcja „SELECT @@ IDENTITY” zwraca liczbę dziesiętną?

24

Korzystam z Dappera, aby wykonać następujące zapytanie przeciwko wystąpieniu programu SQL Server 2008 R2 Express z aplikacji ASP.NET MVC 3 (.NET 4.0).

INSERT INTO Customers (
         Type, Name, Address, ContactName, 
         ContactNumber, ContactEmail, Supplier)
VALUES (
         @Type, @Name, @Address, @ContactName, 
         @ContactNumber, @ContactEmail, @Supplier)

SELECT @@IDENTITY

Wezwanie connection.Query<int>(sql, ...)to zgłasza wyjątek dotyczący nieprawidłowej obsady. Debugowałem go i jest to punkt, w którym Dapper wzywa GetValuezwracany SqlDataReader.

Zwracanym typem GetValuejest to Object, że sprawdzanie go w programie debuggera jest dziesiętne.

Jeśli zmienię opcję select na SELECT CAST(@@IDENTITY as int), zwracana wartość GetValue jest zapakowana w int i wyjątek nie jest zgłaszany.

Kolumna Id jest zdecydowanie typu int; Po co SELECT @@IDENTITYzwracać dziesiętne?

Niektóre dodatkowe informacje:

  • Baza danych jest nowa.
  • Tabela klientów jest jedynym obiektem, który do niej dodałem. W bazie danych nie ma innych tabel (widoków), wyzwalaczy ani procedur przechowywanych (użytkowników).
  • Baza danych zawiera 10 wierszy, tam Id to 1,2,3,4,5,6,7,8,9,10 (tj. Kolumna nie przekracza wartości int).

Moja definicja tabeli to

CREATE TABLE [dbo].[Customers](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Type] [int] NOT NULL,
    [Name] [nvarchar](255) NOT NULL,
    [Address] [nvarchar](1000) NOT NULL,
    [ContactName] [nvarchar](255) NOT NULL,
    [ContactNumber] [nvarchar](50) NOT NULL,
    [ContactEmail] [nvarchar](255) NOT NULL,
    [Supplier] [nvarchar](255) NOT NULL,
 CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (
    PAD_INDEX  = OFF, 
    STATISTICS_NORECOMPUTE  = OFF, 
    IGNORE_DUP_KEY = OFF, 
    ALLOW_ROW_LOCKS  = ON, 
    ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
Greg B.
źródło
Czy masz jakieś wyzwalacze w tabeli Klienci?
Richard
3
Użyłbym SCOPE_IDENTITY () zamiast @@ tożsamości. @@ IDENTITY da ci ostatnią wartość tożsamości utworzoną przez cokolwiek w bieżącym połączeniu, w przeciwieństwie do twojego obecnego zakresu. Tak jak zasugerował Richard, wyzwalacz modyfikujący inną tabelę i generujący tożsamość wpłynąłby na zwrot @@ IDENTITY.
Nick Chammas,
W bazie danych nie ma żadnych wyzwalaczy. To świeża baza danych, a tabela Klienci to jedyna tabela, którą utworzyłem.
Greg B,
@Greg B: jest to typ zwracany przez funkcję. Czy spodziewałeś się int / bigint jako typu zwrotu (jak sugeruje to pytanie) czy kwestionujesz wybór MS dla tej funkcji?
Marian,

Odpowiedzi:

28
  1. @@ tożsamość zwraca wartość liczbową (38,0) . Musisz rzucić go, aby dostać się do int.

    WYBIERZ CAST (@@ tożsamość AS INT)

  2. Spróbuj też zamiast tego użyć scope_identity. Jeśli masz jakieś wyzwalacze w tabeli Klientów, możesz w końcu uzyskać ostatnią tożsamość z innej tabeli.

  3. Wreszcie, ponieważ używasz eleganckiego , będziesz chciał zawinąć to wszystko w procedurę składowaną, aby zagwarantować wykonanie wstawienia, a następnie zaznaczenia tożsamości w tej samej partii.

    Teoretycznie większość czasu powinno działać samodzielnie. Ale mogą pojawić się problemy, jeśli musisz dwukrotnie przejść do bazy danych. (Np. Jak to działa z pulą połączeń? A co z porzuconymi połączeniami? Itd.) Jeśli po prostu rzucisz to wszystko w procedurę składowaną, nie będziesz musiał się martwić o dodatkowy wysiłek na drodze.

Richard
źródło
Dzięki za # 3. Czy nie ma sposobu na zdefiniowanie partii w adhocowej instrukcji SQL?
Greg B,
Spojrzałem na to jeszcze raz. Jeśli dołączysz wszystkie wyciągi w jednym wywołaniu, będzie to jedna partia. Jeśli podzielisz oświadczenia na osobne wywołania, sprawy mogą się popsuć.
Richard
3
+1 za polecanie SCOPE_IDENTITY ()
Andrew Bickerton
10

Utwórz tabelę mówi:

TOŻSAMOŚĆ

Wskazuje, że nowa kolumna jest kolumną tożsamości. Po dodaniu nowego wiersza do tabeli Microsoft SQL Server ™ zapewnia unikalną, przyrostową wartość dla kolumny. Kolumny tożsamości są powszechnie używane w połączeniu z ograniczeniami PIERWOTNEGO KLUCZA, aby służyć jako unikalny identyfikator wiersza dla tabeli. Właściwość TOŻSAMOŚĆ można przypisać do kolumn tinyint, smallint, int, bigint, dziesiętnych (p, 0) lub liczbowych (p, 0). Dla jednej tabeli można utworzyć tylko jedną kolumnę tożsamości. Domyślne ograniczenia i ograniczenia DOMYŚLNE nie mogą być używane z kolumną tożsamości. Musisz podać zarówno ziarno, jak i przyrost, albo żadne. Jeśli nie podano żadnego z nich, wartością domyślną jest (1,1).

nasionko

Jest wartością używaną dla pierwszego wiersza załadowanego do tabeli.

przyrost

Czy załadowano wartość przyrostową dodaną do wartości tożsamości poprzedniego wiersza. ”

Tak więc funkcja systemowa @@ tożsamość będzie musiała poradzić sobie z najbardziej zakrywającym typem.

Marian
źródło
I dlatego powraca, numericponieważ ma najszerszy zasięg ..? Dzięki
Greg B
3
Funkcja nie może mieć więcej niż jednego typu zwracanego. Będzie musiał użyć najszerszego typu, aby uwzględnić każdą możliwość.
Marian
6

„Dlaczego SELECT @@ TOŻSAMOŚĆ zwraca dziesiętne”

Ponieważ może być zbyt duży, aby zmieścił się w int- nie pasuje do typu kolumny tożsamości, ale jak mówi Richard zwraca liczbę (38,0) ( numerici decimal są synonimami )

Jack Douglas
źródło