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