需求很简单,即某项事物使用限额为每月 50 次。
建表,项使用限制表 item_used_limit
create table item_used_limit (
item_id varchar(80) primary key, -- 项标识
item_key varchar(80), -- 项关键信息
last_phase varchar(20), -- 最后使用阶段
used_times int -- 最后阶段使后次数
)
函数标记使用1次并返回可用项
写一个函数,对某个可用项标记使用1次,并返回该可用项关键信息。
取可用项算法:对于最近使用未到达当月的,使用次数归0,否则按记录的使用次数算。使用次数小于50次的算有效。
当有可用项时,更新最近使用月份与次数,没有可用项时,返回 null 值。
CREATE OR REPLACE FUNCTION func_use_item() RETURNS varchar LANGUAGE 'plpgsql'
AS $$
DECLARE
lv_last_phase varchar := to_char(current_timestamp,'YYYYMM');
lv_item_id varchar;
lv_item_key varchar;
BEGIN
-- 找到可用的一项
-- 算法:当 last_phase 已经为最新则次数为记录的记数,否则认为已经过去,按新的从0开始
SELECT item_id, item_key into lv_item_id, lv_item_key
FROM item_used_limit
WHERE (CASE WHEN last_phase=lv_last_phase THEN used_times ELSE 0 END) < 50 LIMIT 1
FOR UPDATE;
-- 如果存在,则更新使用次数
IF lv_item_id IS NOT null THEN
UPDATE item_used_limit
SET last_phase = lv_last_phase,
used_times = (CASE WHEN last_phase=lv_last_phase THEN used_times+1 ELSE 1 END)
WHERE item_id = lv_item_id;
END IF;
RETURN lv_item_key;
END $$;
测试一下
INSERT INTO item_used_limit VALUES ('item1', 'item1', '201908', 0);
使用几次(运行几次)
SELECT func_use_item();
used_times 值记录当月的使用次数,达到 50 后,无可用项。