postgresql 触发器如何生成递增序列号,从1开始,并且每天重置

news/2024/7/9 19:50:22 标签: postgresql, 数据库, java, spring boot, mysql, 递增序列

大家好,我是三叔,许久不见,这期给大家介绍一下笔者在开发中遇到的业务处理:pgsql 创建触发器生成每日递增序列,并且第二天重置,根据不同的用户进行不同的控制。

1.创建生成递增序列的 table 表

-- 创建user_sequences表,用于保存生成的序列号
CREATE TABLE user_sequences 
(
    id                        serial,
    user_name                 varchar(255) NULL,                           -- 区分不同用户(可根据不同业务组装key)
    increment_value           int4 NULL,                                   -- 递增序列
    last_increment_date       timestamp NULL,                              -- 触发器参数时间
	description				  varchar(255) NULL,						   -- 描述
    tenant_id                 varchar(32) NULL,                            -- 租户ID
    create_user               varchar(32) NULL,                            -- 创建人ID
    create_time               timestamp(6) NULL DEFAULT CURRENT_TIMESTAMP, -- 创建时间
    update_user               varchar(32) NULL,                            -- 最后修改人ID
    update_time               timestamp NULL DEFAULT CURRENT_TIMESTAMP,    -- 更新时间
    CONSTRAINT user_sequences_pk PRIMARY KEY (id)
);

2.创建一个触发器函数

要创建一个触发器,你需要:
1、使用 create function 语句创建一个触发器函数
2、使用 create trigger 语句将触发器函数绑定到数据表
3、创建触发器函数语法:
触发器函数与普通函数类似,不同之处在于触发器不需要任何参数,并且触发器函数需要返回trigger类型值

-- 创建触发器函数
CREATE OR REPLACE FUNCTION insert_increment_value_if_not_exists()
RETURNS TRIGGER AS $$
BEGIN
  -- 检查 user_sequences 表中是否存在对应的 user_name
  IF NOT EXISTS (
    SELECT 1 FROM user_sequences WHERE user_name = NEW.user_name
  ) THEN
    -- 在 user_sequences 表中插入新的记录
    RETURN NEW;
  else 	 
	UPDATE user_sequences
    SET increment_value = increment_value + 1
    WHERE user_name = NEW.user_name
	; 
  END IF;
  RETURN null;
END;
$$ LANGUAGE plpgsql;
上述部分语法解释
NEW:该变量为 INSERT/UPDATE 操作触发的行级触发器中存储新的数据行

3.创建触发器

-- 这里介绍一下创建触发器语法(如下简单语法):
create trigger trigger_name
    {before | after | instead of} event1 or event2...
    on table_name
    {for each row | for each statement}
    execute procedure trigger_function;

event1: 事件可以是:insert, update, delete, truncate
before: 表示定义触发器在事件之前
after:   表示定义触发器在事件之后
intead of:   表示仅用于视图的insert, update, delete
for each row:表示行级触发器
for each statement:表示语级触发器

实际业务逻辑如下:笔者在插入表数据的时候触发执行器执行begin -》end 的 sql 逻辑,这样,我就能在每天对不同的用户,生成一个从1开始的递增序列,每次相同用户同一天访问一次,序列递增加1:

CREATE TRIGGER insert_increment_value_trigger
BEFORE INSERT ON user_sequences
FOR EACH ROW
EXECUTE FUNCTION insert_increment_value_if_not_exists();

4.业务处理逻辑

大家可以看到,在创建触发器的时候,有这么一句语法:BEFORE INSERT ON user_sequences,这句话是什么意思呢?
根据上面的触发器语法介绍可以知道,在每次执行 insert 语句之前,会执行触发器里面的语法。

java">@Service
public class xxxCommon {

    @Autowired
    private TableMapper mapper;

    @Transactional(rollbackFor = Exception.class)
    public String getSequencesNum(String userName) {
    // 需要注意的是这里的userName需要保证唯一,可以拼接时间yyyyMMdd,这样可以保证每天获取新的递增序列
    // 第二种方法,就是在笔者的基础上,添加时间的判断条件,判断上一次修改或生成数据的时间是否不等于当前时间,如果是的,则重新从1开始递增
        UserSequencesVO vo = new UserSequencesVO();
        assembleParam(vo);
        vo.setIncrementValue(1);
        vo.setUserName(userName);
        // 触发器触发条件,insert 语句进行触发,这里我在xml里面写了一条新增的sql语句,从而触发触发器
        mapper.insertTriger(vo);
        // 这里获取数据库返回的序列号,
        UserSequencesVO sequencesVO = UserSequencesMapper.selectByUserName(userName);
        // 根据自己的业务组装返回值
 		return sequencesVO.getIncrementValue();
    }

