@@Identity 与触发器冲突的解决方案

@@IDENTITY 
返回最后插入的标识值。 

语法 
@@IDENTITY 

返回类型 
numeric 

注释 
在一条 INSERT、SELECT INTO 或大容量复制语句完成后,@@IDENTITY 中包含此语句产生的最后的标识值。若此语句没有影响任何有标识列的表,则 @@IDENTITY 返回 NULL。若插入了多个行,则会产生多个标识值,@@IDENTITY 返回最后产生的标识值。如果此语句激发一个或多个执行产生标识值的插入操作的触发器,则语句执行后立即调用 @@IDENTITY 将返回由触发器产生的最后的标识值。若 INSERT 或 SELECT INTO 语句失败或大容量复制失败,或事务被回滚,则 @@IDENTITY 值不会还原为以前的设置。 

在返回插入到表的 @@IDENTITY 列的最后一个值方面,@@IDENTITY、SCOPE_IDENTITY 和 IDENT_CURRENT 函数类似。 

@@IDENTITY 和 SCOPE_IDENTITY 将返回在当前会话的所有表中生成的最后一个标识值。但是,SCOPE_IDENTITY 只在当前作用域内返回值,而 @@IDENTITY 不限于特定的作用域。 

IDENT_CURRENT 不受作用域和会话的限制,而受限于指定的表。IDENT_CURRENT 返回任何会话和任何作用域中为特定表生成的标识值。有关更多信息,请参见 IDENT_CURRENT。 


--------------------------------------------------------------- 

我总结的3种返回最大标识值的方法的不同点: 

IDENT_CURRENT 返回为任何会话和任何作用域中的特定表最后生成的标识值。 


@@IDENTITY 返回为当前会话的所有作用域中的任何表最后生成的标识值。 


SCOPE_IDENTITY 返回为当前会话和当前作用域中的任何表最后生成的标识值。(防止返回触发器中的insert的IDENTITY值) 
--------------------------------------------------------------- 

@@IDENTITY 
返回最后插入的标识值。 

语法 
@@IDENTITY 

返回类型 
numeric 

注释 
在一条 INSERT、SELECT INTO 或大容量复制语句完成后,@@IDENTITY 中包含此语句产生的最后的标识值。若此语句没有影响任何有标识列的表,则 @@IDENTITY 返回 NULL。若插入了多个行,则会产生多个标识值,@@IDENTITY 返回最后产生的标识值。如果此语句激发一个或多个执行产生标识值的插入操作的触发器,则语句执行后立即调用 @@IDENTITY 将返回由触发器产生的最后的标识值。若 INSERT 或 SELECT INTO 语句失败或大容量复制失败,或事务被回滚,则 @@IDENTITY 值不会还原为以前的设置。 

在返回插入到表的 @@IDENTITY 列的最后一个值方面,@@IDENTITY、SCOPE_IDENTITY 和 IDENT_CURRENT 函数类似。 

@@IDENTITY 和 SCOPE_IDENTITY 将返回在当前会话的所有表中生成的最后一个标识值。但是,SCOPE_IDENTITY 只在当前作用域内返回值,而 @@IDENTITY 不限于特定的作用域。 

IDENT_CURRENT 不受作用域和会话的限制,而受限于指定的表。IDENT_CURRENT 返回任何会话和任何作用域中为特定表生成的标识值。有关更多信息,请参见 IDENT_CURRENT。 

示例 
下面的示例向带有标识列的表中插入一行,并用 @@IDENTITY 显示在新行中使用的标识值。 

INSERT INTO jobs (job_desc,min_lvl,max_lvl) 
VALUES ('Accountant',12,125) 
SELECT @@IDENTITY AS '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 不受限于特定的作用域。
  例如,有两个表 T1 和 T2,在 T1 上定义了一个 INSERT 触发器。当将某行插入 T1 时,触发器被激发,并在 T2 中插入一行。此例说明了两个作用域:一个是在 T1 上的插入,另一个是作为触发器的结果在 T2 上的插入。
  假设 T1 和 T2 都有 IDENTITY 列,@@IDENTITY 和 SCOPE_IDENTITY 将在 T1 上的 INSERT 语句的最后返回不同的值。
  @@IDENTITY 返回插入到当前会话中任何作用域内的最后一个 IDENTITY 列值,该值是插入 T2 中的值。
  SCOPE_IDENTITY() 返回插入 T1 中的 IDENTITY 值,该值是发生在相同作用域中的最后一个 INSERT。如果在作用域中发生插入语句到标识列之前唤醒调用 SCOPE_IDENTITY() 函数,则该函数将返回 NULL 值。
  而IDENT_CURRENT('T1') 和 IDENT_CURRENT('T2') 返回的值分别是这两个表最后自增的值。
  ajqc的实验:(40条本地线程,40+40条远程线程同时并发测试,插入1200W行),得出的结论是: 
  1.在典型的级联应用中.不能用@@IDENTITY,在CII850,256M SD的机器上1W多行时就会并发冲突.在P42.8C,512M DDR上,才6000多行时就并发冲突. 
  2.SCOPE_IDENTITY()是绝对可靠的,可以用在存储过程中,连触发器也不用建,没并发冲突

