PLSQL_V2_COMPATIBILITY Compatibility - oracle

I have migrated oracle database from 10g to 12c. From 12c oracle doesn't support PLSQL_V2_COMPATIBILITY parameter.
This parameter is used to :
https://www.safaribooksonline.com/library/view/oracle-database-administration/1565925165/re157.html
One of the highlighting point in above url is :
The PL/SQL compiler will allow OUT parameters to be used in expression
contexts in some cases, for example, in dot-qualified names on the
right-hand side of assignment statements. This behaviour is restricted
to fields of OUT parameters that are records, and OUT parameters
referenced in the FROM list of a SELECT statement.
Due to this change many of our packages went into error which previously using functions with record as out parameter.
CREATE OR REPLACE Package SJMUSER.nagendra AS
TYPE r_standard_url IS RECORD (
v_loginurl VARCHAR2(1000),
v_changepasswordurl VARCHAR2(1000),
v_newloginurl VARCHAR2(1000)
);
TYPE t_standardurl_tbl IS TABLE OF r_standard_url
INDEX BY BINARY_INTEGER;
t_standardurlstype t_standardurl_tbl;
FUNCTION Producestandardurls
(
tp_myuserid IN USERS.User_Id%TYPE,
v_scrntime IN VARCHAR2,
v_scrntoken IN VARCHAR2,
v_wwikey IN VARCHAR2
)
RETURN t_standardurlstype;
end nagendra;
/
Error :
PLS-00488 't_standardurlstype' must be type.
Whether this will required entire code changes ? like not using record as out parameter ? whether there is any solution for this ?

For the example you've shown, you just need to change the return type (for this function; potentially OUT parameter types for others) from:
RETURN t_standardurlstype;
to either:
RETURN t_standardurlstype%type;
or more simply:
RETURN t_standardurl_tbl;
Your are currently trying to return the variable t_standardurlstype, which is an instance of the t_standardurl_tbl type. With the PLSQL_V2_COMPATIBILITY setting it's allowing the type to be inferred from the variable, but you can't do that any more. You may not actually be using the variable anywhere else - if not you can remove its declaration, if you use the second form above.
So yes, you will need to make code changes, but only to how return and OUT parameters are declared, in both the package specification and body. You can continue to use a record as an OUT parameter, it just needs to be declared correctly.
There are other implications of that setting though. See My Oracle Support note 47354.1 for details, but summarising what that says, you also need to watch out for these changed behaviours, as PL/SQL now:
correctly enforces the read-only semantics of IN parameters and does not let index table methods modify index tables passed in as IN parameters.
does not permit OUT parameters to be used in expression contexts.
will not allow OUT parameters in the FROM clause of a SELECT list, where their value is read.
will return an error on the illegal syntax return expression which should be return type (which is what the code in your question is hitting).
does not allow the passing of an IN argument into another procedure as an OUT.
There is no quick fix or magic wand for these; if your code relies on any of the old behaviour in any of those categories then it will have to be modified to obey the 'new' syntax rules.

Related

How to use Variable in Alias Oracle PL/SQL

