用于将数据导出为 .csv 格式的 PLSQL 脚本工作正常。我正在寻找一个文件,其中所有数据都将以正确的格式出现

Posted

技术标签:

【中文标题】用于将数据导出为 .csv 格式的 PLSQL 脚本工作正常。我正在寻找一个文件,其中所有数据都将以正确的格式出现【英文标题】:PLSQL script for exporting data into .csv format its working fine. I am looking for one file in which all data will come in proper format 【发布时间】:2019-08-23 09:38:00 【问题描述】:

我有一个用于将数据导出为 .csv 格式的 PL-SQL 脚本,它工作正常。我正在寻找一个 .csv 文件(我可以以 excel 格式打开),其中所有数据都将以正确的格式出现。

在现有代码中,它要求输入开始、结束日期和表名。但它会为一个表名创建一个文件。我想要相同的文件,其中包含用户提供的表格数据作为输入。

工作 PLSQL 脚本:


DECLARE
startdate DATE := to_date('&Enter_Start_Date', 'DD/MM/YYYY');
enddate DATE   := to_date('&Enter_End_Date', 'DD/MM/YYYY');
v_file            UTL_FILE.FILE_TYPE;
 CURSOR c1 IS
    SELECT TO_CHAR(createstampa2,'YYYY-MM-DD') as createdate,
    COUNT(createstampa2) as objectcount
    FROM &table_name lc -- It will prompt me for entering single table name only I want to give multiple table names here
    WHERE ( lc.createStampA2   >= to_date(startdate)
    AND lc.createStampA2        < to_date(enddate) )
    HAVING COUNT(createstampa2) > 1
    GROUP BY TO_CHAR(createstampa2,'YYYY-MM-DD')
    ORDER BY COUNT(createstampa2) DESC; 

BEGIN

    v_file := UTL_FILE.FOPEN(location     => 'XSDDIR',
                             filename     => 'GIVE_FILE_NAME_HERE'||TO_CHAR(SYSDATE,'DD_MM_YYYY')||'.csv',
                             open_mode    => 'w',
                             max_linesize =>10000);

    FOR rec IN c1 LOOP
    DBMS_OUTPUT.PUT_LINE('createdate::'||rec.createdate);
    DBMS_OUTPUT.PUT_LINE('objectcount::'||rec.objectcount);

        UTL_FILE.PUT_LINE(v_file,
                          rec.createdate    || ',' ||
                          rec.objectcount);
    END LOOP;

    UTL_FILE.FCLOSE(v_file);

EXCEPTION      
    WHEN OTHERS THEN
    UTL_FILE.FCLOSE(v_file);
    DBMS_OUTPUT.PUT_LINE('Error Occured::'||SQLERRM);
    RETURN;
END;

预期输出应为以下格式(.csv 文件):

【问题讨论】:

我看起来就像每当我得到第三个表名提示时,我需要那个值并想在 Excel 中输入 DBMS_OUTPUT.PUT_LINE('Entered table name');然后特定表的数据再次将跳过 1 行,对于另一个表数据,它将追加。我在上面的屏幕截图中显示了预期的输出。这可能吗? 【参考方案1】:

以追加模式打开文件:

v_file := UTL_FILE.FOPEN(location => 'XSDDIR', 文件名 => 'GIVE_FILE_NAME_HERE'||TO_CHAR(SYSDATE,'DD_MM_YYYY')||'.csv', open_mode => 'a', max_linesize =>10000);

【讨论】:

感谢 btpys 的回复,我正在寻找第三次提示输入表名的时间,然后我需要该值并希望在 excel 中输入: DBMS_OUTPUT.PUT_LINE('Entered table name') ;然后特定表的数据再次将跳过 1 行,对于另一个表数据,它将追加。 'a' 正在与我合作,感谢您的帮助。 不知道如果我理解正确......你可以使用这个:dbms_output.put_line ('Table ' || '&table_name');【参考方案2】:

读取内联的 cmets(在代码之间),我可以理解您希望将 multiple tablename 作为输入参数传递,并且应该在查询中使用那些传递的输入 table获取记录并将其写入 csv 文件。

注意这个查询是错误的: --Having子句出现在Group by之后

