ทำไม `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, ...)ส่งการยกเว้น Cast ไม่ถูกต้อง ผมเคยบั๊กมันและมันก็เป็นจุดที่ Dapper เรียกบนกลับGetValueSqlDataReader

ชนิดส่งคืนของGetValueคือObjectการตรวจสอบในรายการดีบักเกอร์ซึ่งเป็นทศนิยมแบบกล่อง

ถ้าฉันเปลี่ยนการเลือกSELECT CAST(@@IDENTITY as int)เป็นการคืนค่าของ GetValue จะเป็น int แบบกล่องและข้อยกเว้นจะไม่ถูกส่งออกไป

คอลัมน์รหัสเป็นประเภท int แน่นอน ทำไมจะSELECT @@IDENTITYส่งกลับทศนิยม

ข้อมูลเพิ่มเติมบางส่วน:

  • ฐานข้อมูลเป็นของใหม่
  • ตารางลูกค้าเป็นวัตถุเดียวที่ฉันเพิ่มเข้าไป ไม่มีตาราง (ผู้ใช้) อื่น ๆ มุมมองทริกเกอร์หรือกระบวนงานที่เก็บไว้ในฐานข้อมูล
  • มี 10 แถวในฐานข้อมูลมีรหัสของ 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
Nick Chammas

ไม่มีทริกเกอร์ในฐานข้อมูล มันเป็นฐานข้อมูลใหม่และตารางลูกค้าเป็นตารางเดียวที่ฉันสร้างขึ้น
เกร็ก B

@Greg B: นี่เป็นประเภทส่งคืนของฟังก์ชัน คุณคาดหวังว่า int / bigint เป็นชนิดส่งคืน (ตามคำถามที่แนะนำ) หรือคุณตั้งคำถามกับตัวเลือก MS สำหรับฟังก์ชั่นนี้หรือไม่?
แมเรียน

คำตอบ:


28
  1. @@ ตัวตนส่งกลับตัวเลข (38,0) คุณจะต้องโยนมันเพื่อที่จะได้รับมัน

    เลือกนักแสดง (@@ ตัวตนเป็น INT)

  2. และลองใช้ scope_identity แทน หากคุณมีทริกเกอร์ใด ๆ ในตารางลูกค้าคุณอาจได้รับข้อมูลประจำตัวล่าสุดจากตารางอื่น

  3. ในที่สุดเนื่องจากคุณใช้dapperคุณจะต้องการห่อทั้งหมดนั้นไว้ในกระบวนงานที่เก็บไว้เพื่อให้คุณรับประกันว่าจะสามารถแทรกได้และจากนั้นเลือกข้อมูลประจำตัวในแบทช์เดียวกัน

    ในทางทฤษฎีมันควรใช้เวลาส่วนใหญ่ในการดำเนินการทั้งสองด้วยตัวเอง แต่ปัญหาอาจเกิดขึ้นหากคุณต้องไปที่ฐานข้อมูลสองครั้ง (เช่นวิธีนี้ทำงานร่วมกับการรวมการเชื่อมต่อหรือไม่การเชื่อมต่อที่ถูกทิ้งจะทำอย่างไร ฯลฯ ) ถ้าคุณทิ้งทุกอย่างไว้ในขั้นตอนการจัดเก็บคุณจะไม่ต้องกังวลกับความพยายามพิเศษนั้น


ขอบคุณสำหรับ # 3 ไม่มีวิธีกำหนดแบทช์ในคำสั่งadhoc SQL หรือไม่?
เกร็ก B

ฉันดูอีกครั้ง หากคุณรวมคำสั่งทั้งหมดในการโทรเพียงครั้งเดียวมันเป็นชุดเดียวทั้งหมด หากคุณแยกงบออกเป็นสายที่แยกกัน
ริชาร์ด

3
+1 สำหรับการแนะนำ SCOPE_IDENTITY ()
Andrew Bickerton

10

สร้างตารางพูดว่า:

"ตัวตน

บ่งชี้ว่าคอลัมน์ใหม่เป็นคอลัมน์ข้อมูลประจำตัว เมื่อเพิ่มแถวใหม่ลงในตารางMicrosoft® SQL Server ™จะให้ค่าที่ไม่ซ้ำและเพิ่มขึ้นสำหรับคอลัมน์ โดยทั่วไปคอลัมน์รหัสประจำตัวจะใช้ร่วมกับข้อ จำกัด หลักของ KEY เพื่อใช้เป็นตัวระบุแถวที่ไม่ซ้ำสำหรับตาราง คุณสมบัติ IDENTITY สามารถกำหนดให้กับจิ๋วจิ้น, smallint, int, bigint, ทศนิยม (p, 0) หรือคอลัมน์ตัวเลข (p, 0) สามารถสร้างคอลัมน์ข้อมูลประจำตัวได้หนึ่งคอลัมน์ต่อหนึ่งตาราง ค่าเริ่มต้นที่ถูกผูกไว้และข้อ จำกัด DEFAULT ไม่สามารถใช้กับคอลัมน์ข้อมูลประจำตัวได้ คุณต้องระบุทั้งเมล็ดและการเพิ่มขึ้นหรือไม่ หากไม่ได้ระบุไว้ค่าเริ่มต้นคือ (1,1)

เมล็ดพันธุ์

เป็นค่าที่ใช้สำหรับแถวแรกที่โหลดลงในตาราง

การเพิ่มขึ้น

เป็นค่าที่เพิ่มขึ้นที่เพิ่มเข้าไปในค่าตัวตนของแถวก่อนหน้านี้ที่โหลดหรือไม่ "

ดังนั้นฟังก์ชั่นระบบ @@ ตัวตนจะต้องรับมือกับประเภทที่ครอบคลุมมากที่สุด


และนี่คือสาเหตุที่มันกลับมาnumericเนื่องจากมีช่วงกว้างที่สุด .. ? ขอบคุณ
Greg B

3
ฟังก์ชันไม่สามารถมีประเภทส่งคืนได้มากกว่าหนึ่งประเภท มันจะต้องใช้ประเภทที่กว้างที่สุดเพื่อรวมทุกความเป็นไปได้
แมเรียน

6

"ทำไม SELECT @@ IDENTITY จึงส่งกลับทศนิยม"

เนื่องจากอาจมีขนาดใหญ่เกินไปที่จะใส่ลงในint- มันไม่ตรงกับประเภทของคอลัมน์ข้อมูลประจำตัว แต่ Richard บอกว่าคืนค่าตัวเลข (38,0) ( numericและdecimal เป็นคำพ้องความหมาย )

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.