Can I execute a procedure with default null parameters? - oracle

I recently created a procedure that is defined like this:
create or replace
PACKAGE
pkg_dml_legal_transactions
AS
PROCEDURE spm_update_court_cost(
p_court_state IN legal_court_cost.state%TYPE,
p_tran_code IN legal_court_cost.transaction_code%TYPE,
p_legal_court IN legal_court_cost.court%TYPE default null,
p_end_date IN legal_court_cost.end_date%TYPE,
p_cost_min IN legal_court_cost.cost_range_min%TYPE,
p_cost_max IN legal_court_cost.cost_range_max%TYPE,
p_bal_min IN legal_court_cost.bal_range_min%TYPE DEFAULT NULL,
p_bal_max IN legal_court_cost.bal_range_max%TYPE DEFAULT NULL);
end pkg_dml_legal_transactions;
When I attempt to execute the procedure, I get an error stating that:
PLS-00306: wrong number or types of arguments in call to 'SPM_UPDATE_COURT_COST'
Here is what my execute statement looks like:
execute pkg_dml_legal_transactions.spm_update_court_cost('NJ',1,sysdate,1000,40000);
Now I understand what the error means, but I figured if the parameters are defaulted to null then I could just skip them over, but apparently not. Is there a way around this?

In PL/SQL, you can call a procedure using either named parameter notation or positional notation. If you want to skip some parameters, you'll need to use named parameter notation
execute pkg_dml_legal_transactions.spm_update_court_cost( p_court_state => 'NJ',
p_tran_code => 1,
p_end_date => sysdate,
p_cost_min => 1000,
p_cost_max => 40000 );
Generally, when you're designing a procedure, you would put all the optional parameters at the end so that the caller could also use positional notation.

You can use mixed approach, positional notation until first omitted parameter, named notation for the rest.
declare
procedure do_something(p_foo IN NUMBER
,p_bar IN VARCHAR2 DEFAULT NULL
,p_baz IN VARCHAR2) IS
begin
null;
end;
begin
do_something(12, p_baz => 'abc');
end;
But I would choose what Justin proposed.

Related

What is the result for stored procedure with in ,out parameters and IS keyword parameters before procedure body

Procedure with in , out parameters and having IS keyword with parameters list before BEGIN. In this case which result we will get after executing procedure.
PROCEDURE sample_proc (id in VARCHAR2, name in VARCHAR2, Course out varchar2)
IS error EXCEPTION, error_code VARCHAR2(100), courseID NUMBER, price NUMBER
BEGIN
select * from student where ID =id and name=name;
END executePROC;
Which fields we will get as result after executing via mybatis.
The stored procedure having parameters with data type before BEGIN keyword. In this case the parameters after IS and Before BEGIN keyword how it will work. Please explain
Which fields we will get as result after executing via mybatis.
None, the code has syntax errors and will not compile in Oracle.
You have:
A statement starting with PROCEDURE and not CREATE PROCEDURE (assuming that it is not part of a package as you do not include a preceding CREATE PACKAGE statement).
, following the variable declarations and not ;
A SELECT statement in the PL/SQL scope that does not have an INTO clause.
WHERE id = id AND name=name is (almost) the same as doing WHERE 1=1 AND 1=1 as the id and name values on both sides of the equality comparison will be from the local scope of the SQL statement and will not reference the procedure's arguments.
Variables that you are not using.
The procedure's identifier does not match the identifier after the final END statement.
To fix it you want something like:
CREATE PROCEDURE sample_proc (
i_id in STUDENT.ID%TYPE,
i_name in STUDENT.NAME%TYPE,
o_Course out STUDENT.COURSEID%TYPE
)
IS
BEGIN
SELECT courseid
INTO o_course
FROM student
WHERE id = i_id
AND name = i_name;
END sample_proc;
/
db<>fiddle here
IS keyword with parameters list before BEGIN.
They are not parameters, they are local variables.
As MTO has explained, the example you gave is not valid for a number of reasons.
But for the sake of argument, if you did actually have something like:
... PROCEDURE sample_proc (...)
IS
error EXCEPTION;
error_code VARCHAR2(100);
courseID NUMBER;
price NUMBER;
BEGIN
...
then the bit between IS and BEGIN is the optional declaration part, as described in the documention:
Declarative part (optional)
This part declares and defines local types, cursors, constants, variables, exceptions, and nested subprograms. These items cease to exist when the subprogram completes execution.
This part can also specify pragmas.
Note: The declarative part of a subprogram does not begin with the keyword DECLARE, as the declarative part of an anonymous block does.
The bit that is particularly relevant to your question (as I understand it anyway) is "These items cease to exist when the subprogram completes execution." They are local variables for use within the procedure, and not visible to or accessible by whatever calls the procedure.
The only data made visible to the caller is whatever it put into the OUT parameters.

