How to write into a file apart from UTL_FILE - oracle

I have written a program to write a file into a directory using utl_file.
sample script :
PROCEDURE XX_FILE_TRANS (X_RETCODE VARCHAR2,X_ERRBUF VARCHAR2)
IS
CURSOR ORG_CUR IS
SELECT
'"'||XTRO.IDENTIFIER||'","'||
XTRO.ORGANIZATION_CODE||'","'||
XTRO.NAME ||'","'||
XTRO.PARENT_CODE ||'","'||
XTRO.INDUSTARY_NUMBER ||'","'||
XTRO.STATUS||'","'||
XTRO.SEQUENCE||'"' "ORG_DATA"
FROM abc XTRO;
ORG_REC ORG_CUR%rowtype;
begin
begin
delete XXHCM.XXHR_TAL_REC_ORGANIZATION_hist
where 1 = 1
AND creation_date < TRUNC (SYSDATE - 60);
COMMIT;
EXCEPTION
when OTHERS
then
null;
end;
LOAD_archive_TABLE; -- call the history table procedure
DBMS_OUTPUT.PUT_LINE('start');
fileHandler := UTL_FILE.FOPEN('INTF_DIR_INBOUND', LC_OLF_ORG, 'W');
UTL_FILE.put_line(fileHandler, 'Identifier,OrgCode,OrgName,ParentCode,IndustryNumber,StatusDescription,Sequence');
FOR ORG_REC IN ORG_CUR
LOOP
UTL_FILE.put_line(fileHandler,ORG_REC.ORG_DATA);
END LOOP;
UTL_FILE.FCLOSE(fileHandler);
dbms_output.put_line('end');
EXCEPTION
WHEN UTL_FILE.INVALID_PATH THEN
FND_FILE.PUT_LINE(FND_FILE.LOG,' Invalid File Path');
UTL_FILE.FCLOSE(fileHandler);
dbms_output.put_line('1'||sqlerrm);
WHEN UTL_FILE.WRITE_ERROR THEN
FND_FILE.PUT_LINE(FND_FILE.LOG,' Write Permission on does not exist');
UTL_FILE.FCLOSE(fileHandler);
dbms_output.put_line('2'||sqlerrm);
WHEN UTL_FILE.INVALID_MODE THEN
FND_FILE.PUT(FND_FILE.LOG,'THE INVALID MODE OF DATA FILE');
UTL_FILE.FCLOSE(fileHandler);
dbms_output.put_line('3'||sqlerrm);
WHEN UTL_FILE.INVALID_OPERATION THEN
FND_FILE.PUT(FND_FILE.LOG,' THE FILE CANNOT BE OPENED AS REQUESTED.');
UTL_FILE.FCLOSE(fileHandler);
dbms_output.put_line('4'||sqlerrm);
WHEN UTL_FILE.INVALID_MAXLINESIZE THEN
FND_FILE.PUT(FND_FILE.LOG,'THE SPECIFIED MAXIMUM LINE SIZE IS TOO LARGE OR TOO SMALL.');
UTL_FILE.FCLOSE(fileHandler);
dbms_output.put_line('5'||sqlerrm);
WHEN UTL_FILE.ACCESS_DENIED THEN
FND_FILE.PUT(FND_FILE.LOG,'ACCESS TO THE DIRECTORY OBJECT IS DENIED.');
FND_FILE.PUT(FND_FILE.LOG,'OPERATING SYSTEM ERROR OCCURED DURING THE WRITE OPERATION.');
UTL_FILE.FCLOSE(fileHandler);
dbms_output.put_line('6'||sqlerrm);
WHEN UTL_FILE.CHARSETMISMATCH THEN
FND_FILE.PUT(FND_FILE.OUTPUT,'THIS FILE IS OPEN FOR NCHAR DATA.');
UTL_FILE.FCLOSE(fileHandler);
dbms_output.put_line('7'||sqlerrm);
END;
Now the server i have is not db server because of whch i cannot use UTL_FILE.
Is thee any another way than UTL_FILE to write into a file ?

