I am having a problem using host() command in oracle procedure.
I have written very simple oracle code.
CREATE OR REPLACE PROCEDURE
run_command(command_i IN VARCHAR2)
IS
l_message VARCHAR2 (100);
BEGIN
l_message := 'cmd ' || command_i;
host(l_message);
END run_command;
when host(l_message); is eliminated works fine.
Whats the problem and is there anyway to create a routine which uses host()?
The HOST command is only available in SQL*Plus and not from PL/SQL.
You can use Java stored procedure to call call OS commands. Oracle released a white paper on calling OS commands from within PL/SQL back in 2008 but there's plenty of other stuff out there (including Oracle Base, which is quite good)
Another clunky, but non-Java way would be to create DBMS_SCHEDULER ad-hoc EXECUTABLE job which is your HOST command (e.g. ls ), and then execute the job.
Note these run on the database server, not on your remote/local client.
Related
Hello and thanks in advance. I am running Oracle 11gR2 and want to try to execute an sql loader to insert data into an existing table. I am attempting this via Java stored proc in the database that will perform commands on the OS. The problem I am having is that I cannot seem to get the call to invoke SQLLDR.EXE to work - error I have is: sqlldr not found (NOTE that lookup with PATH isnt done due to the Oracle executable being SETUID)
----------------------Sample Code------------------------------------------
declare
l_ldr varchar2(1000) := '/u01/app/oracle/product/db/11.2.0.4/bin/sqlldr.exe control=C:\ad\controlfile.ctl, log=load.log, bad=load.bad,data=C:\somefile.txt';
l_env varchar2(1000) := 'PATH=/bin:/u01/oracle/db/11.2.0.4/jdk/bin;';
l_out varchar2(5000);
l_ret varchar2(5000);
begin
dbms_output.put_line(l_ldr);
MSO_Java.dbcmd('sqlldr.exe',
l_ldr,
l_env,
'Y',
l_out,
l_ret);
dbms_output.put_line(l_ret);
dbms_output.put_line(l_out);
end;
--------------------------END CODE SAMPLE--------------------
Appreciate ANY help here. I know this can be done.....
SQLLDR doesn't have the option to be executed in a PL/SQL, but you can simulate a SQLLDR with PL/SQL.
Yeap this is posible, I created a stored procedure that works fine just with REGEXP, now the documentation is in spanish but as soon that I can I will translate this.
Here is the link
Performence? Yeah I now that simulate a SQLLDR will be affect the performance in the database but NO, is this the reason that I used REGEXP. That works fine for me loading masive data.
Another thing is that this PL/SQL gives you the opportunity to transform the data. You can use a ETL for that but sometimes that is not possible :(.
THAT IS EASY TO UNDERSTAND :D!
The following stored procedure code works in our DEV and TEST environments which run with Oracle 11G but will not work in our 10G PROD environment:
first, I created my own data structure in Oracle to hold any array of VARCHAR2:
create or replace
type MAT_MULTIPLES_ARRAY as table of VARCHAR2(100);
here is the procedure code:
create or replace PROCEDURE MAT_SUBMIT_JOB (v_multiples_columns_to_add IN our_schema.MAT_MULTIPLES_ARRAY)
v_jobno number;
v_job_name VARCHAR2(100);
v_error_message VARCHAR2(32000);
begin
v_job_name := 'doesnt matter right now';
dbms_scheduler.create_job(v_job_name,program_name=>'MAT_JOB_PROGRAM');
dbms_scheduler.set_job_anydata_value(v_job_name,1,sys.anydata.convertCollection(v_multiples_columns_to_add));
dbms_scheduler.enable(v_job_name);
end;
again, this same code works in 11G in our DEV and TEST environments, and it compiles in our 10G environment, but then it appears to barf during runtime, on the second dbms_scheduler line (in bold).
Does dbms_scheduler work in 10G? Or perhaps there is a problem with 'sys.anydata.convertCollection(v_multiples_columns_to_add)'
Here is the error message:
ORA-22370: incorrect usage of method originated from line 19 in my procedure.
line 19 is the line with convertCollection() call.
Please help!
I found this in the documentation:
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_sched.htm#i1000820
SET_JOB_ANYDATA_VALUE requires that you be the owner of the job or have ALTER privileges on that job. You can also set a job argument value if you have the CREATE ANY JOB privilege.
This might also be related as well:
ANYDATA with Collections based on rowtype
My Application generates a CSV file using UTL_FILE and writes the file to the DB server location,then the SFTP should transfer that file to a desired shared location.
First part is done,need help in the second one i.e SFTP using PLSQL
Thanks
While it is entirely possible to write a SFTP client in PL/SQL using the UTL_TCP package, that is unlikely to be a practical approach. In general, you have a couple options
Create a Java stored procedure using one of the many Java SFTP libraries and call that Java stored procedure from PL/SQL.
Create a shell script that does the SFTP using the server's command-line utililties and call that shell script either using DBMS_SCHEDULER or via a Java stored procedure.
If your Oracle database is running on Windows, you could also write a .Net stored procedure rather than a Java stored procedure in either of the two options above. A Java stored procedure, however, would be much more common.
If you would like to try a commercial offering you can check ORA_SFTP
You can upload a file with it with a code block similar to this:
DECLARE
connection_id NUMBER;
private_key_handle BFILE;
private_key BLOB;
PRIVATE_KEY_PASSWORD VARCHAR2(500);
BEGIN
DBMS_LOB.createtemporary(PRIVATE_KEY, TRUE);
private_key_handle := BFILENAME('PGP_KEYS_DIR', 'test_putty_private.ppk'); -- directory name must be Upper case
DBMS_LOB.OPEN(private_key_handle, DBMS_LOB.LOB_READONLY);
DBMS_LOB.LoadFromFile( private_key, private_key_handle, DBMS_LOB.GETLENGTH(private_key_handle) );
DBMS_LOB.CLOSE(private_key_handle);
PRIVATE_KEY_PASSWORD := 'changeit';
connection_id := ORA_SFTP.CONNECT_HOST('localhost', 22, 'nasko', private_key, private_key_password);
-- upload the private key just for a demo
ORA_SFTP.UPLOAD(connection_id, private_key, 'data.csv');
ORA_SFTP.DISCONNECT_HOST(connection_id);
END;
/
Disclaimer: I work for DidiSoft
How to use "START SCRIPT" in pl/sql block ?
I want to use something like this
declare
begin
proc(para1,para2);
execute immediate 'start prompt1' ;
end;
/
Also I want to know , can i get a value from prompt1 into my PL/SQL block where am calling the script ? Because I need to use the value to perform some operations in the PL/SQL block.
It is 2012 2017. Scripts are a clunky and brittle hangover from the last millennium. Oracle has a fantastic range of functionality we can execute in PL/SQL, plus there's Java Stored Procedures, and there's scheduling for starting jobs. Other than running DDL to create or amend schemas there is hardly any need for scripts in an Oracle database environment; even DDL scripts should be triggered from an external client, probably a build tool such as TeamCity.
In particular I would regard attempting to run a SQL script from a PL/SQL program as an architectural failure. What are you doing with the script which you cannot do with a stored procedure?
As for passing input to a stored procedure, that's what parameters are for. PL/SQL isn't interactive, we need a client to enter the values. Depending on the scenario this can be done asynchronously (values in a file or a table) or synchronously (calling the stored procedure from SQL*Plus, SQL Developer or a bespoke front end).
Having said all that, in the real world we work with messy architectures with inter-dependencies between the database and the external OS. So what can we do?
We can write a Java Stored Procedure to execute shell commands. This is the venerable solution, having been around since Oracle 8i. Find out more.
In 10g Oracle replace DBMS_JOB with DBMS_SCHEDULER. Once of the enhancements of this tool is its ability to run external jobs i.e. shell scripts. Find out more.
Since Oracle 11g R1 external tables support pre-processor scripts, which run shell commands before querying the table. Find out more.
Note that all these options demand elevated access (grants on DIRECTORY objects, security credentials, etc). These can only be granted by privileged users (i.e. DBAs). Unless our database has an astonishingly lax security configuration there is no way for us to run an arbitrary shell script from PL/SQL.
Finally, it is not clear what benefit you expect from running a SQL script in PL/SQL. Remember that PL/SQL runs on the database server, so it can't see scripts on the client machine. This seems relevant in the light of the requirement to accept user input.
Perhaps the simplest solution is reconfiguration of the original script. Split out the necessary PL/SQL call into a block and then just call the named script:
begin
proc(para1,para2);
end;
/
#prompt1.sql
You can write a pl/sql block in SqlPlus to check for a parameter from a table then execute a script. In the script to be executed (MyScript.sql below), the statement terminators must be ";" instead of "/"
declare
vMyParameter number := 0;
begin
select count(*) into vMyParameter
from MyTable
where MyCheckValue = 'Y';
if vMyParameter = 1 then
#MyFolder/MyScript.sql;
end if;
end;
/
If you're using sql*plus (or a tool that is using it) then you can do something like this:
set serveroutput on
variable a number;
begin
:a := &promt;
dbms_output.put_line(:a);
end;
/
If it runs in batch then you can do:
variable a number;
begin
:a := &1;
dbms_output.put_line(:a);
end;
and get the value for :a as a parameter-
sqlplus sdad/fdsfd#fdggd #<your_script.sql> <val_for_a>
Another practice is to execute on one *.bat with parameters, like:
Example c:/oracle/bin/sqlplus.exe -w #c:/name
sql %1 %2 #c:/output.sql
execute immediate 'start prompt1' ;
Execute immediate is to execute SQL statements , not arbitrary commands.
can i get a value from prompt1 into my PL/SQL block where am calling the script
You can run a run script - but I doubt you can capture input from an SQL script, esp within a PL/SQL block
I am using oracle 10g express edition. It has a nice ui for db developers. But i am facing some problems executing stored procedures.
Procedure:
create or replace procedure temp_proc is
begin
DBMS_OUTPUT.PUT_LINE('Test');
end
it is created successfully. But when i execute:
execute temp_proc;
it shows ORA-00900: invalid SQL statement
So help needed here
Execute is sql*plus syntax .. try wrapping your call in begin .. end like this:
begin
temp_proc;
end;
(Although Jeffrey says this doesn't work in APEX .. but you're trying to get this to run in SQLDeveloper .. try the 'Run' menu there.)
Oracle 10g Express Edition ships with Oracle Application Express (Apex) built-in. You're running this in its SQL Commands window, which doesn't support SQL*Plus syntax.
That doesn't matter, because (as you have discovered) the BEGIN...END syntax does work in Apex.
Both 'is' and 'as' are valid syntax. Output is disabled by default. Try a procedure that also enables output...
create or replace procedure temp_proc is
begin
DBMS_OUTPUT.ENABLE(1000000);
DBMS_OUTPUT.PUT_LINE('Test');
end;
...and call it in a PLSQL block...
begin
temp_proc;
end;
...as SQL is non-procedural.
I use oracle 12 and it tell me that if you need to invoke the procedure then use call keyword.
In your case it should be:
begin
call temp_proc;
end;
Have you tried to correct the syntax like this?:
create or replace procedure temp_proc AS
begin
DBMS_OUTPUT.PUT_LINE('Test');
end;
In Oracle SQL Developer (GUI), using 12c, also don't forget to enable the DMBS Output window (click View => Dbms Output, then click "+" sign, and select your connection), by default the window is not enabled.
The following syntax will then output to this window:
begin
temp_proc
end;
You can do simply the following on the Command Window:
Connected to Oracle Database 19c Enterprise Edition Release 19.0.0.0.0
Connected as XXX#YYY
SQL> call temp_proc();
Or:
SQL> execute temp_proc();