2016-08-15 69 views
1

在Oracle PL/SQL中,我运行了一个查询,并试图逐一读取每一列的每一列,以便我可以用分隔符(硬格式要求)。该脚本用于多个不同大小的表格,因此预先不知道列的数量。我用如何通过ID或索引号引用列

SELECT COUNT(column_name) INTO NumColumns FROM all_tabs_cols 
WHERE table_name = Table_Array(i); 

其中Table_Array已被定义。这是一个for循环的中间,并已成功地获得了一个列的总数。 Table_Cursor是一个SELECT *语句。在此之后,我试图做类似

FOR j IN 0..NumColumns-1 LOOP 
    FETCH TABLE_CURSOR.column(j) INTO DataValue; 
    DBMS_OUTPUT.PUT(DataValue || '/'); 
END LOOP 

上面是伪代码。它阐明了我所追求的概念。我不知道PL/SQL是否足够了解如何获得像这样的值。我也担心在执行此操作时意外推进游标。我怎样才能完成这项任务?

+0

谁不只是使用LISTAGG或其他聚合函数? – OldProgrammer

+0

这不是你应该如何使用SQL - SQL是基于设置 - 只要你看看你有麻烦。 – Hogan

+0

@霍根,我很害怕这个。那么,什么是更好的方式来获取这些信息呢? – SandPiper

回答

2

您必须使用某种形式的动态SQL。这里有一个简单的例子:

它构建SQL语句,它将从你想要的表中选择'/'分隔列。然后它使用动态SQL来运行该SQL语句。

DECLARE 
    p_table_name VARCHAR2(30) := 'DBA_OBJECTS'; 
    l_sql VARCHAR2(32000); 

    TYPE varchar2tab IS TABLE OF VARCHAR2(32000); 
    l_array varchar2tab; 

BEGIN 
    SELECT 'SELECT ' || listagg(column_name,' ||''/''||') within group (order by column_id) || ' FROM ' || owner || '.' || table_name || ' WHERE ROWNUM <= 100' 
    INTO l_sql 
    FROM dba_tab_columns 
    where table_Name = 'DBA_OBJECTS' 
    group by owner, table_Name; 

    EXECUTE IMMEDIATE l_sql BULK COLLECT INTO l_array; 

    FOR i in l_array.first .. l_array.last LOOP 
    dbms_output.put_line(l_array(i)); 
    END LOOP; 
END; 
+0

这就像一个冠军。我改变的唯一的事情是在运行EXECUTE IMMEDIATE之前将整个l_sql放在一起作为单个字符串。非常感谢你! – SandPiper

+0

不客气。确保你添加了适当的错误处理。 Oracle行可以(超过!)长于32,000个字节。而且,这对于某些数据类型的表(例如'LONG')不起作用。 –

+0

我仍在学习SQL。为了我的好奇心,为什么它不适用于LONG数据类型?还有其他什么? – SandPiper

0

这是你的代码应该是什么样子:

SELECT F1 || ', ' || F2 || ', ' || ... || ', ' || FN 
FROM TABLE 

没有循环


这里是你如何生成不使用循环代码。 请注意,如果您想要,可以取出where语句并生成整个数据库的代码。 首先测试一个表格。

SELECT 'SELECT '|| LISTAGG(COLUMN_NAME, ' || '', '' || ') || ' FROM '||TABLE_NAME as sql_stm 
FROM ALL_TAB_COLUMNS 
WHERE TABLE_NAME='tablename' 
GROUP BY TABLE_NAME; 
+0

所以你的意思是说,如果他有1000张桌子,他必须按照上面的方式每次做到这一点。我希望你明白我的观点。 – XING

+0

这没有帮助。我的问题与@Raj_Te完全相同。我有很多表,表结构偶尔会改变。我无法控制这一点。我必须使用动态SQL脚本来获取它。我不知道表列名称是什么,这就是为什么我需要通过索引来引用它。 – SandPiper

+1

**正确**编写一些生成上述代码的sql。不要使用循环。循环很慢。 – Hogan