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

