Чому `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 на 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]

Чи є у вас тригери в таблиці "Клієнти"?
Річард

3
Я б використовував SCOPE_IDENTITY () замість @@ IDENTITY. @@ IDENTITY надасть останнє значення ідентичності, створене будь-яким поточним з'єднанням, на відміну від вашого поточного діапазону. Отже, як запропонував Річард, тригер, що модифікує іншу таблицю та генерує ідентичність, вплине на повернення @@ IDENTITY.
Нік Чаммас

У БД немає тригерів. Це свіжа база даних, і таблиця "Клієнти" - єдина таблиця, яку я створив.
Грег Б

@Greg B: це тип повернення функції. Чи очікували ви типу int / bigint як тип повернення (як підказує питання) або ви ставите під сумнів вибір MS для цієї функції?
Маріан

Відповіді:


28
  1. @@ ідентичність повертає числовий (38,0) . Вам потрібно буде надати це, щоб дістати його до int.

    ВИБІРТЕ КАСТ (@@ особи AS INT)

  2. Крім того, спробуйте скористатись domain_identity. Якщо у таблиці "Клієнти" є якісь тригери, ви можете отримати останню ідентифікацію з іншої таблиці.

  3. Нарешті, оскільки ви використовуєте dapper , вам захочеться загортати все це у збережену процедуру, щоб ви гарантовано виконали вкладиш, а потім вибір ідентичності в тій же партії.

    Теоретично слід працювати більшу частину часу, щоб виконати обидва з них самостійно. Але проблеми можуть виникнути, якщо вам доведеться двічі зайти в базу даних. (Наприклад, як це працює при об'єднанні з'єднань? Що з відключеними з'єднаннями?). Якщо ви просто перекинете все це на збережену процедуру, вам не доведеться турбуватися про додаткові зусилля в дорозі.


Дякуємо за №3 Чи немає способу визначити партію в Adhoc SQL-операторі?
Грег Б

Я по-іншому дивився на це. Якщо ви включите всі висловлювання в один дзвінок, це все одна партія. Якщо розділити висловлювання на окремі дзвінки, все може набути помилок.
Річард

3
+1 за рекомендацію SCOPE_IDENTITY ()
Ендрю Бікертон,

10

Створити таблицю :

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

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

насіння

Чи є значення, яке використовується для першого рядка, завантаженого в таблицю.

приріст

Чи додається додаткове значення до значення ідентичності попереднього завантаженого рядка. "

Таким чином, системна функція @@ ідентичність повинна буде справлятися з найбільш охоплюючим типом.


І ось чому він повертається, numericоскільки має найширший діапазон ..? Спасибі
Грег Б

3
Функція не може мати більше одного типу повернення. Для включення кожної можливості доведеться використовувати найширший тип.
Маріан

6

"Чому SELECT @@ IDENTITY повертає десяткові місця"

Оскільки це може бути занадто великим, щоб вмістити в нього int- він не відповідає типу стовпця ідентичності, але, як каже Річард, повертає числовий (38,0) ( numericі decimal є синонімами )

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.