首页 > 数据库 >【问题记录】【数据库】库存或者账户流水记录修复

【问题记录】【数据库】库存或者账户流水记录修复

时间:2024-09-03 21:53:11浏览次数:6  
标签:account 记录 price after t1 流水 id 数据库 change

1  前言

大家的系统有没有关于客户资金、会员卡余额、库存记录等,这些相关信息的存储,说白了就是流水记录表。不知道大家是如何存储的,我们的存储一条记录最起码的是变动数量、变动前数量、变动后数量,这个变动前、变动后就粘的比较紧,那么当系统出现问题的时候,可能中间差一条变动,那么后边的流水记录都要变动,那么如何修复呢?本节来记录一下。

2  数据准备

表结构:

CREATE TABLE "public"."my_account_change_info" (
  "id" int8 NOT NULL,
  "account_code" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
  "change_type" int2 NOT NULL,
  "change_price" numeric(16,2) NOT NULL,
  "before_price" numeric(16,2) NOT NULL,
  "after_price" numeric(16,2) NOT NULL,
  "create_time" timestamp(6),
  "modify_time" timestamp(6),
  CONSTRAINT "pk_my_account_change_info" PRIMARY KEY ("id")
)
;

ALTER TABLE "public"."my_account_change_info" 
  OWNER TO "postgres";

COMMENT ON COLUMN "public"."my_account_change_info"."id" IS '主键';

COMMENT ON COLUMN "public"."my_account_change_info"."account_code" IS '账户编码';

COMMENT ON COLUMN "public"."my_account_change_info"."change_type" IS '资金类型 10-账户资金 20-信用额度';

COMMENT ON COLUMN "public"."my_account_change_info"."change_price" IS '变更金额';

COMMENT ON COLUMN "public"."my_account_change_info"."before_price" IS '变更前金额';

COMMENT ON COLUMN "public"."my_account_change_info"."after_price" IS '变更后金额';

COMMENT ON COLUMN "public"."my_account_change_info"."create_time" IS '创建时间';

COMMENT ON COLUMN "public"."my_account_change_info"."modify_time" IS '更新时间';

COMMENT ON TABLE "public"."my_account_change_info" IS '账户金额变动记录表';

数据:

INSERT INTO "public"."my_account_change_info" ("id", "account_code", "change_type", "change_price", "before_price", "after_price", "create_time", "modify_time") VALUES (1, '001', 10, '10.00', '10.00', '20.00', '2024-09-03 19:36:43', '2024-09-03 19:36:46');
INSERT INTO "public"."my_account_change_info" ("id", "account_code", "change_type", "change_price", "before_price", "after_price", "create_time", "modify_time") VALUES (6, '001', 10, '2.00', '20.00', '22.00', '2024-09-03 19:36:43', '2024-09-03 19:36:46');
INSERT INTO "public"."my_account_change_info" ("id", "account_code", "change_type", "change_price", "before_price", "after_price", "create_time", "modify_time") VALUES (13, '001', 10, '7.00', '22.00', '29.00', '2024-09-03 19:36:43', '2024-09-03 19:36:46');
INSERT INTO "public"."my_account_change_info" ("id", "account_code", "change_type", "change_price", "before_price", "after_price", "create_time", "modify_time") VALUES (24, '001', 10, '15.00', '29.00', '44.00', '2024-09-03 19:36:43', '2024-09-03 19:36:46');
INSERT INTO "public"."my_account_change_info" ("id", "account_code", "change_type", "change_price", "before_price", "after_price", "create_time", "modify_time") VALUES (35, '001', 10, '-2.00', '44.00', '42.00', '2024-09-03 19:36:43', '2024-09-03 19:36:46');
INSERT INTO "public"."my_account_change_info" ("id", "account_code", "change_type", "change_price", "before_price", "after_price", "create_time", "modify_time") VALUES (40, '001', 10, '-9.00', '42.00', '33.00', '2024-09-03 19:36:43', '2024-09-03 19:36:46');
INSERT INTO "public"."my_account_change_info" ("id", "account_code", "change_type", "change_price", "before_price", "after_price", "create_time", "modify_time") VALUES (44, '001', 10, '22.00', '33.00', '55.00', '2024-09-03 19:36:43', '2024-09-03 19:36:46');

数据准备如下:

3  解决方法

从程序的角度看的话,肯定能实现。比如在 id = 13 的后边,加入一条数据,那么 id = 13 后边的数据都要修复。

