You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不修改base34函数的前提下用触发器生成复杂客户ID

问题背景

我们之前用标识列生成唯一编号(比如customer_id),但内部审计认为这种方式存在安全风险,因此打算改用更复杂的ID。目前已找到base34编码函数,计划将随机数、时间戳片段与序列号拼接后传入该函数生成目标ID。

需确认:能否在CUSTOMERS表的BEFORE INSERT触发器中实现此逻辑,不修改现有base34函数,且触发器自动填充customer_id字段?

CUSTOMERS表结构

CREATE TABLE CUSTOMERS (
 customer_id VARCHAR2 (20),
 first_name VARCHAR2 (20),
 last_name VARCHAR2 (20));

参考测试代码

-- 创建测试表
create table t ( pk number);

-- 创建序列,起始值1000000,循环范围1000000-9999999
create sequence seq start with 1000000 minvalue 1000000 maxvalue 9999999 cycle;

-- 插入测试数据:随机数+时间戳片段+序列值拼接成数字
begin
     for i in 1 .. 10 loop
       insert into t values (to_number(trunc(dbms_random.value(1000,9999))||to_char(systimestamp,'FFSS')||seq.nextval));
     end loop;
end;
/

-- Base34编码函数:将数字转为排除易混淆字符的Base34字符串
create or replace function base34(p_num number) return varchar2 is
     l_dig varchar2(34) := 'AB0CD1EF2GH3JK4LM5NP6QR7ST8UV9WXYZ';
     l_num number := p_num;
     l_str varchar2(38);
begin
  loop
     l_str := substr(l_dig,mod(l_num,34)+1,1) || l_str ;
     l_num := trunc(l_num/34);
    exit when l_num = 0;
  end loop;
 return l_str;
end;
/

-- Base34解码函数:将Base34字符串转回数字
create or replace function dec34(p_str varchar2) return number is
  l_dig varchar2(34) := 'AB0CD1EF2GH3JK4LM5NP6QR7ST8UV9WXYZ';
  l_num number := 0;
begin
  for i in 1 .. length(p_str) loop
     l_num := l_num * 34 + instr(l_dig,upper(substr(p_str,i,1)))-1;
   end loop;
  return l_num;
end;
/

-- 测试编码结果
select base34(pk) from t where rownum <= 10;

-- 验证编码解码一致性
select to_char(pk) from t where rownum = 1
   union all
   select base34(pk) from t where rownum = 1
   union all
   select to_char(dec34(base34(pk))) from t where rownum = 1;

实现方案

完全可以通过BEFORE INSERT触发器实现需求,无需修改现有base34函数,步骤如下:

1. 创建专用序列

为CUSTOMERS表单独创建序列(避免与其他业务序列冲突):

create sequence seq_customer_id 
start with 1000000 
minvalue 1000000 
maxvalue 9999999 
cycle;

2. 创建BEFORE INSERT触发器

触发器自动拼接随机数、时间戳片段、序列值,转为数字后调用base34函数生成customer_id:

create or replace trigger trg_customer_id
before insert on CUSTOMERS
for each row
begin
  -- 拼接4位随机数+时间戳FFSS(微秒后两位+秒)+序列值,转数字后执行base34编码
  :new.customer_id := base34(
    to_number(
      trunc(dbms_random.value(1000,9999)) || 
      to_char(systimestamp, 'FFSS') || 
      seq_customer_id.nextval
    )
  );
end;
/

3. 测试验证

插入数据时触发器会自动填充customer_id:

insert into CUSTOMERS(first_name, last_name) values ('John', 'Doe');
insert into CUSTOMERS(first_name, last_name) values ('Jane', 'Smith');

select customer_id, first_name, last_name from CUSTOMERS;

内容的提问来源于stack exchange,提问作者Pugzly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 13:15:19