Problems using clob as a parameter to a constructor - oracle

I have the following PL/SQL code:
create type testingclob as object (
member_value number,
constructor function testingclob(
i_aclob clob
) return self as result
);
/
create type body testingclob as
constructor function testingclob(
i_aclob clob
) return self as result
is
begin
member_value := 0;
return;
end;
end;
/
declare
l_test testingclob;
begin
l_test := new testingclob('some text');
end;
But I get the error
ORA-06550: line 5, column 18:
PLS-00307: too many declarations of 'TESTINGCLOB' match this call
ORA-06550: line 5, column 4:
The compilation of the type works fine. However it appears that I cannot use the constructor. Does anybody know what I am doing wrong?

The parameter 'some text' should be declared as clob.
declare
l_param clob;
l_test testingclob;
begin
l_param:= 'some text';
l_test := new testingclob(l_param);
end;
By default, the system supplies a default constructor that accepts a parameter corresponding to each attribute, see https://docs.oracle.com/cd/B13789_01/appdev.101/b10807/10_objs.htm#i16312 chapter 'defining object constructors'. Therefore the constructor cannot be determined definitely because none of them hits the input parameter varchar2.
Try
begin
l_test := new testingclob(1);
end;
This is your default constructor.

Related

What does it means when there are two functions with the same name but different parameter in the package body?

