DB2 UDF 异常处理

Posted

技术标签:

【中文标题】DB2 UDF 异常处理【英文标题】:DB2 UDF Exception Handling 【发布时间】:2017-12-14 13:22:06 【问题描述】:

我正在努力处理 DB2 中用户定义函数 (UDF) 的异常处理。

我的问题的出发点是,我想选择具有特定格式的 varchar-timestamps 的表并将它们转换为时间戳数据类型。

以下 SQL 语句显示了一个积极的场景。所有 varchar-timestamps 都是有效的。 SELECT 会成功:

DROP TABLE TMP_TSP;
CREATE TABLE TMP_TSP (TSP_VARCHAR VARCHAR(100) NOT NULL UNIQUE);
INSERT INTO TMP_TSP VALUES ('2017-02-27');
INSERT INTO TMP_TSP VALUES ('2017-02-28');
SELECT TSP_VARCHAR, timestamp_format(TSP_VARCHAR, 'YYYY-MM-DD') TSP FROM tmp_tsp;

到目前为止一切顺利。但如果表包含无效的 varchar-timestamp,则 SELECT-Statement 失败:

DROP TABLE TMP_TSP;
CREATE TABLE TMP_TSP (TSP_VARCHAR VARCHAR(100) NOT NULL UNIQUE);
INSERT INTO TMP_TSP VALUES ('2017-02-27');
INSERT INTO TMP_TSP VALUES ('2017-02-28');
INSERT INTO TMP_TSP VALUES ('2017-02-29'); -- Invalid Date!
select TSP_VARCHAR, timestamp_format(TSP_VARCHAR, 'YYYY-MM-DD') TSP from tmp_tsp;

SELECT 语句的执行被以下错误消息中断:

[错误代码:-20448,SQL状态:22007]“2017-02-29”不能 使用格式字符串“YYYY-MM-DD”解释 TIMESTAMP_FORMAT 函数.. SQLCODE=-20448, SQLSTATE=22007

我正在寻找一种解决方案来选择那些时间戳异常安全,这意味着,如果 varchar-timestamp 有效,则应将其转换为时间戳,如果它无效,例如“2017-02-29”,应该返回 null。 SELECT 语句应具有以下结果:

2017-02-27 2017-02-27 00:00:00

2017-02-28 2017-02-28 00:00:00

2017-02-29 无效

我尝试创建一个 UDF,它封装了函数 timestamp_format 并添加了一些异常处理逻辑,例如通过声明继续处理程序。不幸的是,直到现在我都没有成功。

我正在使用 DB2/LINUXX8664 10.5.7。

也许你能帮忙?!非常感谢!

【问题讨论】:

【参考方案1】:

我不明白您为什么认为需要使用 TIMESTAMP_FORMATVARCHARTSP_VARCHAR 转换为 VARCHAR,而且我无法告诉您 UDF 有什么问题,因为您选择不发布它的来源或你得到的错误,但它应该看起来像这样:

create or replace function to_timestamp_safe (
  str varchar(100),
  fmt varchar(100)
) 
returns timestamp 
deterministic 
no external action contains sql 
begin 
  declare continue handler for sqlstate '22018' -- on conversion error
    return null; 
  return to_timestamp(str, fmt); 
end

然后您需要在查询中使用它:

select 
  TSP_VARCHAR, 
  timestamp_format(to_timestamp_safe(TSP_VARCHAR, 'YYYY-MM-DD'), 'YYYY-MM-DD') TSP 
from tmp_tsp;

【讨论】:

【参考方案2】:

感谢 mustaccio!我的核心问题是我无法执行这个创建函数语句。但是现在我找到了解决办法:让文件tmp.sql包含以下语句

create or replace function to_timestamp_safe (
  str varchar(100),
  fmt varchar(100)
) 
returns timestamp 
deterministic 
no external action contains sql 
begin 
  declare continue handler for sqlstate '22007' -- on conversion error
    return null;
  return to_timestamp(str, fmt);
end
@

然后我可以使用以下命令在 DB2 CLP 中执行它:

db2 -td@ -vf  tmp.sql

【讨论】:

【参考方案3】:

这是我的解决方案,不需要 UDF

SELECT 
 XMLCAST(XMLQUERY('if (. castable as xs:date) then . else ()'
  PASSING '2017-02-29') AS DATE)
FROM SYSIBM.SYSDUMMY1

使用XQUERY 测试有效日期,返回传递的值,否则返回一个空元素,该元素转换为NULL

【讨论】:

以上是关于DB2 UDF 异常处理的主要内容,如果未能解决你的问题,请参考以下文章

db2 存储过程 异常处理

从 DB2 存储过程出口处理程序传播默认 SQL 异常

关于db2处理特殊字段出现异常java.io.charConversionException

DB2 SQL 错误:jpa 分页项阅读器抛出 SQLCODE=-270 异常

Hive UDF - Java 字符串转换异常

SQL UDF 中的错误处理