    private void assembleParam(UserSequencesVO vo) {
        vo.setDescription("获取当前key的递增序列");
        vo.setTenantId(userUtil.getTenantId());
        vo.setLastIncrementDate(LocalDateTime.now());
        vo.setCreateTime(LocalDateTime.now());
        vo.setCreateUser(userUtil.getId());
        vo.setTenantId(userUtil.getTenantId());
        vo.setUpdateTime(LocalDateTime.now());
        vo.setUpdateUser(userUtil.getTenantId());
    }
}

业务处理

在拿到递增的序列号之后,就可以对序列号进行一系列的组装操作,这样,根据不同的用户,互不影响,获取从 1 开始递增的序列号,并且第二天重置

结果如下:

笔者成功获取到每天操作文档的次数:
在这里插入图片描述

最后:如何删除触发器

DROP TRIGGER [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]

参数说明:

IF EXISTS:如果该触发器不存在
name:要移除的刚刚定义的触发器的名称
table_name:定义了该触发器的表的名称
CASCADE:自动删除依赖于该触发器的对象,然后删除所有 依赖于那些对象的对象
RESTRICT:如果有任何对象依赖于该触发器,则拒绝删除它,这是默认值

-- 示例
DROP TRIGGER insert_increment_value_trigger ON user_sequences;

http://www.niftyadmin.cn/n/5145198.html

相关文章

【vtk学习笔记4】基本数据类型

一、可视化数据的基本特点 可视化数据有以下特点: 离散型 计算机处理的数据是对无限、连续的空间进行采样,生成的有限采样点数据。在某些离散点上有精确的值,但点与点之间值不可知,只有通过插值方式获取数据具有规则或不规则的结…

LV.12 D13 UART实验 学习笔记

一、UART帧格式详解 UART Universal Asynchronous Receiver Transmitter 即 通用异步收发器,是一种通用的串行、异步通信总线 该总线有两条数据线,可以实现全双工的发送和接收,在嵌入式系统中常用于主机与辅助设备之间的通信。 通…

Linux(openssl):创建selfsign证书

1.创建key文件 openssl ecparam -genkey -out ss.key -name prime256v1 完成后可以在当前目录下查看生成了文件ss.key 2.创建selfsign证书 openssl req -x509 -days 1095 -key ss.key -out selfsign.pem -outform pem -sha256 输入相关信息 You are about to be asked to e…

Qt 6 MinGW使用GSL库的方法

本文参考Qt5配置开源GSL数学库与Windows系统Qt5/mingw-64配置GSL科学计算库。 首先参考MSYS2快速配置C环境ZSH安装MSYS2(64位)并换源(最好安装与Qt Maintenance Tool安装的Qt MinGW binaries相同版本号的MSYS MinGW,本文安装的Qt …

【SpringMVC篇】5种类型参数传递json数据传参

🎊专栏【SpringMVC】 🍔喜欢的诗句:天行健,君子以自强不息。 🎆音乐分享【如愿】 🎄欢迎并且感谢大家指出小吉的问题🥰 文章目录 🌺普通参数🌺POJO参数🌺嵌套…

分治法求最大最小值

分治法是一种递归的问题解决方法,它将一个大问题划分为多个小问题,然后逐个解决这些小问题,最后将结果合并得到最终的解决方案。对于求最大最小值的问题,可以使用分治法来解决。 以下是使用分治法求解最大最小值的一般步骤&#…

IM 系统通信系统是什么

IM(Instant Messaging)系统是一种实时通信系统,允许用户通过互联网或内部网络即时发送文本消息、文件、音频、视频和其他类型的数据给其他用户或群组。这类系统通常支持在线状态显示、消息确认、消息历史记录和多端同步等功能,以提…

【Python入门二】安装第三方库(包)

安装第三方库/包 1 使用pip安装2 使用PyCharm软件安装3 离线安装,使用whl文件安装参考 在Python中,有多种安装第三方库的方法,下面是一些常用的方法: 1 使用pip安装 pip是Python中最常用的包管理工具,也是最常用的在线…