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

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...

Related

User defined table types in Oracle

First of all usually I am working with MSSQL. But I have a stored procedure in MSSQL, which I need to use in Oracle now and since I am absolutely new to Oracle I have no idea at all how to do it correct.
I needed to use user defined table types in my MS SQL stored procedure because I am using "logical" tables in my stored procedure, which I also need to pass them to a dynamic sql statement within this procedure (using column names of "physical" tables as variables/parameters).
I've started to add the oracle function in a package I made before for another function. It looks like
TYPE resultRec IS RECORD
(
[result columns]
);
TYPE resultTable IS TABLE OF resultRec;
Function MyFunctionName([A LOT PARAMETERS]) RETURN resultTable PIPELINED;
I also described the layout of the tables (the user defined table types in MSSQL), which I want to use within this function in this package header.
So far so good, but now I don't really know where I have to declare my table variables or user defined table types. I also tried to put them in the package header, but if I am trying to use these tables in the package body, where I am describing my function, Oracle tells met, that the table or view does not exist.
I also tried it to describe the tables within the package body or in the block of my function, which looks like that:
FUNCTION MyFunctionName
(
[MyParameters]
)
RETURN resultTable PIPELINED is rec resultrec;
TYPE tableVariableA IS TABLE OF tableRecA;
TYPE tableVariableB IS TABLE OF tableRecB;
BEGIN
INSERT INTO tableVariableA
SELECT ColumnA, ColumnB FROM physicalTable WHERE[...];
[A LOT MORE TO DO...]
END;
But in this case Oracle also tells me, that it doesn't know the table or view.
I also tried a few more things, but at the end I wasn't able to tell Oracle what table it should use...
I would appreciate every hint, which helps me to understand how oracle works in this case. Thanks a lot!
You can't insert into a collection (e.g. PL/SQL table). You can use the bulk collect syntax to populate the collection:
SELECT ColumnA, ColumnB
BULK COLLECT INTO tableVariableA
FROM physicalTable
WHERE [...];
However, you might want to check this is an appropriate approach, since SQL Server and Oracle differ quite a bit. You can't use PL/SQL tables in plain SQL (at least prior to 12c), even inside your procedure, so you might need a schema-level type rather than a PL/SQL type, but it depends what you will do next. You might not really want a collection at all. Trying to convert T-SQL straight to PL/SQL without understanding the differences could lead you down a wrong path - make sure you understand the actual requirement and then find the best Oracle mechanism for that.

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.

Oracle: PL/SQL Procedure involving two different Schema in two different Databases

I got a scenario like this, I have an existing procedure that looks similar to this.
PROCEDURE A_DATA_B( p_ID IN SCHEMA1.TABLE1.ID%TYPE,
p_MATCH IN SCHEMA1.TABLE2.MATCH%TYPE,
p_STATUS IN SCHEMA1.TABLE3.STATUS%TYPE,
p_MSG IN SCHEMA1.TABLE1.MSG%TYPE,
The list goes on...
The SCHEMA1 was residing in the same database previously. Now this needs to be moved to another database in different server as such. But the schema name goes to be different but the Table name and the column name remain the same.
So I changed the procedure to look like this
PROCEDURE A_DATA_B( p_ID IN SCHEMA2.TABLE1.ID%TYPE,
p_MATCH IN SCHEMA2.TABLE2.MATCH%TYPE,
p_STATUS IN SCHEMA2.TABLE3.STATUS%TYPE,
p_MSG IN SCHEMA2.TABLE1.MSG%TYPE,
The list goes on..
But when I compile I got the error
PLS-00201: identifier 'SCHEMA2.TABLE1' must be declared PL/SQL:
Declaration ignored
I can understand from this error that SCHEMA2 is not in the database which gives the error. So How should I tackle it?
In the package body where ever am using this SCHEMA2 has been followed by an #db_link. So can I make use of that db_link to solve this?
By looking in to some article I came to know that SYNONYM can also be used. So is this the right way to create a synonym will work?
CREATE SYNONYM SCHEMA2 FOR SCHEMA2#db_link;
Can Someone help me in this regards.
Notes : I may not be able to convert the %type to varchar2 or numbers etc..
Thanks In Advance..
Synonyms are created for objects, not schemas.
You can create synonyms for each table (object, view, etc.) in the local database and use that to declare your anchored types.
CREATE SYNONYM schema2.table1
FOR schema1.table1#db_link
CREATE SYNONYM schema2.table2
FOR schema1.table2#db_link
CREATE SYNONYM schema2.table3
FOR schema1.table3#db_link
The %TYPE referencing items you use as subprogram parameters can point to remote objects through a Database Link by adding the #DBLINK_NAME clause, e.g.:
PROCEDURE A_DATA_B( p_ID IN SCHEMA2.TABLE1.ID#DBLINK_NAME%TYPE,

How can I easily use a collection in an Oracle where clause in a package?

It is my understanding that you cannot use a collection in a where clause unless it is defined at the DB level. I have a distinct dislike for random type definitions laying about a schema. It's a religious thing so don't try to dissuade me.
Types contained within a package are cool, because they are easily found and are related to the work at hand. So having said that I have a package that defines a structure (currently a table type collection) that looks like;
TYPE WORD_LIST_ROW IS RECORD(
WORD VARCHAR(255));
TYPE WORD_LIST IS TABLE OF WORD_LIST_ROW;
There is a routine in the package that instantiates and populates an instance of this. It would be useful to be able to use the instantiated object, or some analog therof in a where clause.
So being the clever (or so I thought) programmer, I said why don't I just create a pipelined function to make a table from the collection which I did, and it looks like;
FUNCTION WORD_LIST_TABLE(IN_WORD_LIST WORD_LIST) RETURN WORD_LIST PIPELINED
AS
OUT_WORD_LIST WORD_LIST := WORD_LIST();
BEGIN
FOR I IN 1 .. IN_WORD_LIST.COUNT
LOOP
PIPE ROW(IN_WORD_LIST(I));
END LOOP;
RETURN;
END WORD_LIST_TABLE;
Then in another routine I call the function that builds the collection, finally I use a pipelined function that uses the collection as input in a cursor's where clause.
sort of like this;
cursor xyz
is
select * from x-stuff where fieldA in (select word from table(word_list_table(temp_word_list));
In the loop for the cursor I get an oracle error ora-21700 object does not exist or is marked for delete.
Is there any easy way to build an oracle object that can be used in an Oracle where clause? Basically what I would like to do is;
select * from whatever where fielda in myobject;
The solution is simple - declare the type at schema level using CREATE TYPE statement and you will be able to use your collections in your SQL statements in PL/SQL blocks.
If you have declared your TYPE inside a PL/SQL package you cannot use it in your queries inside PL/SQL blocks.
Also, you must keep in mind that only varray and nested table type collections can be used in queries as of Oracle 11.2 and you cannot use associative arrays in queries.. In 12c you don't have these restrictions.
For further reference go to Oracle Docs.

Passing an associative array as a parameter between packages

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.

Resources