Why do I get the PLS-00306: wrong number or types of arguments error when calling a Package PROC?

Here is the top part of my Package Body method:
PROCEDURE GetPortfolioAppsAndProjects
(
loginId IN VARCHAR2 := NULL,
portfolioId IN NUMBER := NULL,
portfolioType IN VARCHAR := NULL,
ic IN VARCHAR := NULL,
AppIds_CUR IN OUT SYS_REFCURSOR
)
IS
INVALID_PORTFOLIO_TYPE EXCEPTION;
BEGIN
This runs fine when I execute from the PL/SQL execute dialogue.
I need to be able to run this from an SQL Query window though and join to other tables and what not to develop.
I'm trying to execute this sql from the Sql Window:
DECLARE AppIds_CUR SYS_REFCURSOR;
BEGIN
IREPORT_PORTFOLIOS.GetPortfolioAppsAndProjects('EVANSF', null, null, null, :AppIds_CUR);
END;
And I get this error:
PLS-00306: wrong number or types of arguments in call to 'GETPORTFOLIOAPPSANDPROJECTS'
I count 5 incoming (including one IN OUT cursor).
In my call I pass 5 including the cursor.
How can I get the results of the cursor to the output vars window.
AppIds_CUR is declared locally in your block; you don't need to treat it as a bind variable by prepending a colon:
DECLARE
AppIds_CUR SYS_REFCURSOR;
BEGIN
IREPORT_PORTFOLIOS.GetPortfolioAppsAndProjects('EVANSF', null, null, null, AppIds_CUR);
END;
If you run what you had as a statement in SQL Developer it would prompt you for a bind value, which isn't what you want to happen, and would treat it as a varchar not a ref cursor - hence the wrong-type error.
You'd need to loop over the cursor and display it's values manually with dbms_output with this approach. But you could use a bind variable if you run it as a script, by declaring the type - which would be outside the block, so you don't need the declare:
variable AppIds_CUR REFCURSOR;
BEGIN
IREPORT_PORTFOLIOS.GetPortfolioAppsAndProjects('EVANSF', null, null, null, :AppIds_CUR);
END;
/
print AppIds_CUR
You can display the cursor contents with the SQL Developer print command.

what does => mean in oracle pl sql.is it and invoking operator?

i have a code: OPEN c_data (p_id => 1);
what does => operator mean in PL/SQL
is it a invoking operator or assignment operator
=> is used in a procedure or function call to perform parameter assignment by name. Let's say we have a procedure defined as:
PROCEDURE XYZ(pParm1 IN NUMBER, pParm2 IN NUMBER, pOutput OUT NUMBER);
and we want to invoke it. One way is to pass parameters in the order of declaration, as in:
XYZ(10, 20, nOut);
Another way, which I feel is clearer, is to use the => operator to directly show which values are being assigned to each parameter:
XYZ(pOutput => nOut, pParm1 => 20, pParm2 => 40);
Note that if you use the => operator to assign values to each parameter it is not necessary to pass the parameters in the order they're declared in the procedure.
If you compile and run the following example:
declare
nOut NUMBER;
PROCEDURE XYZ(pParm1 IN NUMBER, pParm2 IN NUMBER, pOutput OUT NUMBER) IS
BEGIN
pOutput := pParm1 * pParm2;
END XYZ;
begin
-- Test statements here
XYZ(10, 20, nOut);
DBMS_OUTPUT.PUT_LINE('After call 1, nOut=' || nOut);
XYZ(pOutput => nOut, pParm1 => 20, pParm2 => 40);
DBMS_OUTPUT.PUT_LINE('After call 2, nOut=' || nOut);
end;
you'll find it produces the following output:
After call 1, nOut=200
After call 2, nOut=800
I find that passing values by name is particularly useful in a couple of cases:
You have a procedure with a large number of parameters where it's difficult to understand which parameter value is associated with each parameter, or
You have a procedure which has default values for most or all of its parameters, and only want to pass in those parameters for which you have values which differ from the defaults.
Share and enjoy.

SQLPLUS object system. is invalid

