为什么`SELECT @@IDENTITY` 返回一个小数?

Gre*_*g B 24 sql-server ado.net t-sql

我正在使用Dapper对来自 ASP.NET MVC 3 (.NET 4.0) 应用程序的 SQL Server 2008 R2 Express 实例执行以下查询。

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

SELECT @@IDENTITY
Run Code Online (Sandbox Code Playgroud)

对 的调用connection.Query<int>(sql, ...)正在引发无效的强制转换异常。我已经调试了它,它是在 Dapper 调用GetValue返回的SqlDataReader.

的返回类型GetValueObject,在调试器中检查它显示它是一个装箱十进制。

如果我将选择更改为SELECT CAST(@@IDENTITY as int),则 GetValue 的返回是一个装箱的 int 并且不会引发异常。

Id 列绝对是 int 类型;为什么会SELECT @@IDENTITY返回一个小数?

一些附加信息:

  • 数据库是全新的。
  • 客户表是我添加到其中的唯一对象。数据库中没有其他(用户)表、视图、触发器或存储过程。
  • 数据库中有 10 行,Id 为 1,2,3,4,5,6,7,8,9,10(即该列不超出 int 的限制)。

我的表定义是

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]
Run Code Online (Sandbox Code Playgroud)

Ric*_*ard 29

  1. @@identity 返回一个 numeric(38,0)。您需要将其转换为 int。

    SELECT CAST(@@identity AS INT)

  2. 另外,请尝试改用 scope_identity。如果客户表上有任何触发器,则最终可能会从另一个表中获取最后一个标识。

  3. 最后,由于您使用的是dapper,您需要将所有这些都包装在一个存储过程中,以便保证在同一批次中执行插入,然后对标识执行选择。

    从理论上讲,在大多数情况下,它们都应该单独执行。但是,如果您必须两次访问数据库,则可能会出现问题。(例如,这如何与连接池一起工作?断开的连接呢?等等)如果您只是将其全部放在存储过程中,您将不必担心在路上进行额外的工作。

  • +1 推荐 SCOPE_IDENTITY() (3认同)

Mar*_*ian 10

创建表说:

"身份

指示新列是标识列。向表中添加新行时,Microsoft® SQL Server™ 会为该列提供唯一的增量值。标识列通常与 PRIMARY KEY 约束结合使用,作为表的唯一行标识符。IDENTITY 属性可以分配给 tinyint、smallint、int、bigint、decimal(p,0) 或 numeric(p,0) 列。每个表只能创建一个标识列。绑定默认值和 DEFAULT 约束不能与标识列一起使用。您必须同时指定种子和增量,或者两者都不指定。如果两者均未指定,则默认值为 (1,1)。

种子

是用于加载到表中的第一行的值。

增量

添加到加载的前一行的标识值的增量值。”

所以系统函数@@identity 将不得不处理覆盖最多的类型。

  • 一个函数不能有多个返回类型。它必须使用最宽的类型来包含所有可能性。 (3认同)

Jac*_*las 6

“为什么 SELECT @@IDENTITY 会返回一个小数”

因为它可能太大而无法放入int- 它与标识列的类型不匹配,但正如 Richard 所说返回 numeric(38,0) (numeric并且decimal 是同义词