Почему `SELECT @@ IDENTITY` возвращает десятичную дробь?

24

Я использую Dapper для выполнения следующего запроса к экземпляру SQL Server 2008 R2 Express из приложения 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

Призыв connection.Query<int>(sql, ...)вызывает недопустимое исключение приведения. Я отладил это, и это в тот момент, когда Даппер звонит GetValueвозвращенным SqlDataReader.

Тип возвращаемого значения GetValue- Objectпроверка его в шоу отладчика - это десятичное число в штучной упаковке.

Если я изменяю выбор на SELECT CAST(@@IDENTITY as int), возвращаемое значение GetValue представляет собой упакованный int, и исключение не выдается.

Столбец Id определенно имеет тип int; Зачем SELECT @@IDENTITYвозвращать десятичную?

Некоторая дополнительная информация:

  • База данных совершенно новая.
  • Таблица Customers - это единственный объект, который я добавил к нему. В базе данных нет других (пользовательских) таблиц, представлений, триггеров или хранимых процедур.
  • В базе данных 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]
Грег Б
источник
Есть ли у вас какие-либо триггеры на столе клиентов?
Ричард
3
Я бы использовал SCOPE_IDENTITY () вместо @@ IDENTITY. @@ IDENTITY даст вам последнее значение идентификатора, созданное чем-либо в текущем соединении, в отличие от вашей текущей области. Таким образом, как предположил Ричард, триггер, изменяющий другую таблицу и создающий идентичность, повлияет на возвращение @@ IDENTITY.
Ник Чаммас
В БД нет триггеров. Это свежая база данных, и таблица Customers - единственная таблица, которую я создал.
Грег Б.
@Greg B: это тип возврата функции. Вы ожидали int / bigint в качестве типа возврата (как предполагает вопрос) или вы сомневаетесь в выборе MS для этой функции?
Marian

Ответы:

28
  1. @@ identity возвращает число (38,0) . Вам нужно будет разыграть его, чтобы получить его в int.

    ВЫБЕРИТЕ CAST (@@ identity AS INT)

  2. Кроме того, попробуйте вместо этого использовать scope_identity. Если у вас есть какие-либо триггеры в таблице «Клиенты», вы можете получить последний идентификатор из другой таблицы.

  3. Наконец, поскольку вы используете dapper , вы захотите обернуть все это внутри хранимой процедуры, чтобы гарантировать, что вы гарантированно выполните вставку, а затем выбор идентификатора в том же пакете.

    Теоретически, он должен работать большую часть времени, чтобы выполнить оба из них самостоятельно. Но могут возникнуть проблемы, если вам придется дважды заходить в базу данных. (Например, как это работает с пулом соединений? Как насчет сброшенных соединений? И т. Д.) Если вы просто добавите все это в хранимую процедуру, вам не придется беспокоиться об этих дополнительных усилиях в будущем.

Ричард
источник
Спасибо за № 3. Нет ли способ определить загрузку в АПЧРК заявлении SQL?
Грег Б.
Я смотрел на это еще раз. Если вы включаете все операторы в один вызов, это все одна партия. Если вы разделите операторы на отдельные вызовы, все может стать ошибочным.
Ричард
3
+1 за рекомендацию SCOPE_IDENTITY ()
Эндрю Бикертон
10

Создать таблицу говорит:

" ИДЕНТИЧНОСТЬ

Указывает, что новый столбец является столбцом идентификаторов. Когда в таблицу добавляется новая строка, Microsoft® SQL Server ™ предоставляет уникальное добавочное значение для столбца. Столбцы идентификаторов обычно используются вместе с ограничениями PRIMARY KEY, чтобы служить уникальным идентификатором строки для таблицы. Свойство IDENTITY может быть назначено столбцам tinyint, smallint, int, bigint, decimal (p, 0) или numeric (p, 0). Для каждой таблицы может быть создан только один столбец идентификаторов. Связанные значения по умолчанию и ограничения DEFAULT нельзя использовать со столбцом идентификаторов. Вы должны указать и начальное значение, и приращение, или ни то, ни другое Если ни то, ни другое не указано, по умолчанию используется значение (1,1).

семя

Значение, используемое для самой первой строки, загруженной в таблицу.

приращение

Добавленное значение добавлено к значению идентичности предыдущей загруженной строки. "

Так что системная функция @@ identity должна справиться с наиболее охватывающим типом.

Мэриан
источник
И именно поэтому он возвращается, так numericкак у него самый широкий ассортимент ..? Спасибо
Грег Б.
3
Функция не может иметь более одного возвращаемого типа. Он должен будет использовать самый широкий тип, чтобы включить каждую возможность.
Мариан
6

«Почему SELECT @@ IDENTITY возвращает десятичную дробь»

Поскольку он может быть слишком большим, чтобы уместиться в int- он не соответствует типу столбца идентификаторов, но, как говорит Ричард, возвращает число (38,0) ( numericи decimal являются синонимами )

Джек Дуглас
источник