I try to use variable in the alias.
Is it possible not to change to dynamic SQL???
For example
get_this_year --> this is the function call this year, so 2018.
CREATE OR REPLACE PROCEDURE do_activity
v_cur_year VARCHAR2(11);
BEGIN
v_cur_year := get_this_year;
select t.1 AS v_cur_year -- I wanna use in here
FROM table1
END do_activity
how can I use Variable as alias.
Thanks
What you are asking for is not possible.
The column list, names, structure, etc. has to be known, when the query is parsed. Queries within PL/SQL are parsed, when PL/SQL code is parsed/compiled, so in your case, on procedure creation. (This obviously excludes dynamic queries, which are constructed in run-time, hence can't be parsed on PL/SQL compilation.)
You would have to use the dynamic SQL, to get the column name defined by the function result, but you already stated, that you do not want dynamic SQL.
There's a second issue with your code, although it may be a result of you simplifying the code. You are not capturing the query result in your procedure, which is obligatory in Oracle PL/SQL. You can't just run a query, and expect its result to be returned by running the procedure - it's not Transact-SQL. To return a data set from PL/SQL, you would have to write a tabular function (still, this would require stable data set structure, so no dynamic column naming) or you would have to use an OUT parameter of ref-cursor type.

Equivalent of oracle type boolean in sap

I have a problem with calling a stored procedure from ABAP.
I use standard ABAP class cl_sql_statement and it's methods execute_procedure and set_param. Called procedure, for example, has a single Boolean input parameter.
CREATE OR REPLACE PROCEDURE print_boolean (
p_in_flag BOOLEAN
) IS
ABAP snippet
DATA: ld_e_bool type char5,
ld_o_stat type ref to cl_sql_statement,
ld_r_data type ref to data.
***************************
ld_e_bool = 'FALSE'.
get references of ld_e_bool into ld_r_data.
ld_o_stat->set_param(DATA_REF = ld_r_data).
ld_o_stat->execute_procedure( 'print_boolean' ).
********************************************
After the call I catch an exception which says something like: 'wrong number or types of arguments'. Maybe I need another type than char5... Any help would be appreciated.
Some observation:
The JDBC drivers do not support the passing of BOOLEAN parameters to PL/SQL stored procedures( suggest wrapping the PL/SQL procedure with a second PL/SQL procedure). But i dont want to use the above option becuase there are already lot of packages/SP's are available.
The Oracle documentation is unclear on how PL/SQL boolean values are actually represented. There is also a question that discusses the use of boolean types in Oracle database fields (not really relevant here, but provides some background).
From the PL/SQL documentation:
The BOOLEAN datatype takes no parameters. Only the values TRUE, FALSE, and NULL can be assigned to a BOOLEAN variable.
You cannot insert the values TRUE and FALSE into a database column. You cannot select or fetch column values into a BOOLEAN variable. Functions called from a SQL query cannot take any BOOLEAN parameters. Neither can built-in SQL functions such as TO_CHAR; to represent BOOLEAN values in output, you must use IF-THEN or CASE constructs to translate BOOLEAN values into some other type, such as 0 or 1, 'Y' or 'N', 'true' or 'false', and so on.
In light of that, and I know you don't want to, you may need to change the type of parameter you pass into the stored procedure (e.g., use a single character or integer) and then use logic to treat that as a boolean.
In SAP doc say:
Almost all SQL statements that are valid for the addressed database system can be included between EXEC and ENDEXEC
Maybe if i try put in this section native pl/sql code i get result...
Edit: I put this code snip and it's ok.
EXEC SQL.
BEGIN
print_boolean(TRUE);
END;
ENDEXEC.
But there is one problem. This sql statement have static form only.

Getting the return value of a PL/SQL function via Hibernate

I have a PL/SQL function in an Oracle database that I can't change. This function takes a parameter which identifies an entity, creates a copy of that entity and then returns the ID of the copy. This looks something like
FUNCTION copy_entity(id IN NUMBER) RETURN NUMBER
I need to call this function from Hibernate. I tried creating a named SQL query with something similar to
CALL copy_entity(:id)
as the query, but from this I can't seem to get the return value of the function. Hibernate's "return-scalar" and similar options require a column name to return and I don't have a column name. This lead me to
SELECT copy_entity(:id) AS newEntityId
with "return-scalar" using newEntityId as column name, but this also did not work since Oracle then throws an exception that I can't call INSERT (to save the copy) in a SELECT.
Is there any way to get the return value of such a PL/SQL function? The function is actually much more complex and still required in other parts of the app, so re-writing it is not really an option.
I hope/think you can use an anonymous PL/SQL block:
begin
:myresult = copy_entity(:id);
end;
Now you have 'column name' myresult with the result.
I've never used hibernate so I hope it works. I don't know how flexible Hibernate is.
I think you are stuck using straight JDBC. The Hibernate documentation has this in the limitations section for Oracle:
For Oracle the following rules apply:
A function must return a result set.
The first parameter of a procedure
must be an OUT that returns a result
set. This is done by using a
SYS_REFCURSOR type in Oracle 9 or 10.
In Oracle you need to define a REF
CURSOR type. See Oracle literature for
further information.
Since this function accepts a number and returns a number you are out of luck with Hibernate and would probably be better off making a simple JDBC CallableStatement.

How to restrict NULL input parameters into oracle stored procedure

I have writtent some Oracle storedprocedures in these there are more then 20 input parameters and from them morethen 10 parameters are required , I want all with some value and do not want to accept null values for that , Is there anything that I can declare in the Procedure defination itself which can restrict null input parameter or Will I have to check for each value and Raise the exception if the required value is null ?
I know this is an old question, but there is another option (described here):
SUBTYPE varchar2_not_null IS VARCHAR2 NOT NULL;
You can define this type (and number_not_null, etc) either in the same package as your stored procedures, or in their own package if you want to use them in lots of places. You can then declare parameters of being these types.
If NULL gets passed as an argument, you'll get a very useful error message:
cannot pass NULL to a NOT NULL constrained formal parameter
In PL/SQL I don't know of a way around checking each one.
If you are calling the stored procedure from an external library, that library might have that functionality. This is probably not likely because frequently NULL input parameters are required.
You could make a helper PL/SQL procedure that, given a value, will raise an exception if it is null to save on redundant code. You could then write a chunk of perl/python/groovy that would slurp up your procedure declaration and crank out these calls to your null check procedure.

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