首先你的数据肯定要有流水性质(也就是先后) 这里的流水性质可以比如主键的自增或者主键的大小或者创建时间或者某个流水号,也就是要能知道记录的先后顺序。比如我这里的表 id 来体现的,id = 13 的前一条变动,肯定是小于 13 里边的最大的 id 也就是 6,后一条变动是大于 13 的里边最小的一条即 24。

那么从程序的角度,首先判断一下要变动的范围 id > 13,即24、35、40、44。那么第一条变动的 before_price 又要取决于上一条的 after_price。

所以每次处理都要 1个起始记录 + 变动记录,即使数据量很大,我们也可以采用分页的方式,每次处理该页的数据 + 该页的前一条数据即(该页起始记录)。 

每页的处理逻辑就是先按照流水号进行升序排序,然后第一个记录的 before_price 取该页起始记录的 after_price,并重新算出第一个记录的 after,然后剩下的记录就是 before = 前一个的 after,重新计算出该记录的 after 即可,最后保存该页的变动。

我想的是能不能直接通过 SQL 来修复呢?我们本节就来试试,看看能不能行:

第一步:我们先往 id = 13 的后边加入一条数据:

第二步:首先给变动范围的数据进行编号(为什么要编号 一是因为要可能你的是流水号那种带前缀编码什么的没有规律,二是因为编好号这种1 2 3 4等等这种方便数据处理)

SELECT
 t1.id,
 t1.account_code,
 t1.change_type,
 t1.change_price,
 t1.before_price,
 t1.after_price,
 t1.create_time,
 t1.modify_time,
 ROW_NUMBER() OVER (ORDER BY id) AS rownum
FROM my_account_change_info t1
WHERE t1.account_code = '001' and t1.change_type = 10 and id >= 12

那么我们变动范围的数据就查询出来了:

第二步:进行初次拼接

with base_info as (
SELECT
 t1.id,
 t1.account_code,
 t1.change_type,
 t1.change_price,
 t1.before_price,
 t1.after_price,
 t1.create_time,
 t1.modify_time,
 ROW_NUMBER() OVER (ORDER BY id) AS rownum
FROM my_account_change_info t1
WHERE t1.account_code = '001' and t1.change_type = 10 and id >= 12
)
select
t1.id,
t1.change_price,
t1.before_price,
t1.after_price,
t1.rownum,
t2.change_price,
t2.before_price,
t2.after_price,
t2.rownum,
t2.after_price 新的before,
t2.after_price + t1.change_price 新的after
from 
base_info t1
left join base_info t2 on t1.rownum = t2.rownum + 1
order by t1.id

看来这么写不行,思路有点问题,应该直取,即然我都知道差值了,那么后边的记录岂不是 before、after 都加上那条新插入的 change 是不是就可以了,还编什么号啊,再看看我新写的这个:

with base_info as (
SELECT
 t1.id,
 t1.account_code,
 t1.change_type,
 t1.change_price,
 t1.before_price,
 t1.after_price,
 t1.create_time,
 t1.modify_time,
 -- 新插入记录的变动数量
 1 change_insert 
FROM my_account_change_info t1
WHERE t1.account_code = '001' and t1.change_type = 10 and id > 12
)
select
t1.id,
t1.change_price,
t1.before_price,
t1.after_price,
-- 该记录的 before after 都加上新插入的那条变动数量
t1.before_price + t1.change_insert 新的before,
t1.after_price + t1.change_insert 新的after
from 
base_info t1
order by t1.id

是不是这样就行了:

那么都查出来了。更新的语句就简单了,比如直接拼出来更新的语句来:

with base_info as (
SELECT
 t1.id,
 t1.account_code,
 t1.change_type,
 t1.change_price,
 t1.before_price,
 t1.after_price,
 t1.create_time,
 t1.modify_time,
 -- 新插入记录的变动数量
 1 change_insert 
FROM my_account_change_info t1
WHERE t1.account_code = '001' and t1.change_type = 10 and id > 12
)
select
t1.id,
t1.change_price,
t1.before_price,
t1.after_price,
-- 该记录的 before after 都加上新插入的那条变动数量
t1.before_price + t1.change_insert 新的before,
t1.after_price + t1.change_insert 新的after,
concat('update my_account_change_info set before_price=', t1.before_price + t1.change_insert, ', after_price=', t1.after_price + t1.change_insert, ' where id = ', t1.id, ';') sql
from 
base_info t1
order by t1.id

