2014-07-03 47 views
2

我正在编写一个将供应商表中的数据转换为本地表的过程,并且有许多从源表上的光标映射到目标表的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 - 我希望获得一个通用的程序/函数,可以安全地分配他们之间,截断多余字符。

+0

非常有趣的问题!我尝试了'sys.anydata' +'sys.anytype'组合,但目前还没有运气。我试着把'p_src'放到一个从'dual'中选择的引用游标中,并且通过'dbms_sql'描述游标列...也没有运气。到目前为止,我认为唯一的“优化”是你对最大字符串长度进行二分搜索而不是线性搜索。 :-) – nop77svk

+0

我也一直在研究'anydata'和'anytype',但是我还不太熟悉他们想要什么。其他一些与我一起工作的人也提出了二分法搜索 - 如果没有更好的选择,我肯定会实现这一点。 –

回答

1

我可以看到两种方法可以做到这一点 - 无论是

A)更改p_safe_mapper接受第三个参数定义的最大允许输出字符串大小

B)更改p_safe_mapper接受目标表和列名称,并使用它们在* _TAB_COLUMNS视图之一中查找最大大小。

分享和享受。

+0

感谢您的建议。关于选项A,我绝对可以做到这一点没有什么问题,但我试图避免硬编码的大小。关于选项B,有没有办法查询ROWTYPE或游标的大小数据的* _TAB_COLUMNS视图?不幸的是,我不是直接写入表格,而是写入这些其他中间容器。 –

+1

@TheDIMMReaper rowtype和cursor是PL/SQL结构,所以我不认为你会为它们找到任何元数据。相反,你必须知道表和列。 – user272735

+0

@ user272735谢谢,这是有道理的。有没有另外一种方法可以从PL/SQL端获得类似的数据,而不需要知道表? –