Oracle和MySQL中生成32位uuid的方法(国产达梦同Oracle)

文章介绍了在Oracle和MySQL数据库中生成UUID的SQL语句,包括大小写转换。在Java中,利用UUID.randomUUID().toString()生成UUID并移除连接符。在Mybatis中,讨论了如何在插入数据时设置自动生成的UUID或获取自增ID。此外,还提到了使用Mybatis的selectKey标签以及AOP切面编程来全局处理UUID生成,简化代码。

Oracle 生成多个GUID值

SELECT sys_guid() from dual connect by rownum<10

Oracle中获取大写小写GUID字符串SQL语句

SELECT upper(rawtohex(sys_guid())) GUID from DUAL connect by rownum<10
SELECT lower(rawtohex(sys_guid())) GUID from DUAL connect by rownum<10

代码层面 (新增时设置字段自动生成uuid)

twoDeOneMember.setTwoOneRecordUuid(UUID.randomUUID().toString().replaceAll("-","").toUpperCase());

String uId = UUID.randomUUID().toString().replaceAll("-","").toUpperCase();

MySQL中生成UUID

SELECT UUID();
结果为:0a3eed30-9ad5-11e9-9835-b8ee6591991d

SELECT REPLACE(UUID(), '-', '');
结果为:eccc72479ad511e99835b8ee6591991d

1、往数据库中新增一条主键为UUID的数据,常用的方式有如下两种:

insert into stu VALUES(UUID(),'小明');

2、使用java.util类库中的方法生成UUID,然后通过传参的方式插入数据库

String uId = UUID.randomUUID().toString().replaceAll("-","");

3、当主键为自增id,为了获取新插入数据的主键id,通常我们在mybatis中是通过如下方式获取

<insert id="insertStu" parameterType="com.zzl.Stu" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
        insert into tb_flyassess_recdlist
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="name != null and name !='' ">name,</if>
            <if test="sex != null ">sex</if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="name != null and name !='' ">#{name},</if>
            <if test="sex != null ">#{sex}</if>
        </trim>
</insert>

注意:useGeneratedKeys只对insert语句生效,默认情况下,其值为false,当设置为true时,表示,若是主键列为自增列,允许 JDBC 支持自动生成主键,并可将自动生成的主键返回。keyColumn,keyProperty是声明主键的数据库字段以及java映射字段,也可以忽略,但是useGeneratedKeys = "true"是必须需要写得。

在上面的代码中,生成的自增主键可以在com.zzl.Stu类中通过其get方法拿到。

除了上述的1、2、3点概述的方法外,还可以通过如下的方法插入UUID或者获取自增ID,即灵活使用Mybatis提供的selectKey组件。