I'm stuck with some simple procedure and I can't figure out why.
This is my code, which I'm running in sqlplus:
CREATE OR REPLACE PROCEDURE NormalizeName(fullname IN NVARCHAR2)
IS
BEGIN
SELECT TRIM(fullname) INTO fullname FROM DUAL;
DBMS_OUTPUT.PUT_LINE(fullname);
END NormalizeName;
/
BEGIN
NormalizeName('Alice Wonderland ');
END;
/
When I run it, I get the error:
Warning: Procedure created with compilation errors.
NormalizeName('Alice Wonderland ');
*
ERROR at line 2:
ORA-06550: line 2, column 2:
PLS-00905: object SYSTEM.NORMALIZENAME is invalid
ORA-06550: line 2, column 2:
PL/SQL: Statement ignored
What's wrong?
1) Never create objects in the SYS or SYSTEM schema. Those are reserved for Oracle. If you want to create objects, create a new schema first.
2) When you see that a procedure has been created with compilation errors in SQL*Plus, type show errors to see the errors.
3) The error appears to be that your SELECT statement is trying to write to the fullname parameter. But that parameter is defined as an IN parameter, not IN OUT, so it is read-only. If you define the parameter as IN OUT, though, you could not pass a string constant to the procedure, you'd need to define a local variable in your calling block. It doesn't make a lot of sense to have a procedure that doesn't do anything other than call dbms_output since there is no guarantee that anyone will see the data written to that buffer. My guess is that you really want a function that returns a normalized name. Something like
CREATE OR REPLACE FUNCTION NormalizeName( p_full_name IN VARCHAR2 )
RETURN VARCHAR2
IS
BEGIN
RETURN TRIM( p_full_name );
END;
which you can then call
DECLARE
l_normalized_name VARCHAR2(100);
BEGIN
l_normalized_name := NormalizeName( 'Alice Wonderland ' );
dbms_output.put_line( l_normalized_name );
END;
If you really need a procedure because this is a homework assignment
CREATE OR REPLACE PROCEDURE NormalizeName( p_fullname IN VARCHAR2 )
AS
BEGIN
dbms_output.put_line( TRIM( p_fullname ));
END;
In the real world, you should only be using procedures when you want to manipulate the state of the database (i.e. you're doing INSERT, UPDATE, DELETE, MERGE, etc.). You use functions when you want to perform calculations without changing the state of the database or when you want to manipulate data passed in parameters.

Oracle procedure with default and to_date shows error

I am using 11g
I have table
CREATE TABLE Agency
(
AgencyID int not null PRIMARY KEY,
AgencyName VARCHAR2(30) not null,
AgencyLtrCode VARCHAR2(10) not null,
IsActive VARCHAR2(3) DEFAULT 'yes'NOT NULL,
LastListSentData DATE DEFAULT SYSDATE ,
LetterSendDate DATE DEFAULT SYSDATE ,
CertificationDate DATE DEFAULT SYSDATE ,
CeresNo int,
AgencyAreaID int not null,
CONSTRAINT fk_Agency FOREIGN KEY (AgencyAreaID) REFERENCES AgencyArea(AriaID)
);
I use procedure to insert new records in it
create or replace PROCEDURE insert_AGENCY_Procedure(
AGENCYID IN AGENCY.AGENCYID%TYPE,
AGENCYNAME IN AGENCY.AGENCYNAME%TYPE,
AGENCYLTRCODE IN AGENCY.AGENCYLTRCODE%TYPE,
ISACTIVE IN AGENCY.ISACTIVE%TYPE DEFAULT 'yes',
LASTLISTSENTDATA IN AGENCY.LASTLISTSENTDATA%TYPE DEFAULT SYSDATE,
LETTERSENDDATE IN AGENCY.LETTERSENDDATE%TYPE DEFAULT SYSDATE,
CERTIFICATIONDATE IN AGENCY.CERTIFICATIONDATE%TYPE DEFAULT SYSDATE,
CERESNO IN AGENCY.CERESNO%TYPE,
AGENCYAREAID IN AGENCY.AGENCYAREAID%TYPE)
IS BEGIN
INSERT INTO AGENCY("AGENCYID", "AGENCYNAME","AGENCYLTRCODE","ISACTIVE","LASTLISTSENTDATA","LETTERSENDDATE","CERTIFICATIONDATE","CERESNO","AGENCYAREAID")
VALUES (AGENCYID, AGENCYNAME,AGENCYLTRCODE,ISACTIVE,LASTLISTSENTDATA,LETTERSENDDATE,CERTIFICATIONDATE,CERESNO,AGENCYAREAID);
COMMIT;
END;​​
right now it throw error "Error at line 17: PLS-00103: Encountered the symbol "" "
line 17 had only END; on it
when I submit inserting which looks like
BEGIN
insert_AGENCY_Procedure(9003,'Some Other Church', 'SomOTCh','no',10-10-2011,10/10/2011,10/10/2011,17,2 );
END;
it throws error
ORA-06550: line 2, column 4:
PLS-00306: wrong number or types of arguments in call to 'INSERT_AGENCY_PROCEDURE'
ORA-06550: line 2, column 4:
PL/SQL: Statement ignored
or other insert like
BEGIN
insert_AGENCY_Procedure(9003,'Some Other Church',SomOTCh',DEFAULT,DEFAULT,DEFAULT,DEFAULT,17,2 );
END;
it throws error
ORA-06550: line 2, column 64:
PLS-00103: Encountered the symbol "DEFAULT" when expecting one of the following:
( - + case mod new not null
The question is what is wrong with my procedure? I was trying to resolve this problem but stuck :(
First off, the INSERT_AGENCY_PROCEDURE procedure is defined to take 8 parameters but you are trying to pass in 9 parameters. It appears that you are trying to pass in an AgencyLtrCode but the procedure does not take an AgencyLtrCode as a parameter. You would either have to stop trying to pass in the AgencyLtrCode or you would need to modify the procedure to accept that parameter.
Second, you need to pass dates to the procedure given the declaration. Your actual procedure call will error out because what you are passing in for the date parameters are not dates (and cannot be implicitly converted to dates). Assuming that we eliminate the third parameter (which is what appears to be the AgencyLtrCode discussed above), you would want something like
BEGIN
insert_AGENCY_Procedure(9003,
'Some Other Church',
'no',
to_date('10-10-2011', 'DD-MM-YYYY'),
to_date('10/10/2011', 'DD/MM/YYYY'),
to_date('10/10/2011','DD/MM/YYYY'),
17,
2 );
END;
Third, your procedure is incorrect. The parameters LASTLISTSENTDATA, LETTERSENDDATE, and CERTIFICATIONDATE are defined as dates so you should not call to_date on them. If you do, you force Oracle to implicitly convert the date to a string using the session's NLS_DATE_FORMAT, then convert the string back to a date using the explicit format mask. That will fail if the session's NLS_DATE_FORMAT is not what you expect.
Finally, declaring optional parameters in the middle of a procedure declaration is rarely correct. If you want to use positional binding and you want the ability to omit parameters, the optional parameters need to be at the end of the parameter list. You can define optional parameters in the middle of the parameter list and then use named binds (as DazzaL demonstrates) but that is seldom what you want to force future developers to use.
In your updated procedure, the declaration of the AgencyLtrCode parameter appears to be incorrect
AGENCYLTRCODE IN AGENCYLTRCODE%TYPE
needs to be
AGENCYLTRCODE IN AGENCY.AGENCYLTRCODE%TYPE
You are missing the name of the table.
You're passing ninevalues, but the procedure is only expecting eight. From the table definition you seem to be missingAgencyLtrCode in the procedure.
In the first call you're passing dates as 10-10-2011 or 10/10/2011, which will be evaluated as (different) numbers not dates. You need to at least enclose them in single quotes, but really ought to specify the date mask, as to_date('10/10/2011', 'DD/MM/YYYY') rather than relying on implicit conversions.
In general, if you want to use the defaults, just leave those parameters out, do not pass DEFAULT; that isn't valid in that context. But because you have values to pass after the defaults, you need to name the parameters, i.e.
insert_agency_procedure(agency_id=>9003, ...);
there is no DEFAULT keyword, you just omit the defaults.
in your case you have the defaults in the middle of the API though, so you'd have to use NAMED notation:
begin
insert_agency_procedure(agencyid => 9003,
agencyname => 'Some Other Church',
isactive => 'SomOTCh',
ceresno => 17,
agencyareaid => 2 );
end;
/
or mixed:
begin
insert_agency_procedure(9003, 'Some Other Church',
'SomOTCh',
ceresno => 17,
agencyareaid => 2 );
end;
/
and in the first exmaple you gave:
BEGIN
insert_AGENCY_Procedure(9003,'Some Other Church', 'SomOTCh','no',10-10-2011,10/10/2011,10/10/2011,17,2 );
END;
you cant just type dates like that. Firstly quote them. Secondly always always use a format mask.
BEGIN
insert_AGENCY_Procedure(9003,'Some Other Church', 'SomOTCh','no',
to_date('10-10-2011', 'dd-mm-yyyy'),
to_date('10-10-2011', 'dd-mm-yyyy'),
to_date('10-10-2011', 'dd-mm-yyyy'),17,2 );
END;
I think you need to enclose your date string in single quotes (if you supply a date, considering you have default values for those parameters):
BEGIN
insert_AGENCY_Procedure(9003,'Some Other Church', 'SomOTCh','no','10-10-2011','10/10/2011','10/10/2011',17,2 );
END;

Resources