SELECT TO_CHAR(createstampa2,'YYYY-MM-DD') as createdate,
    COUNT(createstampa2) as objectcount
    FROM &table_name lc -- It will prompt me for entering single table name only I want to give multiple table names here
    WHERE ( lc.createStampA2   >= to_date(startdate)
    AND lc.createStampA2        < to_date(enddate) )
    HAVING COUNT(createstampa2) > 1   ---<<<<<<<< Having clause comes after Group by
    GROUP BY TO_CHAR(createstampa2,'YYYY-MM-DD')
    ORDER BY COUNT(createstampa2) DESC; 

您可以使用 Oracle PLSQL 表和集合来做到这一点,如下所示: 阅读内联的 cmets 以了解更多信息。

 DECLARE
    startdate DATE := to_date('&Enter_Start_Date', 'YYYY-MM-DD');
    enddate DATE   := to_date('&Enter_End_Date', 'YYYY-MM-DD');
    v_file            UTL_FILE.FILE_TYPE;
    --passing multiple tablenames at runtime
    var   sys.odcivarchar2list := sys.odcivarchar2list(&table1, &table2, &table3); 

    -- Type of date and count to hold records
    Type var_dt is table of DATE;
    v_date  var_dt:=var_dt();

    Type var_cnt is table of number;
    v_cnt   var_cnt;

    v_sql   varchar2(500);
BEGIN
    v_file := UTL_FILE.FOPEN(location     => 'XSDDIR',
                             filename     => 'GIVE_FILE_NAME_HERE'||TO_CHAR(SYSDATE,'DD_MM_YYYY')||'.csv',
                             open_mode    => 'w',
                             max_linesize =>10000); 

    FOR i IN ( SELECT column_value col FROM TABLE ( var )) 
    LOOP            
    --Passing tablnames 
    v_sql:=
     q'[SELECT TO_DATE(createstampa2,'YYYY-MM-DD') as createdate,
              COUNT(createstampa2) as objectcount
       FROM  ]' || i.col ||
     q'[  WHERE 
       createstampa2       >= :startdate 
       AND   createstampa2 < :enddate
       group by TO_DATE(createstampa2,'YYYY-MM-DD') 
       HAVING  COUNT(createstampa2) > 1
       order by count ( createstampa2 ) desc]';                

        Execute immediate v_sql bulk collect into v_date , v_cnt using startdate,enddate;  

       FOR rec IN 1..v_date.count
       LOOP
        DBMS_OUTPUT.PUT_LINE('createdate::'||v_date(rec));
        DBMS_OUTPUT.PUT_LINE('objectcount::'||v_cnt(rec));

        UTL_FILE.PUT_LINE(v_file,v_date(rec) || ',' ||v_cnt(rec));           

        END LOOP;

    END LOOP;

    UTL_FILE.FCLOSE(v_file);

EXCEPTION      
    WHEN OTHERS THEN
    UTL_FILE.FCLOSE(v_file);
    DBMS_OUTPUT.PUT_LINE('Error Occured::'||SQLERRM);
    RETURN;
END;

演示:

**Code:**

DECLARE
    startdate DATE := to_date('&Enter_Start_Date', 'YYYY-MM-DD');
    enddate DATE   := to_date('&Enter_End_Date', 'YYYY-MM-DD');
    v_file            UTL_FILE.FILE_TYPE;
    --passing multiple tablenames at runtime
    var   sys.odcivarchar2list := sys.odcivarchar2list(&table1, &table2, &table3); 

    -- Type of date and count to hold records
    Type var_dt is table of DATE;
    v_date  var_dt:=var_dt();

    Type var_cnt is table of number;
    v_cnt   var_cnt;

    v_sql   varchar2(500);
BEGIN
   /* v_file := UTL_FILE.FOPEN(location     => 'XSDDIR',
                             filename     => 'GIVE_FILE_NAME_HERE'||TO_CHAR(SYSDATE,'DD_MM_YYYY')||'.csv',
                             open_mode    => 'w',
                             max_linesize =>10000); */

    FOR i IN ( SELECT column_value col FROM TABLE ( var )) 
    LOOP            
    --Passing tablnames 
    v_sql:=
     q'[SELECT TO_DATE(createstampa2,'YYYY-MM-DD') as createdate,
              COUNT(createstampa2) as objectcount
       FROM  ]' || i.col ||
     q'[  WHERE 
       createstampa2       >= :startdate 
       AND   createstampa2 < :enddate
       group by TO_DATE(createstampa2,'YYYY-MM-DD') 
       HAVING  COUNT(createstampa2) > 1
       order by count ( createstampa2 ) desc]';              

       Execute immediate v_sql bulk collect into v_date , v_cnt using startdate,enddate;  

       FOR rec IN 1..v_date.count
       LOOP
        DBMS_OUTPUT.PUT_LINE('createdate::'||v_date(rec));
        DBMS_OUTPUT.PUT_LINE('objectcount::'||v_cnt(rec));

       -- UTL_FILE.PUT_LINE(v_file,v_date(rec) || ',' ||v_cnt(rec));           

        END LOOP;

    END LOOP;

    --UTL_FILE.FCLOSE(v_file);

