difference between creating a type with new keyword or without in plsql - oracle

In oracle pl/sql you can create an object with or without the new keyword.
Is there any difference how oracle threats these requests ?
So for example:
CREATE TYPE emp_object AS OBJECT(
emp_no NUMBER,
emp_name VARCHAR2(50),
salary NUMBER,
manager NUMBER,
CONSTRUCTOR FUNCTION emp_object(p_emp_no NUMBER, p_emp_name VARCHAR2,
p_salary NUMBER) RETURN SELF AS RESULT),
MEMBER PROCEDURE insert_records,
MEMBER PROCEDURE display_records);
/
CREATE OR REPLACE TYPE BODY emp_object AS
CONSTRUCTOR FUNCTION emp_object(p_emp_no NUMBER,p_emp_name VARCHAR2,
p_salary NUMBER)
RETURN SELF AS RESULT
IS
BEGIN
Dbms_output.put_line('Constructor fired..');
SELF.emp_no:=p_emp_no;|
SELF.emp_name:=p_emp_name;
SELF.salary:=p_salary;
SELF.managerial:=1001;
RETURN;
END:
MEMBER PROCEDURE insert_records
IS
BEGIN
INSERT INTO emp VALUES(emp_noemp_name,salary,manager);
END
MEMBER PROCEDURE display_records
IS
BEGIN
Dbms_output.put_line('Employee Name:'||emp_name);
Dbms_output.put_line('Employee Number:'||emp_no);
Dbms_output.put_line('Salary':'||salary);
Dbms_output.put_line('Manager:'||manager);
END:
END:
/
This is a type with spec and body, now you can create the object like this without the new keyword:
DECLARE
guru_emp_det emp_object;
BEGIN
guru_emp_det:=emp_object(1005,'RRR',20000,1000);
guru_emp_det.display_records;
guru_emp_det.insert_records;
COMMIT;
END;
But it is also possible with the keyword:
DECLARE
guru_emp_det emp_object;
BEGIN
guru_emp_det:= new emp_object(1005,'RRR',20000,1000);
guru_emp_det.display_records;
guru_emp_det.insert_records;
COMMIT;
END;

From the Type Constructor Expressions documentation:
Type Constructor Expressions
A type constructor expression specifies a call to a constructor method. The argument to the type constructor is any expression. Type constructors can be invoked anywhere functions are invoked.
type_constructor_expression::=
The NEW keyword applies to constructors for object types but not for collection types. It instructs Oracle to construct a new object by invoking an appropriate constructor. The use of the NEW keyword is optional, but it is good practice to specify it.
As to your question:
Is there any difference how oracle treats these requests?
No, there is no difference; the NEW keyword is optional.
Although the documentation states that the NEW keyword does not apply for collection types, in practice it does not appear to be invalid syntax and is both allowable and optional for collection types (there may be an edge-case I have not yet found where the NEW keyword is forbidden; however, on some brief tests I cannot find such a case).
fiddle

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.

How can i use REF type in PL/SQL Oracle?

I have this code :
CREATE OR REPLACE TYPE t_abonnement_type AS OBJECT
(
ref_abonnement_type NUMBER,
type_abonne VARCHAR(50),
MEMBER PROCEDURE DISPLAY
);
CREATE OR REPLACE TYPE t_abonnement AS OBJECT
(
ref_abonnement NUMBER,
date_debut DATE,
type_abonnement REF t_abonnement_type,
MEMBER PROCEDURE DISPLAY
);
What i want to do is just create the members procedures DISPLAY declared.
So i did it this way :
CREATE OR REPLACE TYPE BODY t_abonnement AS
MEMBER PROCEDURE DISPLAY IS
BEGIN
/* SOME CODE */
type_abonnement.display;
END;
END;
And i get this error
PLS-00536: Navigation through REF variables is not supported in PL/SQL.
So how can i deal with REF in PL/SQL statements ?
Thanks
As mentioned by #APC, it's not possible to directly use member function of a Object to another using REF since Oracle supports them in SQL but not in PL/SQL.
However if I look at your requirement from a different angle, I could see you are trying to simply make use of Procedure used in an Object to another Object. Means if I forget the referencing part and create a scenario which could satisfy the referencing concept then it should "OK".
This is possible. Yes..!!! This can be done. The only thing I did here is to make the two Objects as parent-child to achieve referencing. See demo below:
--Parent Object
CREATE OR REPLACE TYPE t_abonnement_type AS OBJECT
(
ref_abonnement_type NUMBER,
type_abonne VARCHAR(50),
MEMBER FUNCTION DISPLAY return varchar2
) NOT FINAL;
-- Member Funtion Body
CREATE OR REPLACE TYPE BODY t_abonnement_type
AS
MEMBER FUNCTION DISPLAY
return varchar2
IS
BEGIN
return ('Hi');
END DISPLAY;
END;
Testing my Parent Object:
SQL> SELECT t_abonnement_type(1,'a').display() col from DUAL;
COL
---
Hi
Child Object to achieve referencing concept
CREATE OR REPLACE TYPE t_abonnement
under t_abonnement_type
(
ref_abonnement NUMBER,
date_debut DATE,
MEMBER function V_DISPLAY return varchar2
);
--Member function
CREATE OR REPLACE TYPE BODY t_abonnement
AS
MEMBER Function V_DISPLAY return varchar2
IS
var varchar2(10);
BEGIN
var:= t_abonnement_type(1,'A').display(); --Calling Parent Member function here
return('Called from Child Object -->'||var);
END;
END;
Testing my Child Object to check if the parent Member function is referenced or not:
SQL> SELECT T_ABONNEMENT(1,'A',2,TO_DATE('30-JUN-2018','DD-MON-YYYY')).V_DISPLAY() COL FROM DUAL;
Col
---
Called from Child Object -->Hi
Note I haven't used overloading done in your code as I feel overloading makes the stuff harder to understand as an individual as well as for compiler.

Setter methods in UDT in Oracle database

I'm still new to this and trying to get my head around it. UDT are able to define methods which you can call on the object stored, I seem to create a method that returns a value fine but was wondering if it's possible create a setter methods. This scenario isn't really useful but it's simple just for clarification
For example, I have this type:
create TYPE TestType2 AS OBJECT(
Numb NUMBER(4),
Str VARCHAR2(10),
MEMBER FUNCTION setNum(numba NUMBER) RETURN NUMBER
);
Which compiles fine so my assumption setter methods are allow
I've tried create the body type below:
CREATE TYPE BODY TestType2 as
member function setNum(numba NUMBER) return NUMBER is
begin
SELF.Numb := numba;
return SELF.Numb;
END;
END;
However this won't work giving me the errors below:
Error(3,9): PL/SQL: Statement ignored
Error(3,14): PLS-00363: expression 'SELF.NUMB' cannot be used as an assignment target
Is there a way to create a set method or is this only allowed in store procedures?
This is an obscure error. The problem is member functions take an implicit parameter of SELF. So if you want to change something you need to make the parameter explicit:
create or replace TYPE TestType2 AS OBJECT(
Numb NUMBER(4,0),
Str VARCHAR2(10),
MEMBER procedure setNum(self in out TestType2, numba NUMBER )
);
/
CREATE or replace TYPE BODY TestType2 as
member function setNum(self in out TestType2 , numba NUMBER) return NUMBER
is
begin
self.Numb := numba;
return SELF.Numb;
END;
END;
/
Note that the SELF parameter remains implicit when calling the function:
declare
t TestType2 := TestType2(4, 'TEST');
n pls_integer;
begin
dbms_output.put_line('1' || t.numb);
n := t.setNum(8);
dbms_output.put_line('2' || t.numb);
end;
/
Incidentally, setter methods don't need to be functions; we can have member procedures too.
create or replace TYPE TestType2 AS OBJECT(
Numb NUMBER(4,0),
Str VARCHAR2(10),
MEMBER procedure setNum(self in out TestType2, numba NUMBER ),
MEMBER FUNCTION getNum RETURN NUMBER
);
/
CREATE or replace TYPE BODY TestType2 as
member procedure setNum(self in out TestType2, numba NUMBER )
is
begin
self.Numb := numba;
END;
MEMBER FUNCTION getNum RETURN NUMBER
is
begin
return self.numb;
end;
END;
/

PLS-00307 when subprograms differ only in type parameters (RAW vs VARCHAR2)

I have a package with two methods:
create or replace package demo
as
function overloaded(p_in varchar2)
return pls_integer;
function overloaded(p_in raw)
return pls_integer;
end;
/
create or replace package body demo
as
function overloaded(p_in raw)
return pls_integer
is
begin
return 1;
end;
function overloaded(p_in varchar2)
return pls_integer
is
begin
return 2;
end;
end;
/
It compiles without any errors, but I cannot call either method, as in both cases I get error PLS-00307: too many declarations match this call. Why does this happen with RAW and VARCHAR2? How can I work around this limitation? Is giving different names to my subprograms the only way out?
The documentation says:
PL/SQL lets you overload nested subprograms, package subprograms, and type methods. You can use the same name for several different subprograms if their formal parameters differ in name, number, order, or data type family.
And according to the the appendix that refers to, 'varchar2 and raw are both members of the char data type family.
You can give the subprograms different names, but you can also change the name and order of the formal parameters; in this case as there is only one parameter that means you can change only the name(s):
create or replace package demo
as
function overloaded(p_in_vc varchar2)
return pls_integer;
function overloaded(p_in_raw raw)
return pls_integer;
end;
/
(and the same change in the body of course); and then call with named notation for the actual parameters:
select demo.overloaded(p_in_vc=>'test') from dual;
DEMO.OVERLOADED(P_IN_VC=>'TEST')
--------------------------------
2
select demo.overloaded(p_in_raw=>'AABB') from dual;
DEMO.OVERLOADED(P_IN_RAW=>'AABB')
---------------------------------
1

Possible to create Oracle Database object types inside of PL/SQL?

Is it possible to create an object type inside of a package in Oracle Database 10g? Something like:
create or replace package my_package as
type my_type as object (
id number(15)
);
end;
Gives:
Error(3,9): PLS-00540: object not supported in this context.
What I'm ultimately looking to be able to do is use polymorphism but also allow the objects to access tables and use PL/SQL, which isn't allowed in types defined outside of packages.
Thanks,
Jeff
From the Oracle 10g documentation:
Currently, you cannot define object
types in a PL/SQL block, subprogram,
or package.
So, unfortunately, no.
Update for Oracle 11g Release 2:
From Chapter 3 Using PL/SQL With Object Types of Oracle Database Object-Relational Developer's Guide:
Using object types in a PL/SQL block, subprogram, or package is a two-step process.
You must define object types using the SQL statement CREATE TYPE, in SQL*Plus or other similar programs.
After an object type is defined and installed in the schema, you can use it in any PL/SQL block, subprogram, or package.
In PL/SQL, you then declare a variable whose data type is the user-defined type or ADT that you just defined.
You can use PL/SQL in objects that are defined outside a PL/SQL package!! Use object bodies:
CREATE TYPE person_typ AS OBJECT (
idno NUMBER,
first_name VARCHAR2(20),
last_name VARCHAR2(25),
email VARCHAR2(25),
phone VARCHAR2(20),
MAP MEMBER FUNCTION get_idno RETURN NUMBER,
MEMBER PROCEDURE display_details ( SELF IN OUT NOCOPY person_typ ));
/
CREATE TYPE BODY person_typ AS
MAP MEMBER FUNCTION get_idno RETURN NUMBER IS
BEGIN
RETURN idno;
END;
MEMBER PROCEDURE display_details ( SELF IN OUT NOCOPY person_typ ) IS
BEGIN
-- use the PUT_LINE procedure of the DBMS_OUTPUT package to display details
DBMS_OUTPUT.PUT_LINE(TO_CHAR(idno) || ' ' || first_name || ' ' || last_name);
DBMS_OUTPUT.PUT_LINE(email || ' ' || phone);
END;
END;
/
copy-pasted this example from this link: http://www.mcs.csueastbay.edu/support/oracle/doc/10.2/appdev.102/b14260/adobjint.htm

Resources