call a oracle procedure from inside a sql block - oracle

If I have a .sql file with this :
begin
exec dbms_stats.gather_table_stats('schema',table');
end;
/
Should I need to use :
call 'exec dbms_stats.gather_table_stats('schema',table')';
I cannot test it out because of system problems so i am posting my query here.

As far as I can tell, both are flawed - exec is used in SQL/Plus without a begin/end block, and call is definitely not PL/SQL; you'd also probably have to escape the single quotes inside your call statement.
You can just use
begin
dbms_stats.gather_table_stats('ALERTS_OWNER','ASYNC_PROCESSING_REQUEST_T');
end;

Related

how to write a batch file, which runs a PL/SQL block, to tell me many records are inserted/deleted/etc. in a log file?

I have created two batch files to run two separate .sql file in Windows Task Scheduler. The batch file for both looks like this:
sqlplus userid/password#database #C:\XXX.sql>>C:\output.log
echo commit; | userid/password#database
The first .sql file (SQL1) is a PL/SQL block like this:
SET SERVEROUT ON
DECLARE
....
BEGIN
IF ...
....
ELSE
#D:\DM_FIX.sql;
END IF
END
The DM_FIX.sql file is to insert a bunch of records into a table, and it starts with the INSERT command.
The second.sql file is not a block file. It's doing a bunch of DDL/DML comand. the file looks like below:
Truncate Table YYY
Reuse Storage;
Commit;
Insert into Table YYY
Select ... from
Commit;
Delete from Table YYY
where ...
Commit;
When I run the second .sql file, I get an output that indicates "The table has been truncated; #### records are inserted; #### records are deleted..."
But when I run the first, although the PL/SQL procedure is executed successfully, I don't get a line saying how many records are inserted, and I'm trying to figure out a way to do it.
Does any one know what could be the trick?
Thanks!
Revised Answer
As #Alex Poole helpfully pointed out, you can use the # nomenclature in a PL/SQL block from SQL*Plus, as that would load the second file's commands into the block that you're calling it from.
The reason that you're not getting any output is that, as far as SQL*Plus is concerned it's all one command: the SQLPlus block. In order to get output to your log for those commands, you'll need to create it yourself, using DBMS_OUTPUT. You would need to include a line like the one below after each command.
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || ' rows inserted');
However, you should note that doing this will cause your script to throw errors if it's ever called from outside of a PL/SQL block. My original solution would avoid this restriction, as it eliminates the need to use DBMS_OUTPUT.
Original Answer
I find it difficult to believe that the PL/SQL in the first file is executing successfully. This is because you're mixing SQL*Plus commands with PL/SQL code. They are separate systems - it's like trying to use shell commands natively in a programming language. You should be getting PLS-00103: Encountered the symbol "#" when expecting... from the first file.
SQL*Plus doesn't have conditionals, so, in order to keep the PL/SQL and SQLPlus commands seperate, you'd need to fake it somewhat. I'd suggest putting the file name into a substitution variable, then using that to run a file:
VARIABLE v_my_file_bind varchar2(100)
DECLARE
...
BEGIN
IF ...
...
:v_my_file_bind := 'D:\EMPTY_FILE.sql';
ELSE
:v_my_file_bind := 'D:\DM_FIX.sql';
END IF;
END;
/
COLUMN v_my_file_column new_value my_file_substitution noprint
SELECT :v_my_file_bind v_my_file_column from dual;
#&&my_file_substitution
To show count of modified rows in PL/SQL, use SQL%ROWCOUNT:
begin
insert into my_table ...
select ...
from ...;
dbms_output.put_line('Rows inserted: ' || SQL%ROWCOUNT);
commit;
end;
/
Remember, that SQL%ROWCOUNT variable will reset to 0 after commit.
Documentation: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/sql_cursor.htm

Oracle PL/SQL's dbms_output.put_line() vs dbms_output.put()

I have a trivial question, I yet to understand the difference between dbms_output.put_line() and dbms_output.put()
set serveroutput on size 200000
Begin
dbms_output.put_line('A' || CHR(10) || 'B');
End;
/
exec dbms_output.put_line('A' || CHR(10) || 'B');
The above gives output A and B in two different lines. But
exec dbms_output.put('A')
exec dbms_output.put('B')
exec dbms_output.new_line
prints nothing. I am using SQL*Plus: Release 11.2.0.1.0 Production
You always have to write full lines in each PL/SQL block. Wehn you write
Begin
dbms_output.put_line('A' || CHR(10) || 'B');
End;
/
You write the two full lines "A" and "B" in one PL/SQL block. When you write
exec dbms_output.put_line('A' || CHR(10) || 'B');
the same holds true.
But when you write
exec dbms_output.put('A')
exec dbms_output.put('B')
exec dbms_output.new_line
you have three separate PL/SQL blocks. The first two write partial lines, which will be skipped by SqlPlus. The third block writes a full, but empty line.
If you write
begin
dbms_output.put('A');
dbms_output.put('B');
dbms_output.new_line;
end;
/
everything works as expected.
The reason for this is how console output in SqlPlus works: PL/SQL writes the output in an intermediate buffer. SqlPlus fetches the content of this buffer at the end of each executed PL/SQL block. It then prints that content to the console, while only printing full lines. Hence it skips the last line in the buffer, when it is not terminated by a new line character.
Technically I suspect SqlPlus to also print lines without a new line character, but starightaway overwrite them in the next step. Technically SqlPlus indeed fetches only full lines from the internal buffer, using the DBMS_OUTPUT.GET_LINES PL/SQL function.
Assuming you are on 11g, you should be considering PUT procedure since it is Obsolete and no longer supported by Oracle. In previous versions, with PUT, the line is not yet completed. Since it doesn't have end of line marker unlike PUT_LINE which automatically is followed by an end-of-line marker.
So, if you add an end-of-line marker, you will get the output.
You can have a look at this old question Is dbms_output.put() being buffered differently from dbms_output.put_line()?

