• Sql Server插入数据并返回自增ID,@@IDENTITY,SCOPE_IDENTITY和IDENT_CURRENT的区别


    预备知识:SQLServer的IDENTITY关键字
    IDENTITY关键字代表的是一个函数,而不是identity属性。在access里边没有这个函数,所以在access不能用这个语句。语法:identity (数据类型,标识种子,标识增长量)
    举例:select identity (数据类型,标识种子,标识增长量) AS 列名 into 新表 from 原表名

    每个表都可以有一个自动增长列,众所周知的就是IDENTITY列。一个IDENTITY列总是被当作表的主键处理(因此,多列主键不可能有一个IDENTITY列)。并且从中可看出,我们很容易指定从什么数开始,增幅是多少。

    SQL SERVER 2000中,有三个比较类似的功能:他们分别是:SCOPE_IDENTITY、IDENT_CURRENT 和 @@IDENTITY,它们都返回插入到 IDENTITY 列中的值。

    IDENT_CURRENT 返回为任何会话和任何作用域中的特定表最后生成的标识值。IDENT_CURRENT 不受作用域和会话的限制,而受限于指定的表。IDENT_CURRENT 返回为任何会话和作用域中的特定表所生成的值。
    @@IDENTITY 返回为当前会话的所有作用域中的任何表最后生成的标识值。
    SCOPE_IDENTITY 返回为当前会话和当前作用域中的任何表最后生成的标识值

    SCOPE_IDENTITY 和 @@IDENTITY 返回在当前会话中的任何表内所生成的最后一个标识值。但是,SCOPE_IDENTITY 只返回插入到当前作用域中的值;@@IDENTITY 不受限于特定的作用域。


    SQLServer中@@IDENTITY,SCOPE_IDENTITY和IDENT_CURRENT的作用
    相同点:
    它们都返回插入到IDENTITY列中的值。

    不同点:

      A. @@IDENTITY不受作用域(存储过程、触发器、函数或批处理)的限制。返回最后一个插入的IDENTITY值。如果在程序中不同的作用域插入的表不同,那么返回最后一个表插入的IDENTITY值。例如:作用域A(存储过程)在表T1上插入IDENTITY列,而T1上的触发器会在T2上插入IDENTITY列。则用@@IDENTITY返回T2上插入的IDENTITY值。举例:
    下面的示例向带有标识列的表中插入一行,并用@@IDENTITY 显示在新行中使用的标识值。

    程序代码
    Insert INTO jobs (job_desc,min_lvl,max_lvl)
    VALUES ('Accountant',12,125)
    Select @@IDENTITY AS 'Identity'


      B. SCOPE_IDENTITY()受作用域的限制,只返回当前作用域中的最后一个IDENTITY值。上例中,如果在存储过程中使用SCOPE_IDENTITY(),则返回T1的IDENTITY值。

      C. IDENT_CURRENT()不受作用域的限制,调用它时必须提供表示表名的字符型参数,你可以得到你想要的任何表的最后一个IDENTITY值,即使你的代码里没有插入动作。例如:IDENT_CURRENT('T1');

    经验:

    比如,表 A 中有个 ID 为自增1的字段,假设此时 ID 的值为100,现在如果我往表A插入一条数据,并在插入后 SELECT @@IDENTITY,则其返回 101,最后一条IDENTITY域(即ID域)的值。

    现在问题来了,为什么说要慎用@@IDENTITY呢?原因是 @@IDENTITY 它总是获取最后一条变更数据的自增字段的值,而忽略了进行变更操作所在的范围约束。

    比如,我有表 A 和表 B 两个表,现在我在表 A 上定义了一个Insert触发器,当在表 A 中插入一条数据时,自动在表 B 也插入一条数据。此时,大家注意,有两个原子操作:在A中插入一条数据, 接着在B中随后插入一条数据。

    现在我们想下,假设上面表 A 和表 B 都有IDENTITY自增域,那么我们在表 A 插入一条数据后,使用了
    SELECT @@IDENTITY 输出时,输出的到底是 A 还是 B 的自增域的值呢? 答案很明显,是谁最后插入就输出谁,那么就是 B 了。于是,我本意是想得到 A 的自增域值,结果得到了 B 的自增域值,一只 BUG 随之诞生,搞不好还会影响到整个系统数据的混乱。

    因此,对于这种情况,建议大家慎用 @@IDENTITY,而尽量采用 SCOPE_IDENTITY() 函数,替换用SCOPE_IDENTITY() 也是得到最后一条自增域的值,但是它是仅限在一个操作范围之内,而不像 @@IDENTITY 是取全局操作的最后一步操作所产生的自增域的值的。


      根据不同的使用场合,选择不同的函数。如果在写存储过程时,向表中新增了一条数据,需要返回该IDENTITY值,则使用 SCOPE_IDENTITY(),因为它和当前会话相关联,不会返回一个你不需要的值。如果你仅仅想得到某个IDENTITY列的最后一个值,则使用 IDENT_CURRENT()最方便。

  • 相关阅读:
    今天刚开通博客,很开心
    ZYNQ双核AMP开发详解(USE_AMP -DUSE_AMP=1 含义和作用详解)
    赛灵思机器学习套件(ML Suite) v1.4 DPU, DNNK
    petalinux add pre-build application to rootfs compile faliure solution
    如何用SDK生成device tree
    Zynq UltraScale+ MPSoC device tree 中 CCF中 clock output数字映射表
    Zynq ZC702平台 QSPI + eMMC实现
    Zynq ZC702平台 Linux + Baremetal AMP实现(一)【快速启动CPU1】
    第五章 任务执行
    第四章 闭锁
  • 原文地址:https://www.cnblogs.com/yonsy/p/5466195.html
Copyright © 2020-2023  润新知