I have two .sql files both are Oracle stored procedures which both take in input parameters. I would like to first connect to a remote oracle database using sqlplus in command line and want to first use both files to create their respective stored procedures so I see them under procedures for that connection in Oracle SQL Developer.
After this I have two more .sql files which look like this and are designed to take input parameters and execute the stored procedures. This is one of the files that is meant to execute the stored procedure "REPORT".
DECLARE
NAME VARCHAR2(200);
VERSION VARCHAR2(200);
STARTDATE DATE;
ENDDATE DATE;
BEGIN
NAME := '&1';
VERSION := '&2';
STARTDATE := '&3';
ENDDATE := '&4';
exec REPORT(NAME, VERSION, STARTDATE, ENDDATE);
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20101,SQLERRM);
END;
/
In command prompt I first try to create the stored procedure in the database by:
C:\Users\Desktop>sqlplus username/password #report_setup.sql
When I try this the output get is just empty lines that are numbered and beginning at the number that is 1 greater then the last line of my .sql file. My report_setup.sql file is 81 lines long and the output of the sqlplus command is blank numbered lines beginning at 83.
Please let me know how I can create and execute these stored procedures properly through sqlplus.
Thanks in advance,
I think you have to remove the 'exec'-word, and it's crucial to have the slash at the bottom at the very start of the line, with no spaces in front of it:
DECLARE
NAME VARCHAR2(200);
VERSION VARCHAR2(200);
STARTDATE DATE;
ENDDATE DATE;
BEGIN
NAME := '&1';
VERSION := '&2';
STARTDATE := '&3';
ENDDATE := '&4';
REPORT(NAME, VERSION, STARTDATE, ENDDATE);
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20101,SQLERRM);
END;
/
It would have been more useful to show the report_setup.sql than the script that calls the procedure it creates... but from the symptoms you describe, the report_setup.sql doesn't have a / at the end of the procedure declaration.
It presumably has something like:
CREATE OR REPLACE PROCEDURE REPORT(NAME VARCHAR2, VERSION VARCHAR2,
STARTDATE DATE, ENDDATE DATE) AS
...
BEGIN
...
END REPORT;
It needs to have
...
BEGIN
...
END REPORT;
/
Since you're running it from the command line with # it should also have an EXIT at the end; but without the / that will be treated as part of the procedure, which is never compiled.
You can suppress the line number display, incidentally, by calling SQL*Plus with the -s flag - though at the moment they are useful since they show roughly what the problem is.
I had a similar issue. The problem was the encoding used, sqlplus expects UTF-8 standard enconding, wherever different encoding cause weird behavior.
Related
I have a shell script that calls an Oracle Stored Procedure. The SP has two parameters - the first is of type VARCHAR2 and the second is of type DATE
CREATE OR REPLACE PROCEDURE MY_SCHEMA.MY_SP_NAME(firstParameter IN VARCHAR2, dateParameter IN DATE)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Successfully called Procedure');
END;
/
In my shell script, I'm trying to execute the procedure using the following command:
echo "EXECUTE MY_SCHEMA.MY_SP_NAME('TEST', '20170909') " | $ORACLE_HOME/bin/sqlplus $ORAUSER/$ORAPASS
The problem is that when the script runs I get the following error: ORA-01861: literal does not match format string. My guess is that there is an issue with the '20170809' value that I'm passing to the date parameter but I'm unsure how to resolve this. Any help is appreciated.
(PS: The ORACLE_HOME/USER/PASS environment variables are all set correctly and I can successfully run SQLPLUS from the script so there are no problems connecting to the Oracle database)
You can try to use the to_date function:
Execute my_schema.my_sp_name(‘test’,to_date(‘20170909’, ‘yyyymmdd’))
Or use ISO date format in your date parameter.
I've made this program and I was wondering why oracle prompts for input even when it does not run the 'D' case (when 'A' is imputed for example).
SET SERVEROUTPUT ON;
ACCEPT p_user_letter PROMPT 'Enter an option';
DECLARE
v_user_letter VARCHAR2(200) := UPPER('&p_user_letter');
BEGIN
CASE v_user_letter
when 'A' then dbms_output.put_line('A pressed');
when 'D' then new_customer('&userEntered');
else dbms_output.put_line('Other');
END CASE;
END;
/
CREATE OR REPLACE PROCEDURE new_customer
(ccName IN Varchar2)
IS
BEGIN
dbms_output.put_line('Ran procedure');
END new_customer;
From the error message it seems like it runs a new and old version of declare which forces all uninitialized prompts to have a value, but i'm not certain and could not find out why online.
Both new and old running
('&userEntered'); is a substitution variable.
The substitution variables are not a part of SQL, this is a feature of SQL-Plus client, it is also supported by SQL-Developer.
When you hit Enter (or Run icon in SQL-Developer), SQL-Plus first analyses your script. When it finds &xxx string in your script, then prompts the user for a value. When the user enters the value then SQL-Plus substitutes (replaces) &xxx with the value entered by the user.
When SQL-Plus substitutes all substitution variables, then it starts to execute this script - that is, it sends SQL commands from the script to the Oracle Database for execution.
You can think of the variable substitution in SQL-Plus as a kind of macro preprocesing.
I have the following stored procedure
CREATE OR Replace PROCEDURE sprocvPOP_GetvemployeeByFilter
(TheFilter varchar2,
TheOrder varchar2,
PageOrder int,
ItemsPerPage int,
TheCount out number,
cur out sys_refcursor)as
begin
........
end
I want to call this procedure, and print cur parameter and the count parameter values because they are out variables.
I tried using the following syntax in SQL Developer
set serveroutput on
var rc refcursor;
declare
mycount number(19);
begin
execute sprocvPOP_GetvemployeeByFilter (NULL,NULL,1,10,mycount,:rc);
print rc;
dbms_output.put_line(mycount);
end;
but I got the error
PLS-00103: Encountered the symbol "RC" when expecting one of the following:
:= . ( # % ;
The symbol ":=" was substituted for "RC" to continue.
How can I execute this procedure and print out parameters in SQL Developer?
To answer your original question, print rc is a SQL*Plus command, so it needs to be outside the PL/SQL block. execute is also a SQL*Plus command and is not used in PL/SQL. So your code should look like this:
set serveroutput on
var rc refcursor;
declare
mycount number(19);
begin
sprocvPOP_GetvemployeeByFilter (NULL,NULL,1,10,mycount,:rc);
dbms_output.put_line(mycount);
end;
/
print rc;
However, it turns out you are using SQL Developer not SQL*Plus client to run your code. Not many SQL*Plus commands are natively supported in SQL Developer. The list is here.
The latest versions of the tool come with a Command Line interface which is very neat. Find out more.
Alternatively, use the built-in Run PL/SQL functionality as described in this tutorial
In the above code, I am giving schemaname as input and using that input it should connect to the database. But In this case the value i entered is not taken by the schemaname. This is how the out put and the error is:
declare schemaname varchar2(20);
exec :schemaname := XYZ;
BEGIN
end;
Error report -
ORA-06550: line 2, column 6:
PLS-00103: Encountered the symbol "" when expecting one of the following:
constant exception <an identifier>
<a double-quoted delimited-identifier> table long double ref
char time timestamp interval date binary national character
nchar
ORA-06550: line 4, column 1:
PLS-00103: Encountered the symbol "CONNECT" when expecting one of the following:
Could any one suggest how to make it work using spool
the code between declare and end is PL/SQL. Commands like CONNECT or SPOOL are SQL*Plus commands. You cannot use SQL*Plus commands in a PL/SQL block.
In your case you don't need PL/SQL at all:
Create a script with following content
connect &1
spool C:\ABC
#c:\ABC
spool off;
and run it
#your_script_name
BTW: there is no reason to run script c:\ABC while you are spooling into it. What exactly do you want to achieve?
exec[ute] is SQL*Plus and SQL Developer (and maybe other clients) shorthand for an anonymous block. It is a client command, it is not part of PL/SQL. You are trying to use it inside a PL/SQL declare section, where it is not valid or recognised.
If you want a client bind variable you need the var[iable] command:
var schemaname varchar2(20);
exec :schemaname := '&1';
BEGIN
...
Notice the single quotes around &1, as it's being assigned to a string variable.
But you can't connect inside a PL/SQL block either, and you can't use a bind variable for the connection.
connect :schemaname
will prompt for a password (even if you defined it's value as user/passwd) and try to connect as a user lieterally called :schemaname.
You can use a substituion variable, but you don't really need to define a new one; as you seem to be passing the credentials in, you can do:
connect &1
(without surrounding quotes)
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