Passing an associative array as a parameter between packages - oracle

I've got two separate Oracle (v9.2) PL/SQL packages and I'm trying to pass an associative array (ie, index-by table) from a procedure in package1, as a parameter to a procedure in package2. Is this possible? I keep getting PLS-00306: wrong number or types of arguments in call to 'ROLLUP_TO_15' when I compile package1.
The array is defined as:
type list_tab is table of number(10)
index by binary_integer;
in both package's spec. In the procedure in package1, I'm calling the second package as package2.rollup_to_15(chanList); That's the line I get the compile error on (chanList is a variable of type list_tab).
In package2, the procedure is defined as:
procedure rollup_to_15(channels in list_tab) is
I'm guessing that my problem is that the type is defined separately in each package, because I can pass the `chanList' variable to other procedures within the first package without any problems.
So, is it possible to pass an associative array between packages? And if so, how?
Dave

Yes, it's possible for sure.
It's hard to explain why do you receive error without package specs samples, but in general to pass a user-defined type as a parameter you should either with define type DDL, or defining the type in package spec.
I suppose you want the latter variant :)
So here're an example:
create or replace package TestPackage_1
as
type TTestType is table of varchar2(1) index by varchar2(1);
end TestPackage_1;
/
create or replace package TestPackage_2
as
procedure Dummy(aParam TestPackage_1.TTestType);
end TestPackage_2;
/
You can use TTestType type in any PL/SQL block, but not in SQL.

"The array is defined as: ... in both
package's spec."
This is the source of your problem. PL/SQL regards two separate declarations as two different objects, even though both types have an identical signature. Consequently the engine hurls when you call this:
package2.rollup_to_15(chanList)
Your code has defined the chanList variable as package1.list_tab but the procedure is expecting a variable of type package2.list_tab.
The simplest solution is to declare LIST_TAB just in PACKAGE2, and chnage PACKAGE1 so that chanList is declared appropriately.

Related

Not recognizing the record type parameter of a stored procedure

I am trying to test a newly created stored procedure in Oracle.
I added the stored procedure to the package and successfully compiled it. The input parameter is a record type.
This is the script:
SET serveroutput on;
DECLARE
p_trlr_rec trailer%ROWTYPE;
BEGIN
/* Call procedure within package, identifying schema if necessary */
TMS_SL_SQL_TRAILER.PR_UPDATE_DUE_INFO(p_trlr_rec);
END;
I get the error:
PLS-00306: wrong number or types of arguments in call to 'PR_UPDATE_DUE_INFO'
In the package file, the parameter is defined like this:
PROCEDURE PR_UPDATE_DUE_INFO
(p_rec IN OUT rectype_trailer);
PROCEDURE PR_UPDATE_DUE_INFO
(p_rec IN OUT rectype_trailer);
I also tried adding the TYPE definition:
PROCEDURE PR_UPDATE_DUE_INFO
(p_rec IN OUT rectype_trailer);
but I get the same error.
Why won't the script recognize the record definition?
Well the script is recognizing your record definitions, both of them. The calling routine is passing a parameter of type "trailer%ROWTYPE" but your procedure is expecting a type of "rectype_trailer" Even if "rectype_trailer" is defined elsewhere they are not the same; thus the error is wrong type of argument.
You need to change one of them to match the other. Assuming the rowtype definition is correct you need to change the procedure definition to
PROCEDURE PR_UPDATE_DUE_INFO
(p_rec IN OUT trailer%ROWTYPE);
In short the calling parameter definition must exactly match the called procedure definition.
PROCEDURE PR_UPDATE_DUE_INFO
(p_rec IN OUT rectype_trailer);
So for this to compile you must have declared that record type somewhere, hopefully in the specification of the package TMS_SL_SQL_TRAILER. So you simply need to reference that declaration in the calling code:
DECLARE
p_trlr_rec TMS_SL_SQL_TRAILER.rectype_trailer;
BEGIN
/* Call procedure within package, identifying schema if necessary */
TMS_SL_SQL_TRAILER.PR_UPDATE_DUE_INFO(p_trlr_rec);
END;
Oracle PL/SQL strictly enforces data typing. Two different types with identical structures are two different types and the compiler regards them as incompatible. So the compiler hurls when it tries to parse your calling code even if TMS_SL_SQL_TRAILER.rectype_trailer is declared as being of trailer%ROWTYPE.

oracle declare a user defined type that can be used across multiple functions and procedure

