How to run sql scripts from a pl sql procedure - sql

I have a procedure like :
CREATE OR REPLACE PROCEDURE test is
BEGIN
DBMS_OUTPUT.PUT_LINE('This is a Test');
END;
I want to run some sql scripts stored in the current directory.
I could run them from sqlplus with '#scriptname.sql' but how can i do it from inside the procedure ? For ex:
CREATE OR REPLACE PROCEDURE test is
BEGIN
DBMS_OUTPUT.PUT_LINE('This is a Test');
#scriptname.sql
END;
This doesn't seem to work ! Is there a specific to run sql scripts from pl/sql procedures ?

You can't, in general, because the pl/sql is run in the database, on the server, and sqlplus is a client process. The server can't rely on even being on the same system as the client and its files, much less knowing anything about how to find the file the client is referring to. Even if the syntax were supported (and it isn't), your sql script would have to be on the server, in a location the server knew about and had access to.

Actually, you can do this in SQL*Plus - you just need to ensure the # is the first character on the line, e.g.:
CREATE OR REPLACE PROCEDURE test is
BEGIN
DBMS_OUTPUT.PUT_LINE('This is a Test');
#scriptname.sql
END;
SQL*Plus will read the entire contents of the script and insert it at that point in the procedure, then create the procedure as it is given. That means you can't have SQL*Plus commands in scriptname.sql. Also, there won't be any reference to #scriptname.sql in the actual procedure created on the database.

You could execute an OS command to start SQLPlus and have that execute the scripts. You can pass a filename into SQLplus at start up and it will execute it.
Google External Procedures and extproc or this article. Or something like call OS command with Java

You could write a Java Stored Procedure to open the file and return its contents as a String and then call Execute Immediate on the String.
Be VERY CAREFUL doing this though as any malicious sql in those files can do pretty much whatever it wants.

Even if there should be a solution, I would not recommend to to this. A PL/SQL procedure basically is a SQL script. Either
1. run your SQL scripts from outside the database, e.g. via shell script or
2. move the SQL code inside your procedure.

Related

Scheduling a query to run on a schedule that exports a CSV in SQL Developer

Good morning,
I am rather new to SQL and I've scoured the internet to try to find a solution to my issue to no avail. I've tried creating procedures, jobs, programs, credentials and schedules through the SQL Developer interface and modifying them as instructed by every article I could find on the subject and I can't seem to get this working.
I'd like to run the following SQL Script every 30 minutes from 0600 to 1700 Mon-Friday, so that it exports a CSV file every 30 minutes.
When I execute the script in SQL developer, it queries the database and saves the file just as intended, but no matter how many times I've tried to get it working on a schedule I can't seem to get t right.
Thanks in advance for the help!
SPOOL C:\Users\X\Documents\SQL\Uploads\X.CSV
SET SQLFORMAT CSV
SELECT
NAME_OF_PERSON
FROM DATABASE;
In versions lower than 12c, Oracle's DBMS_JOB and/or DBMS_SCHEDULER will schedule execution of a stored procedure. It can create a file, but you'll have to use UTL_FILE package to do that, not SPOOL.
As you're on Oracle 12c, its DBMS_SCHEDULER now offers a new job type - SQL_SCRIPT, which lets you schedule a .SQL script. It means that code you posted should be stored as a file. I can't create an example on my 11gXE, but here's a link to ORACLE-BASE site: https://oracle-base.com/articles/12c/scheduler-enhancements-12cr1 and script copied from it which shows how to do that:
CONN test/test#pdb1
-- Create a job with a SQL*Plus script defined in-line,
-- including an explicit connect.
SET SERVEROUTPUT ON
DECLARE
l_job_name VARCHAR2(30);
l_script VARCHAR2(32767);
BEGIN
l_job_name := DBMS_SCHEDULER.generate_job_name;
DBMS_OUTPUT.put_line('JOB_NAME=' || l_job_name);
-- Notice the explicit database connection in the script.
l_script := 'CONN test/test#pdb1
SPOOL /tmp/test.lst
SELECT SYSDATE, USER FROM dual;
SPOOL OFF';
DBMS_SCHEDULER.create_job(
job_name => l_job_name,
job_type => 'SQL_SCRIPT',
job_action => l_script,
credential_name => 'oracle_ol6_121',
enabled => TRUE
);
END;
/
Alternatively, you could use your operating system's scheduling program (Task Scheduler on MS Windows) and tell it to run a .BAT script which would establish SQL*Plus connection and run a .SQL script which contains SPOOL command and that SELECT statement.
Forgot to say: I wouldn't involve SQL Developer into that.
You can also use SQLcl with Oracle 12c.
1) Create .sql file with your spool settings, export location and sql commands
2) Create a .bat file with the SQLcl command:
'>>cd C:\oracle\product\64bit_12.1.0.2client\sqldeveloper\sqldeveloper\bin <--or wherever your sql.exe file is-->
'>>SQL username/password#server:port/pid #C:/users/.../myjob.sql
3) Create a basic job in Windows Task Scheduler to trigger the .bat file

Liquibase Update - Output SQL - Oracle Stored Procedures

We have our stored procedures managed in code as Liquibase change log files (one change set/stored proc per file). These are marked to run every time we deploy. The format of the stored procedure SQL is as follows:
<createProcedure ...>
<![CDATA[
CREATE OR REPLACE MyStoredProc...
...
END;
]]>
</createProcedure>
When we run these change logs against a database everything works fine. However, when we use the updateSQL command to generate a SQL script from the change logs, Liquibase does NOT include the "/" batch separator at the end of each create or replace procedure block.
When I try adding the "/" to the stored proc code in Liquibase, it follows the create or replace statement and the "/" with another semi-colon (;). Either way, you cannot execute the batch script that Liquibase generates because these two issues generate errors.
If anyone has encountered this issue and has some guidance, please post here. This is a show-stopper for our implementation because some of our customers will not allow Liquibase to execute the change logs directly against their production instances. Thanks in advance.

