Tại sao `SELECT @@ IDENTITY` trả về số thập phân?


24

Tôi đang sử dụng Dapper để thực hiện truy vấn sau đối với phiên bản SQL Server 2008 R2 Express từ ứng dụng 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

Cuộc gọi đến connection.Query<int>(sql, ...)đang ném Ngoại lệ không hợp lệ. Tôi đã gỡ lỗi nó và đó là lúc Dapper gọi GetValuelại SqlDataReader.

Kiểu trả về GetValueObject, kiểm tra nó trong trình gỡ lỗi hiển thị đó là số thập phân được đóng hộp.

Nếu tôi thay đổi lựa chọn thành SELECT CAST(@@IDENTITY as int), sự trở lại của GetValue là một int được đóng hộp và ngoại lệ không bị ném.

Cột Id chắc chắn là kiểu int; Tại sao sẽ SELECT @@IDENTITYtrả lại một số thập phân?

Một số thông tin bổ sung:

  • Cơ sở dữ liệu là thương hiệu mới.
  • Bảng Khách hàng là đối tượng duy nhất tôi đã thêm vào nó. Không có bảng (người dùng), khung nhìn, trình kích hoạt hoặc thủ tục được lưu trữ nào trong cơ sở dữ liệu.
  • Có 10 hàng trong cơ sở dữ liệu, có Id là 1,2,3,4,5,6,7,8,9,10 (tức là cột không vượt quá giới hạn của một int).

Định nghĩa bảng của tôi là

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]

Bạn có bất kỳ kích hoạt trên bảng Khách hàng?
Richard

3
Tôi sẽ sử dụng SCOPE_IDENTITY () thay vì @@ IDENTITY. @@ IDENTITY sẽ cung cấp cho bạn giá trị nhận dạng cuối cùng được tạo bởi bất kỳ thứ gì trên kết nối hiện tại, trái ngược với phạm vi hiện tại của bạn. Vì vậy, như Richard đề xuất, một trình kích hoạt sửa đổi một bảng khác và tạo một danh tính sẽ ảnh hưởng đến sự trở lại của @@ IDENTITY.
Nick Chammas

Không có kích hoạt trong DB. Đó là một cơ sở dữ liệu mới và bảng Khách hàng là bảng duy nhất tôi đã tạo.
Greg B

@Greg B: đây là kiểu trả về của hàm. Bạn có mong đợi int / bigint là kiểu trả về (như câu hỏi gợi ý) hoặc bạn đang đặt câu hỏi cho sự lựa chọn MS cho chức năng này?
Mary

Câu trả lời:


28
  1. @@ danh tính trả về một số (38,0) . Bạn sẽ cần bỏ nó để đưa nó đến một int.

    CHỌN CAST (@@ danh tính NHƯ INT)

  2. Ngoài ra, hãy thử sử dụng scope_identity thay thế. Nếu bạn có bất kỳ kích hoạt nào trên bảng Khách hàng, cuối cùng bạn có thể nhận được danh tính cuối cùng từ một bảng khác.

  3. Cuối cùng, vì bạn đang sử dụng dapper , bạn sẽ muốn bọc tất cả những thứ đó trong một thủ tục được lưu trữ để bạn được đảm bảo thực hiện thao tác chèn và sau đó chọn vào danh tính trong cùng một lô.

    Về mặt lý thuyết, nó nên hoạt động hầu hết thời gian để tự mình thực hiện cả hai thứ đó. Nhưng vấn đề có thể phát sinh nếu bạn phải đi đến cơ sở dữ liệu hai lần. (Ví dụ: cách thức này hoạt động với nhóm kết nối? Điều gì về các kết nối bị mất? V.v.) Nếu bạn chỉ cần ném tất cả vào một thủ tục được lưu trữ, bạn sẽ không phải lo lắng về nỗ lực thêm đó.


Cảm ơn # 3. Có cách nào để xác định một lô trong câu lệnh SQL adhoc không?
Greg B

Tôi đã có một cái nhìn khác về nó. Nếu bạn bao gồm tất cả các câu lệnh trong một cuộc gọi, thì đó là tất cả một đợt. Nếu bạn chia các câu lệnh thành các cuộc gọi riêng biệt, mọi thứ có thể bị lỗi.
Richard

3
+1 để giới thiệu SCOPE_IDENTITY ()
Andrew Bickerton

10

Tạo bảng cho biết:

" SẮC

Cho biết cột mới là cột nhận dạng. Khi một hàng mới được thêm vào bảng, Microsoft® SQL Server ™ cung cấp một giá trị gia tăng duy nhất cho cột. Các cột định danh thường được sử dụng cùng với các ràng buộc PRIMARY KEY để đóng vai trò là định danh hàng duy nhất cho bảng. Thuộc tính IDENTITY có thể được gán cho các cột tinyint, smallint, int, bigint, binary (p, 0) hoặc số (p, 0). Chỉ có một cột nhận dạng có thể được tạo trên mỗi bảng. Mặc định giới hạn và ràng buộc DEFAULT không thể được sử dụng với một cột định danh. Bạn phải chỉ định cả hạt giống và gia tăng hoặc không. Nếu không được chỉ định, mặc định là (1,1).

hạt giống

Là giá trị được sử dụng cho hàng đầu tiên được tải vào bảng.

tăng

Là giá trị gia tăng được thêm vào giá trị nhận dạng của hàng trước đó được tải. "

Vì vậy, chức năng hệ thống @@ nhận dạng sẽ phải đối phó với loại bao phủ nhất.


Và đây là lý do tại sao nó trở lại numerickhi nó có phạm vi rộng nhất ..? Cảm ơn
Greg B

3
Một hàm không thể có nhiều hơn một kiểu trả về. Nó sẽ phải sử dụng loại rộng nhất để bao gồm mọi khả năng.
Mary

6

"Tại sao CHỌN @@ IDENTITY trả về số thập phân"

Bởi vì nó có thể quá lớn để phù hợp với một int- nó không khớp với loại cột nhận dạng nhưng như Richard nói trả về một số (38,0) ( numericdecimal là từ đồng nghĩa )

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.