I have an SQL file that creates other stored procedures/functions. I wanted to make use of a user defined type that can be accessed among the created stored procedures/functions. What is the best way to achieve this? The simplest way that I thought of is to just create that user defined type in every procedure/function.
My user defined type looks something like this:
create type array_t is varray(2) of number;
Just execute
create type array_t is varray(2) of number;
globally.
You can either create the type as a stand-alone item, with a create [or replace] type statement, or else include it in a package header. The advantage of a standalone type is that you can use it in SQL queries and as the type for table and view columns. The advantage of a PL/SQL-only declaration is that it simplifies your deployment, and nobody in their right mind would want a varray column anyway.
If your deployment process is giving 'name is already used by an existing object' errors then yes it already exists (perhaps from a previous run). create or replace is standard practice and a good idea, although your scripts should define each item in only one place.

Does a procedure declared in package requires separate creation outside it?

I am new to creating packages, I have to include a procedure and a function in a package,
I will create a package by declaring its head and body, Body will contains details about procedure and function.
My query is, after package is created, do I need to create that procedure and function again outside? i.e Create and Replace procedure ...and all?
No. You just define the procedure in the package body.
A procedure can either be a stand-alone procedure or it can be part of a package. In real systems, you almost never want to have stand-alone procedures. It virtually always makes sense to put related procedures together into packages to better organize them.

Use global type instead of the local subtype with same name

I have a oracle database with several packages and some types. There is a type defined like
create or replace type my_type as table of varchar2(4000)
And then, into pkg_machines there is
subtype my_type is varchar2(4000)
Now, I didn't write the database and while analyzing errors I discovered that several packages do use pkg_machines.my_type, but pkg_machines needs to use both the local and the global one.
The only possible way that came in my mind to do this, is to change the name of the subtype and refactorize every other package that uses it, but it would mean to waste a lot of time on refactoring hundreds of packages.
My question is: is there a way to tell to a procedure to refer to the global type my_type instead of the defined subtype?
When you want to use the global name fully qualify it as schema_name.my_type. The schema name will usually be the same as the user you were logged in to the database with when the type was created.
Share and enjoy.

What is the difference between "AS" and "IS" in an Oracle stored procedure?

I see Oracle procedures sometimes written with "AS", and sometimes with "IS" keyword.
CREATE OR REPLACE Procedure TESTUSER.KILLINSTANCE (INSTANCEID integer) **AS**
...
vs.
CREATE OR REPLACE Procedure TESTUSER.KILLINSTANCE (INSTANCEID integer) **IS**
...
Is there any difference between the two?
Edit: Apparently, there is no functional difference between the two, but some people follow a convention to use "AS" when the SP is part of a package and "IS" when it is not. Or the other way 'round. Meh.
None whatsover. They are synonyms supplied to make your code more readable:
FUNCTION f IS ...
CREATE VIEW v AS SELECT ...
One minor difference...
They are synonyms for packages and procedures, but not for cursors:
This works...
cursor test_cursor
is
select * from emp;
... but this doesn't:
cursor test_cursor
as
select * from emp;
"IS" and "AS" act as a synonym while creating procedures and packages but not for a cursor, table or view.
Here's another difference (in 10g, at any rate)
Given a loose object type:
CREATE TYPE someRecordType AS OBJECT
(
SomeCol VARCHAR2(12 BYTE)
);
You can create a loose Table type of this object type with either AS or IS
CREATE OR REPLACE TYPE someTableType
IS {or AS} TABLE OF someRecordType;
However, if you create this same table type within a package, you must use IS:
CREATE OR REPLACE PACKAGE SomePackage IS
TYPE packageTableType IS TABLE OF someRecordType;
END SomePackage;
Use of AS in the package yields the following error:
Error(2,30): PLS-00103: Encountered the symbol "TABLE" when expecting one of the following: object opaque
According to TutorialsPoint
The AS keyword is used instead of the IS keyword for creating a
standalone procedure.
and considering previous answers,
I guess
AS is for stand alone (outside of any block, subprogram, package) entities
and
IS is for embedded (within a block, subprogram or package) entities.
.
The AS keyword is used instead of the IS keyword for creating a standalone function.
[ A standalone stored function is a function (a subprogram that returns a single value) that is stored in the database.
Note: A standalone stored function that you create with the CREATE FUNCTION statement is different from a function that you declare and define in a PL/SQL block or package. ]
For more explanation, read this...

Resources