You can create an EXTERNAL TABLE instead...
https://docs.oracle.com/cd/B19306_01/server.102/b14215/et_concepts.htm

Why not use sqlplus? Create a simple .sql file (my_script.sql) containing your SQL, with a few SET commands, something like:
SET FEEDBACK OFF;
SET ECHO OFF;
SET TERM OFF;
SET serveroutput on size unlimited;
SET linesize 30000
SET pagesize 0
SET head off
SET trims on
SET verify off
WHENEVER SQLERROR EXIT SQL.SQLCODE
SPOOL my_file.csv;
select
'MY_NUMBER_FIELD1,'||
'MY_VARCHAR_FIELD2,'||
'MY_VARCHAR_FIELD3'
from dual
UNION ALL
select
COL1||','||
'"'||replace(COL2, '"','""')||'",'||
'"'||replace(COL3, '"','""')||'"'
from MY_TABLE
/
Modify the SQL as needed. Place that sql file in a directory on a server of your choice, login to Oracle from that directory using sqlplus, and run:
#my_script.sql
The output file (my_file.csv) will be in the directory you logged in from. A sqlplus login script can be used to automate things as well (along with cron or task scheduler or other scheduling software).

Related

UNIQUE NAMES IN ORACLE PL/SQL

I have a procedure that converts the result of a specific query in a CSV File which is saved in a directory in the server. My question is that is there any way that i can generate unique names for the file every time i save it?
try this
-- not tested
select to_char( sysdate,'yyyymmddhh24miss' ) || '.txt' File_nm from dual;
spool &File_nm ;
-- run query
spool off;
If you create a SEQUENCE, you can increment the sequence each time you go to write your file.
DECLARE
l_filename VARCHAR2 (200);
BEGIN
SELECT 'somename_' || seq_name.NEXTVAL INTO l_filename FROM DUAL;
END;

Storing oracle output in ansible and checking with condition from the output of columns in oracle table

I want to store oracle output like table columns in a separate file and I need to check with columns based conditional statements.
I tried just execution of statements
I want to execute this PLSQL program
###############################
set serveroutput on declare v_sal number(10);
begin select sal into v_sal from emp where empno=7934;
if v_sal=1300 then update emp set sal=6666 where empno=7934;
end if;
end;
exit;
One more query
SQL> select name,OPEN_MODE from v$database;
NAME OPEN_MODE
--------- --------------------
TEST READ WRITE
I want to compare based on open_mode column when open_mode = READ WRITE, I want to execute one condition.

How to redirect 'dbms_output.put_line content' to log file from a TimesTen Stored Procedure

See the sample Timesten procedure below.
CREATE OR REPLACE PROCEDURE test_proc(employee_id IN NUMBER) AS
salary NUMBER;
BEGIN
SELECT emp_sal INTO salary FROM employee where emp_id = employee_id;
DBMS_OUTPUT.PUT_LINE('Employee Id:' || employee_id || ' Annual Income:' || salary*12);
END;
/
If I call the procedure from Command line interface(ttisql), dbms_output.put_line logs gets printed there only.
But I want to collect such debug logs to somewhere else in a log file. Whenever procedure get executed it should append these content to a file. Is there any possible way to do that?
If you are calling your procedure from ttisql as you've said you can use spool filepath and spool off to log any messages appeared on the screen. To append new information to the already existed log file just use APPEND option after filepath
spool c:\logfile.log append

How to redirect the output of DBMS_OUTPUT.PUT_LINE to a file?