如果数据量大的话,我们可以直接创个临时表,把查出来的数据都塞进临时表,然后根据 id 进行连表更新是不是也可以,太大的话再加个范围条件多执行几次。

那么更改完后的数据如何做验证呢?我们也小写一下:

 

 

4  小结

好啦,本节就记录到这里哈,是我想复杂了,直接每个记录给 before、after 加上变动数量即可,有更好的方法的话,欢迎指点哈。

标签:account,记录,price,after,t1,流水,id,数据库,change
From: https://www.cnblogs.com/kukuxjx/p/18395331

相关文章

  • 利用LangChain构建MySQL数据库问答代理
    引言随着自然语言处理技术的飞速发展,尤其是大型语言模型(LLM)的应用日益广泛,人们对于如何更高效地与这些模型交互产生了浓厚的兴趣。LangChain是一个旨在简化与语言模型集成的开源框架,它使得开发者能够轻松地构建出强大的应用程序。本文将介绍如何使用LangChain结合MySQL数据......
  • 达梦数据库的系统视图v$ifun_arg
    达梦数据库的系统视图v$ifun_arg在达梦数据库(DMDatabase)中,V$IFUN_ARG系统视图提供了关于存储函数(或存储过程)参数的详细信息。它是与函数参数相关的系统表,可以帮助数据库管理员和开发人员查看和管理数据库中所有函数参数的信息。使用场景参数管理:查看数据库中所有存......
  • docker容器实验记录(一)
    容器没有父进程,PID==1是所有程序的根进程上帝进程死亡系统实例也就关闭了1.概述1.1技术起源Linux容器的起源-容器的起源可以追溯到1979年UNIX系统中提供的chroot命令,容器的最初的设计目标是为了隔离计算机中的各类资源,以便降低软件开发、测试阶段的风险,或者充当蜜......
  • 数据库实验 SQL server sduwh caohai
    问题一:根据E-R图写出关系模式,标注主键和外键 学生关系模式:Student(StudentNum,StudentName,StudentSex,StudentAge,StudentPhone,StudentBrith,Speciality)其中主键为学号StudentNum,没有外键。课程关系模式:Course(Coursenum,CourseName,Credit,Classhour,ClassType)其中主键为......
  • 数据库系统 第33节 复杂查询优化
    复杂查询优化是数据库管理系统的优化器负责的一项关键任务,它涉及如何有效地处理那些包含多个表联接、子查询以及聚合函数的SQL语句。优化器的工作是生成一个执行计划,该计划尽可能高效地完成查询请求。下面我将简要介绍一些优化技巧及其背后的原理。索引使用索引可以极大地......
  • 数据库系统 第34节 数据库压缩
    数据库压缩是一种优化技术,它通过压缩数据库中的数据来减少所需的存储空间,并且可以加速数据的读取和写入操作(尤其是在带宽受限的情况下)。压缩通常是在数据写入磁盘之前执行,并在数据被读取到内存中之前解压。数据库管理系统(DBMS)通常提供不同的压缩选项,包括行级压缩和列级压缩......
  • 阿里云数据库使用感受--操作界面有点眼花缭乱 --3年的使用感受与反馈系列
    此篇是一个系列,专门剖析笔者在3年使用阿里云数据库中遇到的问题,并针对这些问题进行假设性的改进建议,大部分内容为真正使用过产品和服务后的感触,带有个人的一些主观观点,这也是不可避免的。此篇是本系列的第一篇,主要针对阿里云数据库系列产品中的产品界面进行一个使用后的主观的反馈......
  • 小琳AI课堂:向量数据库
    大家好,这里是小琳AI课堂!今天我们将探讨向量数据库的精彩世界。......
  • 阿里云数据库使用感受--客户服务问题深入剖析与什么是廉价客户 --3年的使用感受与反馈
    此篇是一个系列,专门剖析笔者在3年使用阿里云数据库中遇到的问题,并针对这些问题进行假设性的改进建议,大部分内容为真正使用过产品和服务后的感触,带有个人的一些主观观点,这也是不可避免的。此篇是本系列的第二篇,主要针对阿里云数据库系列产品中的产品客服服务长达3年的沟通交流产生的......
  • Java数据库连接池的优化与配置
    Java数据库连接池的优化与配置大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!数据库连接池是现代Java应用中不可或缺的一部分,它允许多个用户共享一个固定数量的数据库连接,显著提高了应用程序的性能和可扩展性。本文将探讨如何优化和配置Java数据库连......