In the package spec, the function name only appears once therefore it's not overloaded. In the package body, the same function name appears twice using different set of parameters. One of them has the same parameter as the one in the package spec. My question is, is the "first func" in the package body actually being invoked and if so, what exactly is it doing? It's trying to return itself.
--package specification
CREATE OR REPLACE
PACKAGE jtestpkg
IS
FUNCTION testfunc(p_num IN NUMBER, p_out1 IN out varchar2, p_out2 IN out varchar2)
RETURN NUMBER;
END jtestpkg;
--package body
CREATE OR REPLACE
PACKAGE BODY jtestpkg
IS
--first func
function testfunc
(p_num IN NUMBER,
p_out1 IN OUT varchar2)
return number is
v_out2 varchar2(50);
BEGIN
dbms_output.put_line('invoking first func');
RETURN testfunc(
p_num,
p_out1,
v_out2);
END;
--second func
FUNCTION testfunc(
p_num IN NUMBER,
p_out1 IN OUT varchar2,
p_out2 IN OUT varchar2)
RETURN NUMBER
IS
v_num number;
BEGIN
IF 1=p_num THEN
p_out1:='FirstOUT_1';
p_out2:='SecondOUT_1';
dbms_output.put_line(v_num||p_out1||p_out2);
RETURN 1;
elsif 2=p_num THEN
p_out1:='FirstOUT_2';
p_out2:='SecondOUT_2';
dbms_output.put_line(v_num||p_out1||p_out2);
RETURN 2;
ELSE
p_out1:='FirstOUT_3';
p_out2:='SecondOUT_3';
dbms_output.put_line(v_num||p_out1||p_out2);
return 3;
END IF;
------
p_out1:='FirstOUT_0';
p_out2:='SecondOUT_0';
dbms_output.put_line(v_num||p_out1||p_out2);
RETURN 0;
END testfunc;
END jtestpkg;
A function declared in the specification is public and can be invoked from outside the package. A function which is defined in the body but not declared in the specification is private and can only be called from within that package.
In your example the second overloaded version of your function in the package body, which you've labelled 'second func', matches the declaration in the specification, so that is the one that is involved when you call the function from elsewhere:
declare
rc number;
in_out_1 varchar2(20) := 'A';
in_out_2 varchar2(20) := 'B';
begin
rc := jtestpkg.testfunc(42, in_out_1, in_out_2);
end;
/
FirstOUT_3SecondOUT_3
PL/SQL procedure successfully completed.
The first overloaded function in your body, which you've labelled 'first func', does not have a matching declaration in the specification, so you can't call it externally:
declare
rc number;
in_out_1 varchar2(20) := 'A';
begin
rc := jtestpkg.testfunc(42, in_out_1);
end;
/
ORA-06550: line 5, column 9:
PLS-00306: wrong number or types of arguments in call to 'TESTFUNC'
ORA-06550: line 5, column 3:
PL/SQL: Statement ignored
My question is, is the "first func" in the package body actually being invoked
No. In your code the 'first func' is not ever being invoked.
It's trying to return itself.
No it isn't. Your 'first func' would call 'second func' if it was itself called from somewhere else inside the package, but you aren't currently doing that.
The debug in there says 'invoking first func' but that isn't true, it's invoking second func, since the call it makes has three arguments - matching the 'second func' argument list. (That happens to be public, but it wouldn't matter if it wasn't, since it's internal to the package anyway).
Just as an example, you could call the private function as part of the package instantiation and initialization:
...
END testfunc;
-- initialization, called on instantiation (for each session)
BEGIN
dbms_output.put_line('Initialization start');
declare
rc number;
in_out_1 varchar2(20) := 'A';
begin
dbms_output.put_line('Initialization: calling first func');
rc := testfunc(1, in_out_1);
end;
dbms_output.put_line('Initialization end');
END jtestpkg;
/
then calling anything public in the package the first time in a session instantiates it, which initializes it, which runs that package-level block. So with the same anonymous block:
declare
rc number;
in_out_1 varchar2(20) := 'A';
in_out_2 varchar2(20) := 'B';
begin
rc := jtestpkg.testfunc(42, in_out_1, in_out_2);
end;
/
you see (first time in the session only):
Initialization start
Initialization: calling first func
invoking first func
FirstOUT_1SecondOUT_1
Initialization end
FirstOUT_3SecondOUT_3
PL/SQL procedure successfully completed.
You still see the same FirstOUT_3SecondOUT_3 output as before, from the value 42 passed in that call; but before that you see the output FirstOUT_1SecondOUT_1 from 'first func' calling 'second func' with value 1 as part of that initialization process.
It is allowed for a function to call itself, i.e. recursively, but it would need to change the call each time or it would get stuck in an infinite loop, and eventually be killed. You aren't doing that either here though.

ORACLE: How to call a Stored procedure with BOTH in and out parameters

I have a StoredProcedure in Oracle with a In Parameter and a our paramterer (a cursor)
The procedure is defined as following:
PROCEDURE GetAccessObjects2(ALotteryID IN VARCHAR2, AAccessObjects OUT CURSOR_TYPE) AS
BEGIN
OPEN AAccessObjects FOR
SELECT AccessObjectID, AccessObjectName
FROM AccessObjects;
END;
Then I try to call it from Delphi:
procedure TForm7.Button1Click(Sender: TObject);
begin
with ADOStoredProc1 do
begin
Connection := ADOConnection1;
CursorType := ctOpenForwardOnly;
MaxRecords := 5000;
ProcedureName := 'DDK.GetAccessObjects2';
with Parameters.AddParameter do
begin
Name := 'ALotteryID';
DataType := ftString;
Value := 'TEST';
end;
end;
ADOStoredProc1.Open;
end;
But then I got an exception :
ORA-06550: line 1, column 7: PLS-00306: wrong number or types of
arguments in call to 'GETACCESSOBJECTS2' ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
PS: ADOConnection1 is a valid connection to the database.
According to this web page it isn't necessary to define a parameter for the cursor (AAccessObjects) but oracle thinks otherwise.
So in short how do I call my SP from Delphi with ADO
UPDATE
I've tried to provide the curser ad a parameter:
with ADOStoredProc1 do
begin
Connection := ADOConnection1;
CursorType := ctOpenForwardOnly;
MaxRecords := 5000;
ProcedureName := 'DDK.GetAccessObjects2';
Parameters.CreateParameter('ALotteryID', ftString, pdInput, 255, 'TEST');
Parameters.CreateParameter('AAccessObjects', ftCursor, pdOutput, 0, null);
end;
ADOStoredProc1.Open;
But then I get an Exception inside ADO:
Parameter object is improperly defined
Try this:
ParamType := ptOutput
Not sure what the datatype will be for a CURSOR_TYPE in Oracle.

i have created stored procedure but can't able to execute same

I defined a stored procedure
create or replace procedure spfirst
(
sp_loc out varchar,
sp_sal out int
)
as
begin
select LOCATION, MONTHLY_SALARY
into sp_loc, sp_sal
from nilesh;
end;
I then call the procedure and get an error
begin
spfirst;
end;
ORA-06550: line 2, column 1:
PLS-00201: identifier 'SPNAME' must be declared
ORA-06550: line 2, column 1:
PL/SQL: Statement ignored
Your procedure takes two parameters. You are calling it without any parameters. Oracle thus looks for a procedure named spfirst that takes no parameters, finds no such procedure, and throws an error.
Something like
DECLARE
l_location nilesh.location%type;
l_salary nilesh.monthly_salary%type;
BEGIN
spfirst( l_location, l_salary );
END;
should work. Of course, you'd generally want to do something with the variables that are returned. If you've enabled dbms_output, you could print them out
DECLARE
l_location nilesh.location%type;
l_salary nilesh.monthly_salary%type;
BEGIN
spfirst( l_location, l_salary );
dbms_output.put_line( 'Location = ' || l_location );
dbms_output.put_line( 'Salary = ' || l_salary );
END;
Be aware that your procedure will throw an error unless the nilesh table has exactly one row. It seems likely that you either want the procedure to take an additional parameter that is the key to the table so that the select into always returns a single row or that you want a function that returns a sys_refcursor rather than a procedure that has multiple out parameters.

Function having an in parameter and returning a object type

How can I pass number as in parameter and return a object type in a function
create type my_details as
object(v_ename varchar2(20),v_sal number(10));
create or replace function f_emp(v_empno in number)
return my_details
as
v_det my_details;
begin
select ename,sal
into v_det.v_ename,v_det.v_sal
from emp
where empno=v_empno;
return v_det;
end;
When I try to call the function, I get an error
declare
v_type my_details;
begin
v_type:=f_emp(7839);
end;
/
The error stack
declare
*
ERROR at line 1:
ORA-06530: Reference to uninitialized composite
ORA-06512: at "SCOTT.F_EMP", line 6
ORA-06512: at line 4
Can any one help me pointing out where I have made mistake and how can I improve this?
Your function would either need to initialize the object before referencing it
create or replace function f_emp(v_empno in number)
return my_details
as
v_det my_details := new my_details(null, null);
begin
select ename,sal
into v_det.v_ename,v_det.v_sal
from emp
where empno=v_empno;
return v_det;
end;
or your could call the constructor as part of the select
create or replace function f_emp(v_empno in number)
return my_details
as
v_det my_details;
begin
select my_details(ename,sal)
into v_det
from emp
where empno=v_empno;
return v_det;
end;
Putting the constructor in the select statement would be the approach I would generally suggest.

expression 'string' cannot be used as an assignment target -SQL PLUS

I wrote the following procedure which was meant to be anonymous and remove all the vowels from a string, but when I call it I get an error: I've followed the advice given in a similar post, but it didn't help:Oracle PLS-00363: expression '' cannot be used as an assignment target
SQL> CREATE OR REPLACE PROCEDURE disemvowel (string IN OUT NVARCHAR2)
2 IS
3 BEGIN
4 DBMS_OUTPUT.PUT_LINE(translate(string,'euioa',''));
5 END disemvowel;
6 /
Procedure created.
So good so far, but now I call it:
SQL> BEGIN
2 disemvowel('hahahahaha');
3 END;
4 /
The Error message says:
disemvowel('hahahahaha');
*
ERROR at line 2:
ORA-06550: line 2, column 12:
PLS-00363: expression 'hahahahaha' cannot be used as an assignment target
ORA-06550: line 2, column 1:
PL/SQL: Statement ignored
Your procedure has IN OUT parameter. So while calling the procedure you should supply a variable to it, so that it can hold the value that the procedure gives back. You cannot supply a value directly, as it cannot be modified by the procedure.
DECLARE
param NVARCHAR2 (20) := 'hahahahaha';
BEGIN
disemvowel (param);
END;
/
Generate new VARCHAR2 type variable to assign your IN (input) string.
PROCEDURE sp_name(
ps_list IN VARCHAR2,
...
write here other IN's and OUT's
...
)
AS
ps_list_copy VARCHAR2 (32000);
BEGIN
ps_list_copy := ps_list;
...
do your works with ps_list_copy
...
...
EXCEPTION WHEN OTHERS THEN
....
END sp_name;

Resources