我正在编写一个将供应商表中的数据转换为本地表的过程,并且有许多从源表上的光标映射到目标表的ROWTYPE
的分配。所有供应商的字符串列的大小定义为255,但我们的字符串列的定义更严格,通常只有30或50个字符。如果源表的字符串太长而目标行类型的列无法接受,则某些映射会抛出异常VALUE_ERROR
。自动截断超过目标字符串大小的源字符串
预期的结果是目标ROWTYPE
的列包含尽可能多的可容纳的部分,其余部分将被截断。我的第一本能就是简单地使用SUBSTR
并对最大尺寸进行硬编码,但必须有一个更加优雅和强大的解决方案。
我想出了一个解决方案(虽然它不给我温暖的模糊感觉)是以下过程,它只处理异常并重试映射。
PROCEDURE p_safe_mapper(p_dest IN OUT VARCHAR2, p_out IN VARCHAR2) IS
counter INTEGER := 0;
BEGIN
--only loop for as many characters are in the source string
WHILE counter < length(p_src) LOOP
BEGIN
--attempt to map, trimming COUNTER characters from the end of the source string. If it works, we're done.
p_dest := substr(p_src,
0,
length(p_src) - counter);
EXIT;
EXCEPTION
--else if we get an error, increment the counter to try again with the source string one character shorter.
WHEN value_error THEN
counter := counter + 1;
END;
END LOOP;
END;
我也考虑表列的大小查询ALL_TAB_COLUMNS
,但我不知道任何方式从具有ROWTYPE
那里。基本上,因为甲骨文显然知道我的变量的最大大小 - 无论他们ROWTYPEs
,游标,或普通老VARCHAR2s
- 我希望获得一个通用的程序/函数,可以安全地分配他们之间,截断多余字符。
非常有趣的问题!我尝试了'sys.anydata' +'sys.anytype'组合,但目前还没有运气。我试着把'p_src'放到一个从'dual'中选择的引用游标中,并且通过'dbms_sql'描述游标列...也没有运气。到目前为止,我认为唯一的“优化”是你对最大字符串长度进行二分搜索而不是线性搜索。 :-) – nop77svk
我也一直在研究'anydata'和'anytype',但是我还不太熟悉他们想要什么。其他一些与我一起工作的人也提出了二分法搜索 - 如果没有更好的选择,我肯定会实现这一点。 –