<think>好的,用户的问题是关于在不同数据库中实现主键自增,以及Java实体类中@TableName和@KeySequence注解的作用。首先,我需要明确这两个注解的具体用途,尤其是它们在MyBatis-Plus框架中的功能。 用户提到了多个数据库,包括Oracle、PostgreSQL、Kingbase、DB2、H2和MySQL,每个数据库的主键自增机制可能不同。例如,MySQL使用AUTO_INCREMENT,而Oracle通常用序列(Sequence)和触发器(Trigger)。PostgreSQL和Kingbase可能使用SERIAL类型或序列。需要分别说明每种数据库的实现方式,并指出对应的注解或配置方法。 接下来,@TableName注解在MyBatis-Plus中用于指定数据库表名,特别是当实体类名表名不一致时。而@KeySequence用于指定主键生成策略的序列名,适用于支持序列的数据库,比如Oracle和PostgreSQL。需要注意的是,MyBatis-Plus中可能需要结合其他注解如@TableId来使用,同时设置主键生成策略为IdType.INPUT。 然后,要检查各个数据库的兼容性。例如,Oracle和PostgreSQL使用序列,所以@KeySequence适用;而MySQL的AUTO_INCREMENT则需要不同的处理,可能使用@TableId(type = IdType.AUTO)。同时,用户提供的引用中提到@TableName的autoResultMap属性需要设置为true,以确保类型处理器生效,这点在回答时需要提及。 还要考虑不同数据库的驱动配置和可能的异常,如Kingbase中的关键字问题,可能需要修改字段名或设置排除关键字。此外,引用中的JSON类型和Geometry类型的问题可能主键自增无关,但需要注意其他配置可能影响整体功能。 最后,整合所有信息,分步骤说明每个数据库的主键自增实现方法,并解释注解的作用及配置注意事项。确保回答结构清晰,覆盖用户提到的所有数据库,并引用提供的参考资料中的解决方案,如排除关键字和autoResultMap的设置。</think>### 不同数据库主键自增实现及注解作用详解 #### 一、Java 实体类中的注解作用 1. **@TableName** - 用于指定实体类对应的数据库表名,当表名类名不一致时使用。 - 关键属性 `autoResultMap = true`:启用自动结果映射,确保自定义类型处理器(如处理数据库特有类型)生效[^3]。 2. **@KeySequence** - 声明主键生成策略为数据库序列(Sequence),适用于支持序列的数据库(如 Oracle、PostgreSQL)。 - 需配合 `@TableId(type = IdType.INPUT)` 使用,指定主键值由外部输入(即通过序列生成)。 #### 二、各数据库主键自增实现方式 1. **Oracle** - **实现方式**:使用序列(Sequence)生成主键。 - **代码配置**: ```sql CREATE SEQUENCE seq_name INCREMENT BY 1 START WITH 1; ``` ```java @KeySequence("seq_name") @TableName(value = "table_name", autoResultMap = true) public class Entity { @TableId(type = IdType.INPUT) private Long id; } ``` 2. **PostgreSQL/Kingbase** - **实现方式**:使用 `SERIAL` 类型或自定义序列。 - **SERIAL 类型**: ```sql CREATE TABLE table_name (id SERIAL PRIMARY KEY, ...); ``` - **自定义序列**(兼容@KeySequence): ```java @KeySequence("seq_name") @TableName(value = "table_name", autoResultMap = true) public class Entity { @TableId(type = IdType.INPUT) private Integer id; } ``` 3. **DB2** - **实现方式**:`GENERATED BY DEFAULT AS IDENTITY`。 - **建表语句**: ```sql CREATE TABLE table_name (id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, ...); ``` 4. **H2** - **实现方式**:`AUTO_INCREMENT` 或 `IDENTITY`。 - **代码配置**: ```java @TableId(type = IdType.AUTO) private Long id; ``` 5. **MySQL** - **实现方式**:`AUTO_INCREMENT`。 - **配置**: ```sql CREATE TABLE table_name (id INT AUTO_INCREMENT PRIMARY KEY, ...); ``` ```java @TableId(type = IdType.AUTO) private Long id; ``` #### 三、兼容性注意事项 1. **关键字冲突处理** - 若字段名数据库保留关键字冲突(如 `level`),需修改字段名或通过配置忽略关键字(如 Kingbase 中执行 `ALTER SYSTEM SET exclude_reserved_words = 'level'`)[^1]。 2. **类型映射问题** - 复杂类型(如 `geometry` 或 `json`)需在实体类中指定类型处理器,并确保 `@TableName(autoResultMap = true)` 开启[^3]。 3. **驱动差异** - PostgreSQL 的 `json` 类型需严格匹配,避免将字符串赋值给 `json` 字段[^2]。 #### 四、总结对比 | 数据库 | 主键生成方式 | 注解配置 | 驱动适配要点 | |------------|------------------------|-----------------------------------|----------------------------------| | Oracle | 序列 | `@KeySequence` + `IdType.INPUT` | 序列需预先创建 | | PostgreSQL | 序列/SERIAL | `@KeySequence` 或 `IdType.AUTO` | 自定义序列需显式绑定 | | Kingbase | 同 PostgreSQL | 同上 | 注意关键字排除配置 | | DB2 | IDENTITY | `IdType.AUTO` | 使用标准 SQL 语法 | | H2 | AUTO_INCREMENT/IDENTITY| `IdType.AUTO` | 兼容 MySQL/PostgreSQL 模式 | | MySQL | AUTO_INCREMENT | `IdType.AUTO` | 默认支持无需额外配置 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值