Skip to Main Content
  • Questions
  • Load, Execute, Store Output of script into database.

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Brian.

Asked: June 06, 2006 - 5:13 pm UTC

Last updated: June 07, 2006 - 5:39 pm UTC

Version: 9.2.07

Viewed 1000+ times

You Asked

Hi Tom,

When new scripts are created by our engineering teams, I would like to store the content of those scripts in the database in a table, execute the script, capture the output, and store the output in the database as well.

Here's what I have so far:

SQL> create or replace directory SCRIPT_FILES as '/export/home/oracle/dbasql/TEST/scripts';

Directory created.

SQL> CREATE TABLE SCRIPT_CONTAINER
2 (
3 SCRIPT_NAME VARCHAR2(500) NOT NULL,
4 SCRIPT_CONTENT CLOB NOT NULL,
5 SCRIPT_OUTPUT CLOB,
6 RELEASE_VERSION VARCHAR2(8) NOT NULL,
7 SCRIPT_APPLIED VARCHAR2(1) NOT NULL,
8 RUN_DATE DATE NOT NULL,
9 RAN_BY VARCHAR2(70) NOT NULL
10 )
11 LOGGING
12 NOCOMPRESS
13 NOCACHE
14 NOPARALLEL
15 NOMONITORING;

Table created.

SQL> CREATE OR REPLACE procedure load_script_to_db(p_filename in varchar2)
2 as
3 l_clob clob;
4 l_bfile bfile;
5 begin
6 insert into script_container (script_name,script_content,release_version,script_applied,run_date,ran_by) val
ues ( p_filename,empty_clob(),'1','N',sysdate,'BLUCAS')
7 returning script_content into l_clob;
8 l_bfile := bfilename( 'SCRIPT_FILES', p_filename );
9 dbms_lob.fileopen( l_bfile );
10 dbms_lob.loadfromfile( l_clob, l_bfile, dbms_lob.getlength(l_bfile));
11 dbms_lob.fileclose( l_bfile );
12 end;
13 /

Procedure created.

SQL> exec load_script_to_db('test.sql');

PL/SQL procedure successfully completed.

SQL> set long 50000 pages 1000
SQL> select * from script_container;

SCRIPT_NAME
--------------------------------------------------------------------------------
SCRIPT_CONTENT
--------------------------------------------------------------------------------
SCRIPT_OUTPUT
--------------------------------------------------------------------------------
RELEASE_ S RUN_DATE
-------- - ---------
RAN_BY
----------------------------------------------------------------------
test.sql
--garbage test script
create table my_objects_db as select * from user_objects;
select count(1) from my_objects_db;
update my_objects_db set object_name=object_name where 1=0;
commit;
exit;


1 N 06-JUN-06
BLUCAS


SQL>


Thanks for the procedure to actually load the data from the text file into the CLOB column. I found that in one of your other posts. What I am thinking about is the following process:

1. Scripts delivered to directory.
2. Scripts loaded from directory into table flagged SCRIPT_APPLIED as 'N'.
3. Script then ran. I could use a simple "@" directive but what about using a job to run the PL/SQL as stored in the SCRIPT_CONTENT column?
4. Capture the output of the script even if no direct "spool on/off" commands are in the script.
5. Make the record sticky (cannot update/delete).

So, seeing I'm at steps 1 and 2, okay, I am looking for guidance on going the next few.

Thanks, Tom. I'm quite surprised I can post a question and I appreciate the amazing work you've done for the Oracle community.

Brian

and Tom said...

This is something you would normally use a tool like Enterprise Manager or something (there are dozens of them) to do.

They can have a repository where by you deposit scripts

And then schedule them to be executed on a recurring basis

And then route their output where ever.

Even APEX ( </code> http://htmldb.oracle.com/ <code>) has a simple implementation of this - you can upload your scripts into the database and then run them at the push of a button.


You will NOT be running the script from PLSQL until you re-implement sqlplus (a command line tool) in PLSQL yourself!


I strongly suggest you investigate off the shelf solutions rather than do it yourself.

What you would have to do to finish your job is:

a) read the script back out
b) save it to a file
c) invoke sqlplus against it, using redirection to capture the output (forget spool, that would be an entirely different, seriously hard problem to tackle - so they spooled to "x.my_file.whose.name.you.WILL.not.guess.so.there.lst" - now what??)
d) take file you just created and load it into the database


I think you would be better served using a tool that runs jobs for you.

Rating

  (4 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

A reader, June 07, 2006 - 12:08 pm UTC

"You will NOT be running the script from PLSQL until you re-implement sqlplus (a command line tool) in PLSQL yourself!"

--can you please elaborate what you mean by this?


Tom Kyte
June 07, 2006 - 3:22 pm UTC

question to you: how do you run a sqlplus plus script in plsql?



the answer is "you don't, because plsql isn't the command line client application called sqlplus"


Unless you write your own "parser" and execute engine for the script in plsql - you won't be running a "script" in plsql.

APEX did just that for example...

A reader, June 07, 2006 - 4:44 pm UTC

so are you just saying, the sql*plus commands (like set/spool etc.) in the script, will create issues within pl/sql? That's true, I agree. I somehow thought you were saying that there is a limitation for running sql scripts (lets say pure sql) from pl/sql (becauase of issues of output redirection)..

Tom Kyte
June 07, 2006 - 5:39 pm UTC

they have no meaning in plsql.

tell me, so you have a script. How would you even start to run it via plsql?

Just the simplest of scripts:

connect /
select * from dual;
exit;




you are so damn right!! Thank you.

A reader, June 08, 2006 - 10:16 am UTC


A reader, June 12, 2006 - 6:54 pm UTC


More to Explore

CLOB/BLOB/etc

Complete documentation on Securefiles and Large Objects here