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

Snowflake中JS存储过程日期校验陷入循环问题求助

Snowflake JavaScript存储过程死循环问题修复

我尝试在Snowflake中创建一个JavaScript存储过程,用于校验当月1日是否为银行假日或周末,若是则将其调整为下一个工作日,但该存储过程目前陷入了死循环。银行假日数据存储在calender表中,需要校验日期是否匹配表中记录,匹配则取下一个工作日。

原代码

create or replace procedure check_dt(run_dt DATE)
    returns string
    language javascript
    execute as caller
    as

    $$

    function batch_date(ts){

      var a = new Date(ts);
      var dt = new Date(a.setDate(1));
      var flag = false;
      
       while(flag==false){
            var sql_stment = `select 1 from calender where bh_date = date'` + dt.toLocaleDateString() + `'`;
            var result = snowflake.execute({sqlText: sql_stment});

                while(result.next()){
                    if(result.getColumnValue(1) == 1){
                        dt.setDate(dt.getDate() + 1);    
                    }
                    else if (dt.getDay() == 0){
                        dt.setDate(dt.getDate() + 1);
                    }
                    else if(dt.getDay() == 6){
                        dt.setDate(dt.getDate() + 2);
                    }
                    else{
                      flag = true;
                      break;
                    }   
                }
    }
       
 
    
    var batch_dt = batch_date(RUN_DT);
    
    return batch_dt;
    $$;

问题分析

  1. 日期格式不兼容:dt.toLocaleDateString()生成的日期格式依赖环境地区设置,可能和Snowflake默认的YYYY-MM-DD格式不匹配,导致查询calender表始终无结果,无法触发后续逻辑。
  2. 循环逻辑缺陷:当日期不是银行假日时,result.next()返回false,内层while循环完全不执行,既不会检查周末状态,也不会设置flag=true,外层while循环因此无限运行。
  3. 函数无返回值:batch_date函数未返回处理后的日期,最终存储过程返回undefined。
  4. 未循环校验新日期:原逻辑中日期推后后,没有重新校验新日期是否仍为假日或周末,可能导致结果不符合预期。

修复后的代码

create or replace procedure check_dt(run_dt DATE)
    returns string
    language javascript
    execute as caller
    as
    $$
    function batch_date(ts) {
        // 构造当月1日的Date对象,避免setDate的边界问题
        var a = new Date(ts);
        var dt = new Date(a.getFullYear(), a.getMonth(), 1);
        var flag = false;

        while (!flag) {
            // 统一生成YYYY-MM-DD格式的日期字符串,适配Snowflake DATE类型
            var formattedDt = `${dt.getFullYear()}-${String(dt.getMonth() + 1).padStart(2, '0')}-${String(dt.getDate()).padStart(2, '0')}`;
            // 查询当前日期是否为银行假日
            var sqlStmt = `SELECT 1 FROM calender WHERE bh_date = DATE('${formattedDt}')`;
            var result = snowflake.execute({ sqlText: sqlStmt });
            
            var isBankHoliday = result.next(); // 有结果则说明是银行假日

            if (isBankHoliday) {
                // 银行假日,推后1天
                dt.setDate(dt.getDate() + 1);
            } else if (dt.getDay() === 0) { // 周日(getDay()返回0)
                // 周日推后1天到周一
                dt.setDate(dt.getDate() + 1);
            } else if (dt.getDay() === 6) { // 周六(getDay()返回6)
                // 周六推后2天到周一
                dt.setDate(dt.getDate() + 2);
            } else {
                // 是工作日,退出循环
                flag = true;
            }
        }
        // 返回格式化后的工作日日期字符串
        return `${dt.getFullYear()}-${String(dt.getMonth() + 1).padStart(2, '0')}-${String(dt.getDate()).padStart(2, '0')}`;
    }

    var batchDt = batch_date(RUN_DT);
    return batchDt;
    $$;

修改点说明

  • 统一日期格式:手动构造YYYY-MM-DD格式字符串,彻底避免toLocaleDateString()的地区差异问题,确保和Snowflake的DATE类型兼容。
  • 重构循环逻辑:通过result.next()直接判断是否为银行假日,去掉冗余的内层循环,保证每次循环都能完整检查当前日期的状态。
  • 添加返回值:在batch_date函数末尾返回处理后的日期字符串,确保存储过程能输出正确结果。
  • 完整循环校验:每次推后日期后,重新进入循环校验新日期,直到找到第一个符合要求的工作日为止。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 18:50:41