Write Output of DBMS.OUTPUT.put_line To Specified Common Location Like Desktop

I have a long series of calls like:
DBMS_OUTPUT.put_line(v_1||','||v_2);
I have only read priveleges to the database and invision writing the ouptut from the statement above to a common location on all computers that I might read from later (using VBA).
I've found UTL_FILE packages that Oracle seems to support but I am having trouble understanding how to get it to do what I want.
Could someone provide me with a simple example of how I could use the put_line method and UTL_FILE packsage in tandem to write to a common location such as the desktop of a computer?
Spooling is a SQL*Plus feature one can perform on your desktop without invoking the UTL_FILE database package. Toad (utilizing the SQL*Plus feature) can do this as well.
As Justin Cave commented, UTL_FILE is an Oracle database package intended for reading and writing to the database server (e.g. 11g documentation http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_file.htm#BABGGEDF).
Spooling is documented here for SQL*Plus (associated with the Oracle 11g database http://docs.oracle.com/cd/E11882_01/server.112/e27507/sqlplus.htm#DFSUG144 section 3.1.7).
You could select 'Run as a script' in TOAD as follows:
set serveroutput on
spool c:\temp.lst
begin
dbms_output.put_line('My text');
end;
/
spool off
Spooling is a client side feature (SQL*Plus), thus if one wanted to have invocations to dbms_output within a procedure (below, I call it my_procedure), I would just create a sql script that drives the procedure.
One could make this the contents of a sql script (e.g. test_dbms_output.sql):
SET serveroutput ON
spool c:\temp.lst
BEGIN
my_procedure(params);
END;
/
spool OFF
Then, one just can invoke this script with the SQL*Plus run command (or 'Run as a script' in Toad):
#test_dbms_output.sql;
or
run test_dbms_output.sql;

how to execute oracle procedure in ssis sql execute task? [duplicate]

I'm working with SSIS 2008 and am having a problem calling an Oracle stored procedure that has an output parameter.
I call the stored procedure in SqlPlus like this:
var vresult number;
exec my_stored_procedure(:vresult);
print vresult;
The statements work and I get the output I need. I am trying to do something similar in SSIS, yet I need to do this repeatedly, maybe in a ForEach or a script to update a temporary result set with the result of calling the stored procedure (the stored procedure generates a number, and I need to add that number to each row in a result set which just holds some state information).
I have tried a lot of different approaches and always end up with 'invalid statement' or similar errors.
I have also tried the following approaches:
How to resolve SQL query parameters mapping issues while using Oracle OLE DB provider?
Update a row in oracle using OLEDB command(SSIS)
Oracle variables
The crux of the problem seems to be the stored procedure's output parameter.
I have tried using the the Oracle Provider for OLE DB. Any ideas?
If you are trying to invoke The stored Procedure in Oracle PLSQL this Link is very brief.
http://plsql-tutorial.com/plsql-passing-parameters-procedure-function.htm
If you are Working in Java then. The Statement Object
java.sql.CallableStatement ps;
ps.registerOutParameter(parameterIndex, sqlType);
Similarly .Net or Any Other Platform must will have the same Convictions. Hope so.:)
I came up with a solution that works:
Use the 'declare' and 'end' construct
Combine with 'execute immediate'
Add the 'using' statement to the end of the exec immediate to inject variable
So a script that implements this might look something like this:
declare
myVar number;
myStatement varchar2(50);
begin
myStatement:='exec myProc(:1)';
execute immediate myStatement using output myVar;
end;
Paste this script into an Execute SQL task, set the task's properties and it works!
I'm new to Oracle but it looks like the :1 notation is a place-holder for the variable. You can test this using sqlplus too - just save the code in a file and start sqlplus using the # option on the command line.
The only problem: I can't get value of the variable for use in SSIS, but that's another problem.
check tis post: Run an Oracle package from SQL Server Integration Services
http://www.mssqltips.com/sqlservertip/2724/run-an-oracle-package-from-sql-server-integration-services/
regards
You are almost there. In order to retrieve the value of the output parameter from the Oracle stored procedure in SSIS, here is what worked for me
In the Execute SQL task, paste this in the SQL statement box
declare
vresult number;
begin
my_stored_procedure(vresult);
?:=vresult;
end;
In the Parameter Mapping, ensure to map your SSIS variable to this output of your stored procedure by setting the direction to "Output" and parameter name as "0" (if it is the first parameter)
PS: ensure the Oracle output variable datatypes match your SSIS variables
Thanks
Mezue

oracle - run stored procedure from script

I've a script that I am using to build/drop tables and basically setting up the entire schema.
After googling, I still can't figure out how to run a stored procedure.
The script is a .txt file, and I run it using Apex SQL Oracle.
If I write only this line in a script:
execute procedurename(1); --where 1 is paramter.
You have requested to run a script that does not contain any runnable
statements.
SQL>create or replace procedure procedurename(p_num number)
as
begin
null;
end;
/
Procedure created.
SQL>execute procedurename(1);
PL/SQL procedure successfully completed.
everything seems ok on SQLPLUS with oracle 11.
so it must be an apex thing.
Since execute is a sqlplus statement ,try calling the procedure using begin-end PLSQL block in Apex SQL
BEGIN
procedurename(1);
END;
/
save this in a file proc_call.sql and then call it in your script like
#C:\proc_call.sql
where C: is the sample path
For some information refer the below link
https://forums.oracle.com/forums/thread.jspa?threadID=618393