PLSQL 在变量中存储具有未知数据类型的游标(使用 FETCH INTO)
Posted
技术标签:
【中文标题】PLSQL 在变量中存储具有未知数据类型的游标(使用 FETCH INTO)【英文标题】:PLSQL Store cursor with unknown data type in a variable (using FETCH INTO) 【发布时间】:2017-11-13 04:50:54 【问题描述】:我是 PLSQL 的新手,并尝试完成以下任务:遍历用户架构中的所有列并为每列输出唯一值。 我正在尝试使用嵌套游标,初始游标是每列,嵌套游标是每列的唯一值。我遇到的问题似乎是嵌套游标具有各种类型的值(取决于列)并且无法放入定义为 varchar2 的变量中。 This question 建议这应该可以工作,并且日期和数字变量将被隐式转换为字符。但是,我似乎无法让它工作,我的代码产生了以下错误:
ORA-06502:PL/SQL:数字或值错误。
我曾尝试(未成功)通过使用 to_char() 将光标强制为字符变量: 'FETCH TO_CHAR(row_cursor) INTO...' 这也不起作用。
有没有办法存储未知类型的数据以便输出?有没有更好的方法来列出架构中所有列的唯一值?
编辑:根据@Kaushik-Nayak 的评论,我深入研究了一些正在处理的列/表。一些内部 Oracle 视图似乎有已弃用的类型(我开始看到很多 ORA-00932: inconsistent datatypes: expected CHAR got LONG
)错误(导致我发现 this question)。为了解决这个问题,我为我想要分析的所有表添加了一个公共前缀(在本例中为“MY_”),并添加了一个 WHERE 子句,并在 SUBSTR() 函数的帮助下仅从具有公共前缀的表中获取列来自user_tab_columns
表。此更改解决了问题:
DECLARE
row_cursor SYS_REFCURSOR;
var_rowval VARCHAR2(4000);
BEGIN
FOR c IN (SELECT table_name, column_name FROM user_tab_columns WHERE SUBSTR(table_name, 1, 2) = 'MY')
LOOP
这是我的(原始)代码:
DECLARE
row_cursor SYS_REFCURSOR;
var_rowval VARCHAR2(500);
BEGIN
FOR c IN (SELECT table_name, column_name FROM user_tab_columns)
LOOP
OPEN row_cursor
FOR 'SELECT DISTINCT ' || c.column_name || ' FROM ' || c.table_name;
LOOP
FETCH row_cursor INTO var_rowval;
dbms_output.put_line(c.table_name || ', ' || c.column_name || ': ' || var_rowval );
EXIT WHEN row_cursor%NOTFOUND;
END LOOP;
CLOSE row_cursor;
END LOOP;
END;
【问题讨论】:
问题不在于数据类型,而在于大小。您可能有一个值大于 500 的列。您必须保持var_rowval
的大小足够大(可能是 4000)以容纳所有类型的列。但是,如果您有 CLOB
列,您可能仍然会遇到问题。因此,最好重新设计代码以避免此类错误。
与问题无关,但您不能以您使用的方式使用SYS_REFCURSOR
。首先纠正它。
【参考方案1】:
我在我的架构上运行了你的代码,它运行良好,没有任何错误。我的表有数据类型 varchar2、Number 和 Date 的列。正如所言 @Kaushik Nayak 请将变量“var_rowval(500)”的大小增加到 “var_rowval(4000)”。
还有一个建议,请不要对所有表运行此代码,因为当您使用 dbms_output.put_line() 打印它时,您会得到 缓冲区溢出错误。为了便于理解,您可以占用 2 到 3 个表并尝试打印这些列的不同值。
您想找到导致问题的列,下面是可以帮助您实现该目标的代码。
set serveroutput on
DECLARE
row_cursor SYS_REFCURSOR;
var_rowval VARCHAR2(500);
BEGIN
FOR c IN (SELECT * /*table_name, column_name*/ FROM user_tab_columns)
LOOP
begin
OPEN row_cursor
FOR 'SELECT DISTINCT ' || c.column_name || ' FROM ' || c.table_name;
LOOP
FETCH row_cursor INTO var_rowval;
dbms_output.put_line(c.table_name || ', ' || c.column_name || ': ' || var_rowval );
EXIT WHEN row_cursor%NOTFOUND;
END LOOP;
CLOSE row_cursor;
exception
when others then
dbms_output.put_line('Table Name:'||' '||c.table_name||' '||'column name'||c.column_name||','||'data type:'||' '||c.data_type);
EXIT;
end;
END LOOP;
END;
/
【讨论】:
以上是关于PLSQL 在变量中存储具有未知数据类型的游标(使用 FETCH INTO)的主要内容,如果未能解决你的问题,请参考以下文章
Oracle数据库存储过程中输出参数为自定义游标类型时,使用call或者exec调用时,用啥来给游标赋值
Oracle-4 - :超级适合初学者的入门级笔记:plsql,基本语法,记录类型,循环,游标,异常处理,存储过程,存储函数,触发器