1、在插入前获取UUID,并且作为参数传入insert语句中:

 <insert id="insert" parameterType="com.zzl.Stu">
        <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.string">
            select uuid()
        </selectKey>
        insert into stu(id,name,sex)
        values
        (#{id},#{name},#{sex})
   </insert>

在selectKey组件中,通过keyProperty来指定insert语句的参数id;order值有BEFORE/AFTER两种,当order = "BEFORE"时,表示在执行insert语句前,执行该selectKey,order = "AFTER"则反之;resultType指定selectKey返回类型。

2、在插入后返回最近的自增主键

<insert id="insert" parameterType="com.zzl.Stu2" >
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select LAST_INSERT_ID()
        </selectKey>
        insert into stu2(id,name, sex)
        values
        (#{id},#{name},#{sex})
</insert>

select LAST_INSERT_ID()是将最后插入表中自增id查询出来,然后赋值给keyProperty定义的字段中,order = "AFTER",表示在insert语句执行结束之后执行selectKey语句,resultType定义selectKey的返回值。最后可以通过com.zzl.Stu2类中的get方法获取到返回的自增id。

另外,对于UUID的处理,除了以上方法,还可以引入AOP切面原理,使其达到全局处理的目的。如下可以作为一个简单的参考模式,可以根据实际的业务逻辑进行扩展。

package com.zzl.aop;
 
import org.springframework.stereotype.Component;
 
import java.lang.reflect.Method;
import java.util.UUID;
 
/**
 * @author zzl
 * @Date 2022/4/11
 * @description
 */
@Aspect
@Component
public class AopTest {
 
 
    /**
     *
     * insert开头的方法
     */
    @Pointcut("execution(* **..insert(..))")
    public void insert() {
    }
 
    /**
     * 数据插入前操作
     *
     * @param joinPoint
     * @throws Exception
     */
    @Before(value = "insert()")
    public void insertBefore(JoinPoint joinPoint) throws Exception {
        Object[] obj = joinPoint.getArgs();
 
        for (Object argItem : obj) {
            if (BaseEntity.class.isAssignableFrom(argItem.getClass())) {
                Method setId = argItem.getClass().getMethod("setId", String.class);
                setId.invoke(argItem, UUID.randomUUID().toString().replaceAll("-", ""));
            }
        }
    }
 
}
 

如上代码中,@Aspect注解修饰该类为切面类,如下的操作将切面类的操作进行执行。@Component注解是使其切面类能被Spring扫描到,并且将其注册成为Spring容器中的Bean。@PointCut注解定义一个切点,且参数定义了匹配规则,唯有满足对应的匹配规则,该切点才得以执行。@Before注解指名了在切点执行之前,该执行哪些具体的业务逻辑,因为定义该切面类的初衷是在插入前生成UUID。于是在该切面类中,在判断insert语句中的参数实体类是否是BaseEntity或者其子类(这个步骤就是简单的进行过滤),若满足条件,则在插入前执行set方法,将生成的UUID传至对应的参数中。

于是,每当我们执行insert开头的插入语句,该切面类会起作用,会判断insert中的实体类是否是BaseEntity或者其子类,若是,则会自动生成UUID,不需要再对UUID值进行手动处理,其灵活性会高很多。

<think>我们注意到用户现在想要使用UUID来实现32的自增ID字段。但是,UUID通常是12832个十六进制字符)的,而不是32(4字节)的。在计算机中,32通常指4字节整数,而UUID是128的全局唯一标识符。因此,我们需要澄清: 用户要求的是32的自增ID?还是32个字符的UUID字符串? 根据用户之前的描述,他们之前要求的是32自增ID(即4字节整数,最大值为2147483647),但现在又提到使用UUID实现32自增ID。这存在矛盾,因为UUID不是自增的,也不是32整数。 然而,从用户提供的引用中,我们看到他们引用了UUID的使用(引用[3]引用[4])。因此,我们推测用户实际上想要一个32个字符的字符串作为ID,并且这个ID是全局唯一的(使用UUID生成),而不是自增的整数。 所以,我们需要明确: 1. 如果用户确实想要32整数(4字节)的自增ID,那么应该使用序列(sequence)触发器(trigger)或者Oracle 12c以上的identity列,如之前回答所述。 2. 如果用户想要一个32个字符的UUID(通常由32个十六进制字符组成,如`550e8400-e29b-41d4-a716-446655440000`去掉连字符后就是32字符),那么我们可以使用UUID生成函数。 但是,Oracle本身并没有内置的UUID生成函数。通常,我们可以使用`SYS_GUID()`函数来生成一个16字节(128)的全局唯一标识符,它返回的是RAW类型,通常表示为32个十六进制字符(但注意,RAW类型在显示上可以转换为32个字符的字符串)。 因此,我们假设用户需要的是32个字符的UUID字符串(由32个十六进制字符组成)作为主键。 步骤: 1. 在表中添加一个VARCHAR2(32)类型的列(或者CHAR(32))来存储UUID字符串。 2. 创建一个触发器,在插入数据之前,如果该列没有值,则生成一个UUID(使用`SYS_GUID()`函数)并转换为32个字符的字符串(去掉可能存在的连字符,但注意`SYS_GUID()`返回的RAW类型默认没有连字符,直接转换为字符串就是32个字符)。 3. 注意:`SYS_GUID()`返回的是RAW类型,长度为16字节,转换为十六进制字符串就是32个字符。 具体实现: ### 步骤1:添加列 ```sql ALTER TABLE yjl_yjsyqk ADD uuid_id VARCHAR2(32); ``` ### 步骤2:创建触发器 ```sql CREATE OR REPLACE TRIGGER trg_yjl_yjsyqk_uuid BEFORE INSERT ON yjl_yjsyqk FOR EACH ROW BEGIN IF :NEW.uuid_id IS NULL THEN -- 将SYS_GUID()生成的RAW类型转换为32个字符的十六进制字符串 :NEW.uuid_id := LOWER(RAWTOHEX(SYS_GUID())); END IF; END; / ``` ### 步骤3:测试 插入一条数据,不提供uuid_id,看触发器是否自动生成。 ```sql INSERT INTO yjl_yjsyqk (其他列) VALUES (其他值); SELECT * FROM yjl_yjsyqk WHERE ...; -- 查看uuid_id是否生成 ``` ### 说明: 1. `SYS_GUID()` 生成一个16字节的RAW值,`RAWTOHEX`将其转换为32个字符的十六进制字符串(大写)。使用`LOWER`可以转换为小写(可选)。 2. 如果需要大写,可以去掉`LOWER`函数。 3. 这个UUID不是自增的,而是随机的全局唯一标识符。如果用户需要自增的整数,那么UUID方案并不符合(因为UUID不是自增的)。 ### 补充:如果用户确实需要自增的32整数(4字节整数) 那么请按照之前回答中的方案(使用序列+触发器或identity列)来实现,并注意32整数的范围限制(最大2147483647)。 ### 相关问题: 1. 如何将Oracle的RAW类型转换为字符串? 2. 如何生成大写UUID字符串? 3. Oracle中如何保证UUID的唯一性? 4. 使用UUID作为主键对性能有什么影响? 5. 如何为已有数据批量生成UUID? ### 引用说明: 在引用[3]中,使用了`select uuid()`,但这是MySQL的函数,在Oracle中我们使用`SYS_GUID()`。引用[4]中提到了Hibernate的uuid生成策略,但在数据库层面我们使用触发器。 因此,根据用户提供的引用,我们提供了Oracle对应的UUID生成方法。 注意:如果用户之前已经添加了自增的整数ID,现在又想改为UUID,那么需要删除原来的自增列,并添加新的UUID列,然后更新所有现有数据的UUID值(通过触发器只能对新插入的数据生效,所以需要手动更新旧数据)。 更新已有数据的UUID: ```sql UPDATE yjl_yjsyqk SET uuid_id = LOWER(RAWTOHEX(SYS_GUID())) WHERE uuid_id IS NULL; ``` 最后,建议将UUID列设置为主键: ```sql ALTER TABLE yjl_yjsyqk ADD CONSTRAINT pk_yjl_yjsyqk_uuid PRIMARY KEY (uuid_id); ``` 请用户根据实际需求选择方案。</think>在 Oracle 数据库中为 `yjl_yjsyqk` 表添加 UUID 实现的 32 唯一标识符字段,可以通过以下步骤实现。UUID 是全局唯一标识符(128 ),通常表示为 32 个十六进制字符,符合您要求的 32 字符长度。 ### 完整实现步骤 #### 1. 添加 UUID 字段 ```sql -- 添加 VARCHAR2(32) 类型的字段存储 UUID ALTER TABLE yjl_yjsyqk ADD uuid_id VARCHAR2(32); ``` #### 2. 创建触发器生成 UUID ```sql CREATE OR REPLACE TRIGGER trg_gen_uuid BEFORE INSERT ON yjl_yjsyqk FOR EACH ROW BEGIN IF :NEW.uuid_id IS NULL THEN -- 生成32字符UUID(去除分隔符) :NEW.uuid_id := REPLACE(RAWTOHEX(SYS_GUID()), '-', ''); END IF; END; / ``` #### 3. 验证功能 ```sql -- 测试插入数据 INSERT INTO yjl_yjsyqk (其他字段) VALUES ('测试数据'); -- 查询生成UUID SELECT uuid_id FROM yjl_yjsyqk WHERE ROWNUM = 1; ``` #### 4. (可选)设置主键约束 ```sql -- 添加主键约束 ALTER TABLE yjl_yjsyqk ADD CONSTRAINT pk_yjl_uuid PRIMARY KEY (uuid_id); ``` ### 关键说明 1. **UUID 生成原理**: - `SYS_GUID()`:Oracle 内置函数,生成 16 字节 RAW 类型的全局唯一标识符 - `RAWTOHEX()`:将 RAW 类型转换为 32 字符十六进制字符串 - `REPLACE(..., '-', '')`:移除 UUID 中的连字符(生成紧凑的 32 字符串) 2. **数据存储**: ```plaintext 示例值:550e8400e29b41d4a716446655440000 长度:32 字符 类型:VARCHAR2(32) ``` 3. **MyBatis 集成示例**(参考引用[1][3]): ```xml <insert id="insertData" parameterType="com.example.Entity"> <selectKey keyProperty="uuidId" order="BEFORE" resultType="String"> SELECT REPLACE(RAWTOHEX(SYS_GUID()), '-', '') FROM dual </selectKey> INSERT INTO yjl_yjsyqk(uuid_id, 其他字段) VALUES(#{uuidId}, #{其他字段}) </insert> ``` ### 性能与注意事项 1. **索引优化**: - UUID 作为主键时,建议使用反向键索引减少热点争用 ```sql CREATE INDEX idx_uuid_reverse ON yjl_yjsyqk(REVERSE(uuid_id)); ``` 2. **存储开销**: - 相比自增数字(4字节),UUID 需要 32 字节存储 - 评估表数据量,超 1 亿行建议分区表 3. **数据迁移**: ```sql -- 为已有数据生成UUID UPDATE yjl_yjsyqk SET uuid_id = REPLACE(RAWTOHEX(SYS_GUID()), '-', '') WHERE uuid_id IS NULL; ``` ### 生成结果示例 | UUID_ID | 其他字段 | |----------------------------------|----------| | `550e8400e29b41d4a716446655440000` | 测试数据 | | `6ba7b8149d6011d4b716446655440000` | 样本数据 | > **提示**:UUID 虽非严格自增,但通过 `SYS_GUID()` 生成的序列具有时间成分,插入顺序近似有序[^1][^3]。若需严格自增,建议采用序列方案(见引用[1])。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@百思不如奇解

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值