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

如何用PL/SQL和C#将硬编码派生列转为动态自动化列

自动化每月客户收支汇总方案

核心优化方向

  • 动态计算目标月份:通过系统时间自动获取当前月份,推导需要处理的上月及当年1月至上月的区间,彻底替代硬编码的月份值
  • 动态生成SQL逻辑:用动态SQL替代固定列的PL/SQL脚本,自动适配上月的预算、差异、完成率字段,同时保留历史月份的收支数据
  • 代码参数化:C#端通过时间参数传递目标月份,不再手动修改代码中的月份常量

PL/SQL脚本自动化改造

1. 动态获取时间参数

先定义变量获取当前年、当前月、上月,同时处理1月对应上年12月的特殊情况:

DECLARE
    v_current_year NUMBER := EXTRACT(YEAR FROM SYSDATE);
    v_current_month NUMBER := EXTRACT(MONTH FROM SYSDATE);
    v_last_month NUMBER := v_current_month - 1;
    v_target_year NUMBER := CASE WHEN v_last_month = 0 THEN v_current_year - 1 ELSE v_current_year END;
    v_target_month NUMBER := CASE WHEN v_last_month = 0 THEN 12 ELSE v_last_month END;
BEGIN
    -- 后续逻辑基于上述变量展开
END;

2. 动态生成列与预算字段

替换硬编码的月份列,用循环生成1到上月的收支列,仅对上月追加预算、差异、完成率字段:

DECLARE
    v_column_list VARCHAR2(4000);
    v_month NUMBER;
BEGIN
    FOR v_month IN 1..v_last_month LOOP
        -- 普通月份仅取收支数据
        v_column_list := v_column_list || 'SUM(CASE WHEN MONTH = ' || v_month || ' THEN AMOUNT ELSE 0 END) AS "MON_' || v_month || '_AMOUNT",';
        -- 上月追加预算相关字段
        IF v_month = v_last_month THEN
            v_column_list := v_column_list || 'SUM(BUDGET_AMOUNT) AS "MON_' || v_month || '_BUDGET",'
                || 'SUM(AMOUNT - BUDGET_AMOUNT) AS "MON_' || v_month || '_DIFF",'
                || 'ROUND(SUM(AMOUNT)/SUM(BUDGET_AMOUNT)*100,2) AS "MON_' || v_month || '_COMPLETION_RATE",';
        END IF;
    END LOOP;
    -- 移除最后一个多余的逗号
    v_column_list := RTRIM(v_column_list, ',');
    
    -- 动态执行查询或更新逻辑
    EXECUTE IMMEDIATE 'SELECT ' || v_column_list || ' FROM YOUR_TABLE WHERE YEAR = ' || v_current_year;
END;

3. PBT汇总自动追加

动态判断上月数据是否已加入PBT汇总,若未则自动插入:

-- 检查上月数据是否存在,不存在则插入
IF NOT EXISTS (SELECT 1 FROM PBT_SUMMARY WHERE YEAR = v_target_year AND MONTH = v_target_month) THEN
    INSERT INTO PBT_SUMMARY (YEAR, MONTH, AMOUNT, BUDGET, DIFF, COMPLETION_RATE)
    SELECT v_target_year, v_target_month, SUM(AMOUNT), SUM(BUDGET_AMOUNT), SUM(AMOUNT-BUDGET_AMOUNT), ROUND(SUM(AMOUNT)/SUM(BUDGET_AMOUNT)*100,2)
    FROM YOUR_TABLE WHERE YEAR = v_target_year AND MONTH = v_target_month;
END IF;

C#代码优化

1. 动态计算目标月份

替换硬编码的月份,用系统时间自动推导:

// 获取上月的年和月
DateTime lastMonth = DateTime.Now.AddMonths(-1);
int targetYear = lastMonth.Year;
int targetMonth = lastMonth.Month;
int currentYear = DateTime.Now.Year;
// 生成当年1月至上月的月份范围
var monthsRange = Enumerable.Range(1, targetMonth == 12 ? 12 : targetMonth);

2. 参数化调用存储过程

将PL/SQL逻辑封装为存储过程,C#端传递年、月参数调用,不再手动修改SQL字符串:

using (SqlConnection conn = new SqlConnection(yourConnString))
{
    conn.Open();
    SqlCommand cmd = new SqlCommand("SP_AUTO_UPDATE_SUMMARY", conn);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("@CurrentYear", currentYear);
    cmd.Parameters.AddWithValue("@TargetYear", targetYear);
    cmd.Parameters.AddWithValue("@TargetMonth", targetMonth);
    cmd.ExecuteNonQuery();
}

3. 解决之前循环无效的问题

之前用DateTime.Now.Month-1循环无效,大概率是循环逻辑未结合动态列生成或数据库条件过滤。现在通过参数化+动态SQL的方式,直接基于计算出的月份范围生成对应逻辑,无需手动适配列名。


验证与调度

  • 测试:手动修改系统时间(如改为8月),执行脚本和代码,检查是否自动适配7月的预算字段、替换6月预算数据,且7月数据成功加入PBT汇总
  • 调度:将C#程序或PL/SQL脚本设置为每月1日自动执行(通过Windows任务计划或数据库Job)

内容的提问来源于stack exchange,提问作者Jonaθn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 12:39:49