EXCEPTION      
    WHEN OTHERS THEN
    --UTL_FILE.FCLOSE(v_file);
    DBMS_OUTPUT.PUT_LINE('Error Occured::'||SQLERRM);
    RETURN;
END;

这是为了解释这个概念。我没有写任何文件,所以在演示中你会发现代码UTL 部分已注释。

SQL> /
Enter value for enter_start_date: 2019-08-01
old   2:     startdate DATE := to_date('&Enter_Start_Date', 'YYYY-MM-DD');
new   2:     startdate DATE := to_date('2019-08-01', 'YYYY-MM-DD');
Enter value for enter_end_date: 2019-08-31
old   3:     enddate DATE   := to_date('&Enter_End_Date', 'YYYY-MM-DD');
new   3:     enddate DATE   := to_date('2019-08-31', 'YYYY-MM-DD');
Enter value for table1: 'A'
Enter value for table2: 'B'
Enter value for table3: 'TEST'
old   6:     var   sys.odcivarchar2list := sys.odcivarchar2list(&table1, &table2, &table3);
new   6:     var   sys.odcivarchar2list := sys.odcivarchar2list('A', 'B', 'TEST');
createdate::19-AUG-03
objectcount::3
createdate::19-AUG-07
objectcount::2
createdate::19-AUG-15
objectcount::2

PL/SQL procedure successfully completed.

【讨论】:

感谢 XING 的回复,我看起来就像每当我会收到第三个表名提示时,我需要该值并想在 Excel 中输入类似 DBMS_OUTPUT.PUT_LINE('Entered table name') ;然后特定表的数据再次将跳过 1 行,对于另一个表数据,它将追加。我已经显示了预期的输出。这可能吗? @SwapnilGThaware 你执行了我的代码吗?它也在做同样的事情。它会要求输入表名,然后将数据导出到文件中。我强调一次传递 3 个表名,就像您提到要传递多个表名一样。读取内联 cmets 是的,我尝试按原样执行您的代码,但出现错误:错误报告:ORA-06550:第 6 行,第 56 列:PLS-00357:不允许表、视图或序列引用“MYTABLENAME”在这种情况下 ORA-06550:第 6 行,第 11 列:PL/SQL:忽略项目 ORA-06550:第 22 行,第 53 列:PLS-00320:此表达式类型的声明不完整或格式错误 ORA-06550:第 22 行,第 53 列:PL/SQL:ORA-00904:“VAR”:无效标识符 ORA-06550:第 22 行,第 16 列:PL/SQL:SQL 语句忽略 ORA -06550:第 27 行,第 18 列:PLS-00364:循环索引变量 'I' 使用无效 ORA-06550:第 25 行,第 5 列:PL/SQL:语句被忽略 06550。00000 -“第 %s 行,第 %s 列:\n%s" *原因:通常是 PL/SQL 编译错误。 *行动: @SwapnilGThaware 您的查询不正确,这就是您收到以下问题的原因。我不知何故没有检查您使用的查询。 Having 子句出现在 Group by 之后,在您的情况下则相反。请查看我更新的工作代码。

以上是关于用于将数据导出为 .csv 格式的 PLSQL 脚本工作正常。我正在寻找一个文件,其中所有数据都将以正确的格式出现的主要内容,如果未能解决你的问题,请参考以下文章

plsql导出csv数据是空白

Access数据表怎么导出.csv格式的文件并附加到oracle数据库?

plsql怎么导出csv

plsql导出cvs文件后数值为啥会变

求源码!PHP导出数据到csv文件

使用navicat或plsql导出csv格式,超过15位数字后面变成000(E+19)的问题