Can you help me write a procedure in Oracle to spo

2020-03-31 06:32发布

I am writing a procedure to create a CSV file with the data in an Oracle table. I used "spool filename;" but an error is coming. Can I use spool in PL/SQL?

6条回答
Evening l夕情丶
3楼-- · 2020-03-31 07:08

I think that there are better ways to implement this on Oracle 10g/11g, but this should work fine on Oracle 9i or higher:

CREATE OR REPLACE PROCEDURE prc_file_mult_column_generate(
p_file_dir         VARCHAR2, -- mandatory (Oracle directory name)
p_file_name     VARCHAR2, -- mandatory
p_sql_query        VARCHAR2, -- Multiple column SQL SELECT statement that needs to be executed and processed
p_delimiter     CHAR      -- column delimiter
)
AS

l_cursor_handle  INTEGER;
l_dummy              NUMBER;
l_col_cnt          INTEGER;
l_rec_tab            DBMS_SQL.DESC_TAB;
l_current_col      NUMBER(16);
l_current_line   VARCHAR2(2047);
l_column_value   VARCHAR2(300);

l_file_handle      UTL_FILE.FILE_TYPE;
l_print_text       VARCHAR2(100);
l_record_count   NUMBER(16) := 0;

BEGIN

   /* Open file for append*/
   l_file_handle := UTL_FILE.FOPEN(p_file_dir, p_file_name, 'a', 2047); --Append Mode, 2047 chars per line max, possibly increasable

   l_cursor_handle := DBMS_SQL.OPEN_CURSOR;
   DBMS_SQL.PARSE(l_cursor_handle, p_sql_query, DBMS_SQL.native);
   l_dummy := DBMS_SQL.EXECUTE(l_cursor_handle);

   /* Output column names and define them for latter retrieval of data */
   DBMS_SQL.DESCRIBE_COLUMNS(l_cursor_handle, l_col_cnt, l_rec_tab); -- get column names

   /* Append to file column headers */
   l_current_col := l_rec_tab.FIRST;
   IF (l_current_col IS NOT NULL) THEN
      LOOP
         DBMS_SQL.DEFINE_COLUMN(l_cursor_handle, l_current_col, l_column_value, 300);
         l_print_text := l_rec_tab(l_current_col).col_name || p_delimiter;
         UTL_FILE.PUT (l_file_handle, l_print_text);
         l_current_col := l_rec_tab.NEXT(l_current_col);
         EXIT WHEN (l_current_col IS NULL);
      END LOOP;
   END IF;
   UTL_FILE.PUT_LINE (l_file_handle,' ');

   /* Append data for each row */
   LOOP
      EXIT WHEN DBMS_SQL.FETCH_ROWS(l_cursor_handle) = 0; -- no more rows to be fetched

      l_current_line := '';
      /* Append data for each column */
      FOR l_current_col IN 1..l_col_cnt LOOP
         DBMS_SQL.COLUMN_VALUE (l_cursor_handle, l_current_col, l_column_value);
         l_print_text := l_column_value || p_delimiter;

         l_current_line := l_current_line || l_column_value || p_delimiter;
      END LOOP;
      l_record_count := l_record_count + 1;
      UTL_FILE.PUT_LINE (l_file_handle, l_current_line);
   END LOOP;

   UTL_FILE.FCLOSE (l_file_handle);
   DBMS_SQL.CLOSE_CURSOR(l_cursor_handle);

EXCEPTION
   WHEN OTHERS THEN

   -- Release resources
   IF DBMS_SQL.IS_OPEN(l_cursor_handle) THEN
      DBMS_SQL.CLOSE_CURSOR(l_cursor_handle);
   END IF;

   IF UTL_FILE.IS_OPEN (l_file_handle) THEN
      UTL_FILE.FCLOSE (l_file_handle);
   END IF;

   --RAISE ;
   DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.format_error_stack);

END;
/
查看更多
我欲成王,谁敢阻挡
4楼-- · 2020-03-31 07:11

Here are a couple of links you might find helpful:

A PL/SQL Tutorial and SQL*Plus User Guide (11g)

查看更多
Juvenile、少年°
5楼-- · 2020-03-31 07:19

If you only need the data in a cvs file you can do this:

create a sql file with the query like this:

set feedback off verify off heading off pagesize 0
select field1 || ',' || field2 ...  from table;
quit;
/

then call sqlplus from a terminal like this:

sqlplus -S user/password @file.sql> cvsfile.cvs
查看更多
叼着烟拽天下
6楼-- · 2020-03-31 07:21

No, SPOOL is a SQL Plus command so you would have to do this in SQL Plus:

spool myfile.txt
exec myproc
spool off

You would probably also need to set some values before starting the process e.g.

set pagesize 0 linesize 1000 trimspool on

... to get the correct formatting.

查看更多
Summer. ? 凉城
7楼-- · 2020-03-31 07:24

spool is a sqlplus command. it cannot be used in pl/sql.

it seems that you have been trying a variety of ways to get oracle to do your formatting and file saving. why not have your program that is calling the proc do this work for you?

查看更多
登录 后发表回答