I need to debug in pl/sql to figure times of procedures, I want to use:
SELECT systimestamp FROM dual INTO time_db;
DBMS_OUTPUT.PUT_LINE('time before procedure ' || time_db);
but I don't understand where the output goes to and how can I redirect it to a log file that will contain all the data I want to collect?
DBMS_OUTPUT is not the best tool to debug, since most environments don't use it natively. If you want to capture the output of DBMS_OUTPUT however, you would simply use the DBMS_OUTPUT.get_line procedure.
Here is a small example:
SQL> create directory tmp as '/tmp/';
Directory created
SQL> CREATE OR REPLACE PROCEDURE write_log AS
2 l_line VARCHAR2(255);
3 l_done NUMBER;
4 l_file utl_file.file_type;
5 BEGIN
6 l_file := utl_file.fopen('TMP', 'foo.log', 'A');
7 LOOP
8 EXIT WHEN l_done = 1;
9 dbms_output.get_line(l_line, l_done);
10 utl_file.put_line(l_file, l_line);
11 END LOOP;
12 utl_file.fflush(l_file);
13 utl_file.fclose(l_file);
14 END write_log;
15 /
Procedure created
SQL> BEGIN
2 dbms_output.enable(100000);
3 -- write something to DBMS_OUTPUT
4 dbms_output.put_line('this is a test');
5 -- write the content of the buffer to a file
6 write_log;
7 END;
8 /
PL/SQL procedure successfully completed
SQL> host cat /tmp/foo.log
this is a test
As an alternative to writing to a file, how about writing to a table? Instead of calling DBMS_OUTPUT.PUT_LINE you could call your own DEBUG.OUTPUT procedure something like:
procedure output (p_text varchar2) is
pragma autonomous_transaction;
begin
if g_debugging then
insert into debug_messages (username, datetime, text)
values (user, sysdate, p_text);
commit;
end if;
end;
The use of an autonomous transaction allows you to retain debug messages produced from transactions that get rolled back (e.g. after an exception is raised), as would happen if you were using a file.
The g_debugging boolean variable is a package variable that can be defaulted to false and set to true when debug output is required.
Of course, you need to manage that table so that it doesn't grow forever! One way would be a job that runs nightly/weekly and deletes any debug messages that are "old".
use
set serveroutput on;
for example:
set serveroutput on;
DECLARE
x NUMBER;
BEGIN
x := 72600;
dbms_output.put_line('The variable X = '); dbms_output.put_line(x);
END;
If you are just testing your PL/SQL in SQL Plus you can direct it to a file like this:
spool output.txt
set serveroutput on
begin
SELECT systimestamp FROM dual INTO time_db;
DBMS_OUTPUT.PUT_LINE('time before procedure ' || time_db);
end;
/
spool off
IDEs like Toad and SQL Developer can capture the output in other ways, but I'm not familiar with how.
In addition to Tony's answer, if you are looking to find out where your PL/SQL program is spending it's time, it is also worth checking out this part of the Oracle PL/SQL documentation.
Using UTL_FILE instead of DBMS_OUTPUT will redirect output to a file:
http://oreilly.com/catalog/oraclebip/chapter/ch06.html
As a side note, remember that all this output is generated in the server side.
Using DBMS_OUTPUT, the text is generated in the server while it executes your query and stored in a buffer. It is then redirected to your client app when the server finishes the query data retrieval. That is, you only get this info when the query ends.
With UTL_FILE all the information logged will be stored in a file in the server. When the execution finishes you will have to navigate to this file to get the information.
Hope this helps.
Its possible write a file directly to the DB server that hosts your database, and that will change all along with the execution of your PL/SQL program.
This uses the Oracle directory TMP_DIR; you have to declare it, and create the below procedure:
CREATE OR REPLACE PROCEDURE write_log(p_log varchar2)
-- file mode; thisrequires
--- CREATE OR REPLACE DIRECTORY TMP_DIR as '/directory/where/oracle/can/write/on/DB_server/';
AS
l_file utl_file.file_type;
BEGIN
l_file := utl_file.fopen('TMP_DIR', 'my_output.log', 'A');
utl_file.put_line(l_file, p_log);
utl_file.fflush(l_file);
utl_file.fclose(l_file);
END write_log;
/
Here is how to use it:
1) Launch this from your SQL*PLUS client:
BEGIN
write_log('this is a test');
for i in 1..100 loop
DBMS_LOCK.sleep(1);
write_log('iter=' || i);
end loop;
write_log('test complete');
END;
/
2) on the database server, open a shell and
tail -f -n500 /directory/where/oracle/can/write/on/DB_server/my_output.log
An old thread, but there is another alternative.
Since 9i you can use pipelined table function.
First, create a type as a table of varchar:
CREATE TYPE t_string_max IS TABLE OF VARCHAR2(32767);
Second, wrap your code in a pipelined function declaration:
CREATE FUNCTION fn_foo (bar VARCHAR2) -- your params
RETURN t_string_max PIPELINED IS
-- your vars
BEGIN
-- your code
END;
/
Replace all DBMS_OUTPUT.PUT_LINE for PIPE ROW.
Finally, call it like this:
SELECT * FROM TABLE(fn_foo('param'));
Hope it helps.
Try This:
SELECT systimestamp INTO time_db FROM dual ;
DBMS_OUTPUT.PUT_LINE('time before procedure ' || time_db);