Can Sqlplus read the contents of a file into a variable?

I've been tinkering with sqlplus for awhile now, and I've managed to get sqlplus to read the contents of a file into a substitution variable as such:
exit | sqlplus -s login/pass#db #script.sql "`cat file.txt`"
This mostly works as my script requires... even newlines in the file are preserved. However, I was only using a sample file which was 50 or 60 bytes in size. The actual files I'll end up using will be at least a few kilobytes. So it was at this point I decided to check the max size of a substitution variable: 240 characters.
Is there a way within my sqlplus script to read a file's contents into a bind variable? The Oracle documentation seems to hint at this with the GET command, saying that typically you'll use this just to load a sql/sqlplus script.
http://docs.oracle.com/cd/B10501_01/server.920/a90842/ch13.htm#1009882
file_name[.ext] Represents the file you wish to load (typically a script).
Yes, there's a tricky way to do it.
Put something into props.txt and run the script:
DECLARE
-- the ## expression must be in separate line as follows
file_contents VARCHAR2(32767) := '
##props.txt
';
BEGIN
dbms_output.put_line('===');
dbms_output.put_line(file_contents);
dbms_output.put_line('===');
END;
/
Note that the file props.txt can not contain an "#" or you'll get nested
SQL*PLUS calls
No. Load would only store the file contents in Sql*Plus's own sql buffer. You can then run, edit and list the buffer.
A substitution variable is not the right place to load a file into. Use a bind variable of type clob for that and load the file contents using utl_file. But of course the file has to be located on the server in this case.
edit: if the data has to be located on the client, your option would be to load the clob using a pl/sql block and several calls to dbms_lob.writeappend
Your file would have to look like this (cannot test it ATM):
var l clob;
begin
dbms_lob.createtemporary(l);
dbms_lob.writeappend(l, 'abcdef...');
dbms_lob.writeappend(l, 'ijkl...');
end;
/
Please consider using literal quoted string - this allows you to have quotes in the linked file:
DECLARE
-- the ## expression must be in separate line as follows
file_contents VARCHAR2(32767) := q'[
##props.txt
]';
BEGIN
dbms_output.put_line('===');
dbms_output.put_line(file_contents);
dbms_output.put_line('===');
END;
/

How to return result of an Oracle stored procedure to a shell script

I have a oracle procedure proc1 which adds two values and gives the result.I have to call this procedure from shell and show its result back to the shell.I am able to call that procedure from the shell,but it just shows that PL/SQL procedure successfully completed.But the result is not coming to the shell .
i am doing this to call the procedure from shell...
$ echo "execute proc1(10,10);"|sqlplus -s system/xxxxx#orcl
This is the procedure which is running fine .
create or replace procedure proc1
(N1 in number,N2 in number) is
begin
dbms_output.put_line(N1+N2);
end;
/
I need the output in the shell .Anyone plese help.
I am aware there is another answer showing how to use set serveroutput on and the procedure call on separate lines, however I am writing this answer as a one-liner to do the same thing.
Bascially you need to shove this into sqlplus:
set serveroutput on
execute proc1(10,10);
You might at first think this can be done on one line, separated with a semi-colon.
set serveroutput on; execute proc1(10,10);
However that doesn't work - you really need a newline character.
So the trick is to also use -e flag with echo, which can give you a newline with \n.
Using head -1 trims everyting but the line containing the procedure result.
Final one-line answer:
echo -e "set serveroutput on\n execute proc1(10,10);"|sqlplus -s system/xxxxx#orcl| head -1
P.S. I editted your question to remove the password :)

Execute immediate run from a PL/SQL package

I have the following lines of code in a PL/SQL package
l_sql := 'alter table LOG_FILES location ('||chr(39)|| filename || to_char(sysdate,'DDMMYY') ||chr(39)||'))';
execute immediate l_sql;
The pl/sql package compiles fine but i dont see the change. The alter command has no effect at all. Is there any reason for this?
Note: The table I am trying to alter is an Oracle External table.
The filename is a string and needs to be bracketed with single quotes in the final statement. In order to acheive that you need to escape the single quote. One way is to use two single quotes. So, your assignment needs to look something like this:
l_sql := 'alter table LOG_FILES location ('''|| filename || to_char(sysdate,'DDMMYY') ||''')';
You have an extra parentheses at the end of your statement

Resources