Best way to get identity of inserted row?

后端 未结 14 2412
醉梦人生
醉梦人生 2020-11-21 07:06

What is the best way to get IDENTITY of inserted row?

I know about @@IDENTITY and IDENT_CURRENT and SCOPE_IDENTITY

相关标签:
14条回答
  • 2020-11-21 07:40

    One other way to guarantee the identity of the rows you insert is to specify the identity values and use the SET IDENTITY_INSERT ON and then OFF. This guarantees you know exactly what the identity values are! As long as the values are not in use then you can insert these values into the identity column.

    CREATE TABLE #foo 
      ( 
         fooid   INT IDENTITY NOT NULL, 
         fooname VARCHAR(20) 
      ) 
    
    SELECT @@Identity            AS [@@Identity], 
           Scope_identity()      AS [SCOPE_IDENTITY()], 
           Ident_current('#Foo') AS [IDENT_CURRENT] 
    
    SET IDENTITY_INSERT #foo ON 
    
    INSERT INTO #foo 
                (fooid, 
                 fooname) 
    VALUES      (1, 
                 'one'), 
                (2, 
                 'Two') 
    
    SET IDENTITY_INSERT #foo OFF 
    
    SELECT @@Identity            AS [@@Identity], 
           Scope_identity()      AS [SCOPE_IDENTITY()], 
           Ident_current('#Foo') AS [IDENT_CURRENT] 
    
    INSERT INTO #foo 
                (fooname) 
    VALUES      ('Three') 
    
    SELECT @@Identity            AS [@@Identity], 
           Scope_identity()      AS [SCOPE_IDENTITY()], 
           Ident_current('#Foo') AS [IDENT_CURRENT] 
    
    -- YOU CAN INSERT  
    SET IDENTITY_INSERT #foo ON 
    
    INSERT INTO #foo 
                (fooid, 
                 fooname) 
    VALUES      (10, 
                 'Ten'), 
                (11, 
                 'Eleven') 
    
    SET IDENTITY_INSERT #foo OFF 
    
    SELECT @@Identity            AS [@@Identity], 
           Scope_identity()      AS [SCOPE_IDENTITY()], 
           Ident_current('#Foo') AS [IDENT_CURRENT] 
    
    SELECT * 
    FROM   #foo 
    

    This can be a very useful technique if you are loading data from another source or merging data from two databases etc.

    0 讨论(0)
  • 2020-11-21 07:43

    After Your Insert Statement you need to add this. And Make sure about the table name where data is inserting.You will get current row no where row affected just now by your insert statement.

    IDENT_CURRENT('tableName')
    
    0 讨论(0)
  • 2020-11-21 07:44
    • @@IDENTITY returns the last identity value generated for any table in the current session, across all scopes. You need to be careful here, since it's across scopes. You could get a value from a trigger, instead of your current statement.

    • SCOPE_IDENTITY() returns the last identity value generated for any table in the current session and the current scope. Generally what you want to use.

    • IDENT_CURRENT('tableName') returns the last identity value generated for a specific table in any session and any scope. This lets you specify which table you want the value from, in case the two above aren't quite what you need (very rare). Also, as @Guy Starbuck mentioned, "You could use this if you want to get the current IDENTITY value for a table that you have not inserted a record into."

    • The OUTPUT clause of the INSERT statement will let you access every row that was inserted via that statement. Since it's scoped to the specific statement, it's more straightforward than the other functions above. However, it's a little more verbose (you'll need to insert into a table variable/temp table and then query that) and it gives results even in an error scenario where the statement is rolled back. That said, if your query uses a parallel execution plan, this is the only guaranteed method for getting the identity (short of turning off parallelism). However, it is executed before triggers and cannot be used to return trigger-generated values.

    0 讨论(0)
  • 2020-11-21 07:45

    I believe the safest and most accurate method of retrieving the inserted id would be using the output clause.

    for example (taken from the following MSDN article)

    USE AdventureWorks2008R2;
    GO
    DECLARE @MyTableVar table( NewScrapReasonID smallint,
                               Name varchar(50),
                               ModifiedDate datetime);
    INSERT Production.ScrapReason
        OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
            INTO @MyTableVar
    VALUES (N'Operator error', GETDATE());
    
    --Display the result set of the table variable.
    SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar;
    --Display the result set of the table.
    SELECT ScrapReasonID, Name, ModifiedDate 
    FROM Production.ScrapReason;
    GO
    
    0 讨论(0)
  • 2020-11-21 07:45

    When you use Entity Framework, it internally uses the OUTPUT technique to return the newly inserted ID value

    DECLARE @generated_keys table([Id] uniqueidentifier)
    
    INSERT INTO TurboEncabulators(StatorSlots)
    OUTPUT inserted.TurboEncabulatorID INTO @generated_keys
    VALUES('Malleable logarithmic casing');
    
    SELECT t.[TurboEncabulatorID ]
    FROM @generated_keys AS g 
       JOIN dbo.TurboEncabulators AS t 
       ON g.Id = t.TurboEncabulatorID 
    WHERE @@ROWCOUNT > 0
    

    The output results are stored in a temporary table variable, joined back to the table, and return the row value out of the table.

    Note: I have no idea why EF would inner join the ephemeral table back to the real table (under what circumstances would the two not match).

    But that's what EF does.

    This technique (OUTPUT) is only available on SQL Server 2008 or newer.

    Edit - The reason for the join

    The reason that Entity Framework joins back to the original table, rather than simply use the OUTPUT values is because EF also uses this technique to get the rowversion of a newly inserted row.

    You can use optimistic concurrency in your entity framework models by using the Timestamp attribute:

    0 讨论(0)
  • 2020-11-21 07:46

    Create a uuid and also insert it to a column. Then you can easily identify your row with the uuid. Thats the only 100% working solution you can implement. All the other solutions are too complicated or are not working in same edge cases. E.g.:

    1) Create row

    INSERT INTO table (uuid, name, street, zip) 
            VALUES ('2f802845-447b-4caa-8783-2086a0a8d437', 'Peter', 'Mainstreet 7', '88888');
    

    2) Get created row

    SELECT * FROM table WHERE uuid='2f802845-447b-4caa-8783-2086a0a8d437';
    
    0 讨论(0)
提交回复
热议问题