Print text in Oracle SQL Developer SQL Worksheet window

I am using Oracle SQL (in SQLDeveloper, using the SQL Worksheet). I would like to print a statement before my select, such as
PRINT 'Querying Table1';
SELECT * from Table1;
What do I use to Print / show text output? It's not Print, because that gives me the error: Bind Variable Table1 is NOT DECLARED. DBMS_OUTPUT.PUT_LINE is an unknown command. (Obviously, I'm an inexperienced SQLDeveloper and Oracle user. There must be some synonym for Print, but I'm having trouble finding help on it without knowing what it is.)
for simple comments:
set serveroutput on format wrapped;
begin
DBMS_OUTPUT.put_line('simple comment');
end;
/
-- do something
begin
DBMS_OUTPUT.put_line('second simple comment');
end;
/
you should get:
anonymous block completed
simple comment
anonymous block completed
second simple comment
if you want to print out the results of variables, here's another example:
set serveroutput on format wrapped;
declare
a_comment VARCHAR2(200) :='first comment';
begin
DBMS_OUTPUT.put_line(a_comment);
end;
/
-- do something
declare
a_comment VARCHAR2(200) :='comment';
begin
DBMS_OUTPUT.put_line(a_comment || 2);
end;
your output should be:
anonymous block completed
first comment
anonymous block completed
comment2
PROMPT text to print
Note: must use
Run as Script (F5)
not
Run Statement (Ctl + Enter)
The main answer left out a step for new installs where one has to open up the dbms output window.
Then the script I used:
dbms_output.put_line('Start');
Another script:
set serveroutput on format wrapped;
begin
DBMS_OUTPUT.put_line('jabberwocky');
end;
You could set echo to on:
set echo on
REM Querying table
select * from dual;
In SQLDeveloper, hit F5 to run as a script.
You could put your text in a select statement such as...
SELECT 'Querying Table1' FROM dual;
For me, I could only get it to work with
set serveroutput on format word_wrapped;
The wraped and WRAPPED just threw errors: SQLPLUS command failed - not enough arguments
If I ommit begin - end it is error. So for me this is working (nothing else needed):
set serveroutput on;
begin
DBMS_OUTPUT.PUT_LINE('testing');
end;
If you don't want all of your SQL statements to be echoed, but you only want to see the easily identifiable results of your script, do it this way:
set echo on
REM MyFirstTable
set echo off
delete from MyFirstTable;
set echo on
REM MySecondTable
set echo off
delete from MySecondTable;
The output from the above example will look something like this:
-REM MyFirstTable
13 rows deleted.
-REM MySecondTable
27 rows deleted.

Resources