首页 > 解决方案 > PLSQL:如何使用变量作为 table_name 创建游标

问题描述

我在 PLSQL 中尝试以下操作:

到目前为止,我试图将表名提取到一个变量中,然后遍历该变量,但它不起作用。

我有以下代码:

Declare
    var1 SYS_REFCURSOR;
    var2 varchar2(20);
    var3 varchar2(20);    
    ARCHIVE UTL_FILE.FILE_TYPE;
    Cursor cur2 IS SELECT TABLE_NAME FROM LIST_OF_TABLES; 

BEGIN   

ARCHIVO:=UTL_FILE.FOPEN('test_path','test.txt','W');

        for i in cur2 loop

        var2:= i.table_name;

        OPEN var1 for 'SELECT SKUID, CMRPRICE FROM '||VAR2;
        loop

       FOR C IN MICURSOR LOOP
  UTL_FILE.PUT_LINE(ARCHIVE,(''||C.SKUID||''||','||''||  C.CMRPRICE||''));
      END LOOP;
      UTL_FILE.FCLOSE(ARCHIVE);
        close var1;
        end loop;

END;

我希望获得与表格列表中的表格相同数量的文件

提前致谢

标签: oracleplsqlcursordynamic-sql

解决方案


我希望获得与表格列表中的表格相同数量的文件

在这种情况下,您需要为每个表打开不同的文件。

此外,您需要与变量命名(archivo| archivecur2| micursor)保持一致。一般来说,最好给变量提供有意义的名称,以反映它们的用法。var1和太容易混淆了var2

我认为您希望将文件的内容用引号括起来。我使用了双引号,这是 CSV 格式的标准。

此代码定义了一个 PL/SQL 记录类型,tgt_rec其投影与查询字符串的投影相匹配。我们打开一个动态引用游标,然后在循环中将记录提取到该记录变量中,直到游标耗尽。

declare
    file_handle utl_file.file_type;

    rc sys_refcursor;          
    cursor cur_tables is 
        select table_name from list_of_tables; 
    type tgt_rec is record ( skuid number, cmrprice number); 
    l_rec tgt_rec;

begin   

    << tables >>
    for i in cur_tables loop

        file_handle := utl_file.fopen('test_path', i.table_name||'.csv','w');

        open rc for 'select skuid, cmrprice from '||i.table_name;

        << table_rows >>
        loop

           fetch rc into l_rec;
           exit when rc%not found;

            utl_file.put_line(file_handle, '"'||l_rec.skuid||'","'||  l_rec.cmrprice||'"');

        end loop table_rows;        

        utl_file.fclose(file_handle);

        close rc;

    end loop tables;

end;
/

您可能不喜欢我对您的程序所做的外观更改(例如.csv文件扩展名),显然您可以自由地还原它们。毕竟,您是可执行代码的 Josiah Spode。


“你知道我是否可以使用相同的代码结构打印两个脚本的结果吗?”

这取决于。您可以将此匿名块转换为过程并将查询字符串 - 'select skuid, cmrprice from '- 作为参数传递。这将允许您改变执行的查询。但是,您仍然需要将结果集提取到某些内容中,并且该内容必须与投影的结构相匹配:相同的列数和相同的数据类型。所以这限制了你的灵活性。

幸运的是,PL/SQL 是一种合适的编程语言,具有很多功能(尽管不是 Java 风格的反射)。因此,您可以选择编写一些非常模块化的程序套件,其中包含用于通用事物的子例程,例如文件处理和用于查询特定数据处理的子例程。


推荐阅读