ORA-06550 in "IS NOT A SET" - oracle

I am trying to find duplicated values in a ttXs:
DECLARE
type invmXXs is table of inv_table.mobileId%type index by binary_integer;
ttXs invmXXs;
answer BOOLEAN;
BEGIN
-- out_exported_list is ref cursor
-- (...)
OPEN out_exported_list FOR
/* (....) */
FETCH out_exported_list
BULK COLLECT INTO ttXs;
answer := ttXs IS NOT A SET; -- ORA-06550
-- ...
END;
But I am getting ORA-06550 and I dont know why. How can I fix it?
Error at line 1 ORA-06550: line 46, column 14: PLS-00306: wrong number
or types of arguments in call to 'MULTISET_UNION_DISTINCT' ORA-06550:
line 46, column 1: PL/SQL: Statement ignored

Below is a very simplified example in whcih you can try to handle/Find out Duplicate with nested tables. You are trying to achiev this by using Associative Array which doesnt support SET operations. Hope this helps.
set serveroutput on;
DECLARE
TYPE lv_var
IS
TABLE OF VARCHAR2(100);
v_tab lv_var;
v1_tab lv_var;
BEGIN
v_tab :=lv_var('a','a','b','c','d','d','e');
v1_tab:=SET(v_tab);
v1_tab:=SET(v_tab MULTISET
EXCEPT v1_tab);
FOR i IN v1_tab.FIRST..v1_tab.LAST
LOOP
dbms_output.put_line(v1_tab(i));
END LOOP;
END;

Related

Oracle access the record type values using dot notation with identifiers from varray

I am going to access the values from oracle record using the dot notation and identifier as variable, i am getting error V_COL must be declared.
declare
cursor c1 is select * from temp_sample_records;
type t is table of temp_sample_records%rowtype;
l_tab t;
rec c1%rowtype;
term term_cell_data#ktkcm%rowtype;
term_reverify term_cell_data_reverify#ktkcm%rowtype;
type t_cols IS VARRAY(100) OF VARCHAR2(100);
cols t_cols;
V_COL varchar2(100);
begin
cols := t_cols('GSMNUMBER','CAF_SERIAL_NO','CUSTOMER_NAME');
open c1;
loop
fetch c1 bulk collect into l_tab limit 5000;
exit when l_tab.count=0;
for i in l_tab.first..l_tab.last loop
begin
select * into term from term_cell_data#ktkcm where gsmnumber=l_tab(i).msisdn and caf_serial_no=l_tab(i).caf_serial_no;
for c in 1..cols.last loop
V_COL :=cols(c);
dbms_output.put_line(term.V_COL);
end loop;
exception
when no_data_found then null;
end;
end loop;
end loop;
close c1;
end;
/
kindly help where i am making a mistake
Error ORA-06550: line 22, column 51:
PLS-00302: component 'V_COL' must be declared
ORA-06550: line 22, column 25:
PL/SQL: Statement ignored
where i am making a mistake
term.V_COL is not valid as, I am assuming that, you do not have a column named V_COL in the term_cell_data#ktkcm table and you are trying to dynamically access the columns. You cannot do this.
You could look at reflection using ANYDATA, however that does not work with record data types and would need Object data types defined in the SQL scope.
You could also look at the DBMS_SQL package but I think that, even if you worked to get the data using position indexes rather than column names, you would still need to know the data type of every column.
You would probably be best to just statically name each column in the %ROWTYPE variable (rather than trying to dynamically reference columns). So in your inner-most loop, you could use:
select *
into term
from term_cell_data#ktkcm
where gsmnumber=l_tab(i).msisdn
and caf_serial_no=l_tab(i).caf_serial_no;
dbms_output.put_line(term.GSMNUMBER);
dbms_output.put_line(term.CAF_SERIAL_NO);
dbms_output.put_line(term.CUSTOMER_NAME);

Can I use INSERT ALL with multiple recordtype variables?

Given a PL/SQL block where I have access to 2 recordtype variables, I want to insert these 2 records into the same table in a single statement, but my attempts to use INSERT ALL have failed thus far. Is it possible to use INSERT ALL with record variables at all?
Here is some code that works, using dedicated inserts:
DECLARE
mProperty1 MyTable%ROWTYPE;
mProperty2 MyTable%ROWTYPE;
...
BEGIN
...
INSERT INTO MyTable VALUES mProperty1;
INSERT INTO MyTable VALUES mProperty2;
...
END;
If I try to convert the statement to a INSERT ALL though, it fails with an error message:
DECLARE
mProperty1 MyTable%ROWTYPE;
mProperty2 MyTable%ROWTYPE;
...
BEGIN
...
INSERT ALL
INTO MyTable VALUES mProperty1
INTO MyTable VALUES mProperty2
SELECT 1 FROM DUAL;
...
END;
ORA-06550: line 14, column 60:
PLS-00382: expression is of wrong type
ORA-06550: line 13, column 60:
PLS-00382: expression is of wrong type
ORA-06550: line 13, column 60:
PL/SQL: ORA-00904: : invalid identifier
ORA-06550: line 12, column 7:
PL/SQL: SQL Statement ignored
Am I missing something obvious? Is there a way to make this statement work?
I have tried using different methods but succeeded with the only following:
Method 1:
Using particular record names from %ROWTYPE field
DECLARE
mProperty1 MyTable%ROWTYPE;
mProperty2 MyTable%ROWTYPE;
BEGIN
mProperty1.COL1 := 1;
mProperty2.COL1 := 2;
INSERT ALL
INTO MyTable VALUES (mProperty1.col1)
INTO MyTable VALUES (mProperty2.col1)
SELECT 1 FROM DUAL;
END;
/
-- may be bad choice but you can use like this
Method 2:
If you are concerned about performance then you can also use this method:
DECLARE
TYPE mProperty_TYPE IS TABLE OF MyTable%ROWTYPE;
mProperty mProperty_TYPE;
BEGIN
mProperty := mProperty_TYPE();
mProperty.EXTEND(2);
mProperty(1).COL1 := 3;
mProperty(2).COL1 := 4;
FORALL I IN 1..mProperty.COUNT
INSERT INTO MyTable VALUES mProperty(I);
END;
/
db<>fiddle demo

Apex button and procedure

Im trying to create button in Apex which execute given procedure. As input values I gave two date fields called Poczatek and Koniec. The button should execute this procedure on submit. It perfectly works in Oracle, but throw a lot of errors in Apex.
set serveroutput on
create or replace procedure KORELACJA(:Poczatek, :Koniec)
IS
miasto VARCHAR(25);
korelacja NUMBER;
cursor c1 is
SELECT TEMP.nazwa, corr(TEMP.temperatura, WILGOTNOSC.wilg)
FROM TEMP INNER JOIN WILGOTNOSC
on TEMP.nazwa = WILGOTNOSC.nazwa
and TEMP.data = WILGOTNOSC.data
WHERE TEMP.data between to_date(:Poczatek, 'YYYY-MM-DD') and to_date(:Koniec, 'YYYY-MM-DD')
GROUP BY TEMP.nazwa;
BEGIN
DBMS_OUTPUT.put_line(RPAD('Miasto',10)||RPAD('Korelacja',10));
open c1;
FOR i IN 1..6
LOOP
commit;
fetch c1 into miasto, korelacja;
DBMS_OUTPUT.put_line(RPAD(miasto,10)||RPAD(korelacja,10));
END LOOP;
close c1;
END KORELACJA;
/
Errors look like this:
1 error has occurred
ORA-06550: line 2, column 5: PL/SQL: ORA-00922: missing or invalid option
ORA-06550: line 2, column 1: PL/SQL: SQL Statement ignored ORA-06550: line 6,
column 11: PLS-00103: Encountered the symbol "NUMBER" when expecting one of the
following: := . ( # % ; ORA-06550: line 9, column 18: PLS-00103: Encountered the symbol "JOIN" when
expecting one of the following: , ; for group having intersect minus order start
union where connect
Anyone knows the solution?
I'd suggest you to leave the procedure in the database; call it from Apex.
As you said that it works OK, I'm not going to examine the code. Just modify the first line:
create or replace procedure KORELACJA(par_Poczatek in date,
par_Koniec in date)
is ...
Then, in Apex process, call the procedure as
korelacja(:p1_poczatek, :p2_koniec);
Note that you might need to apply TO_DATE function to those items, using appropriate format mask, such as
korelacja(to_date(:p1_poczatek, 'dd.mm.yyyy',
to_date(:p1_koniec , 'dd.mm.yyyy');
If you insist on keeping the procedure in Apex' process (I wouldn't recommend it), the you don't need CREATE PROCEDURE but an anonymous PL/SQL block. It won't accept any parameters - use Apex items directly.
declare
miasto VARCHAR(25);
korelacja NUMBER;
cursor ...
WHERE TEMP.data between to_date(:p1_Poczatek, 'YYYY-MM-DD') ...
begin
...
end;

PLS-00306: wrong number or types of arguments in call to a Oracle SP

I'm trying to execute a below SP and it throws be the below error:
CREATE OR REPLACE PROCEDURE denodo.CLEAR_INDEX
( INDEX_NAME1 IN VARCHAR2,
INDEX_NAME2 IN VARCHAR2,
IT_WORKED OUT BOOLEAN ) as
BEGIN
IT_WORKED := FALSE;
EXECUTE IMMEDIATE 'drop index ' || INDEX_NAME1;
EXECUTE IMMEDIATE 'drop index ' || INDEX_NAME2;
IT_WORKED := TRUE;
EXCEPTION
WHEN OTHERS THEN
IT_WORKED := FALSE;
END CLEAR_INDEX;
CLEAR_INDEX#0 [JDBC ROUTE] [ERROR] Received exception with message 'ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'CLEAR_INDEX'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
What is going on here? appreciate your help.
This error you generally face when you deal with BOOLEAN datatype as OUT parameter and you try to print it or do any operation with any other inbuilt Oracle packages. You cannot directly use BOOLEAN datatype in dbms_output.put_line or any other DBMS package. For instance,if you want to print the OUT parameter you need to use sys.diutil.bool_to_int.
See below example which demonstrate the error you faced when you try to execute as below:
DECLARE
inx VARCHAR2(100):='ABC';
var BOOLEAN;
BEGIN
CLEAR_INDEX(INDEX_NAME1=>inx ,IT_WORKED =>var);
dbms_output.put_line(var);
END;
You face the issue:
ORA-06550: line 6, column 3:
PLS-00306: wrong number or types of arguments in call to 'PUT_LINE'
ORA-06550: line 6, column 3:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action
To overcome such issue you must execute as below:
DECLARE
inx VARCHAR2(100):='ABC';
var BOOLEAN;
var1 varchar2(10);
BEGIN
CLEAR_INDEX(INDEX_NAME1=>inx ,IT_WORKED =>var);
var1:=CASE WHEN (sys.diutil.bool_to_int(var)) = 1 THEN 'TRUE'
WHEN (sys.diutil.bool_to_int(var)) = 0 THEN 'FALSE'
END;
dbms_output.put_line(var1);
END;
Output:
anonymous block completed
Mine is a similar case, however, a different call to a function, which has return type as Boolean and the input to the function is varchar2.
So, this is what I am doing:
Declare
v_ret1 varchar2(1000);
v_ret BOOLEAN;
Begin
v_ret := CASE WHEN SEI_PROCESS_MF_MNL_INVC_PKG.f_process_mf_mnl_invc(v_ret1) = 1 THEN 'TRUE'
WHEN SEI_PROCESS_MF_MNL_INVC_PKG.f_process_mf_mnl_invc(v_ret1) = 0 THEN 'FALSE'
END;
dbms_output.put_line(v_ret);
end;
I just wanted to see output of v_ret so that I can use that for further decision making. If v_ret is of type Boolean, the output should be either "TRUE" or "FALSE".

Executing Stored Procedure - Oracle PL SQL

I'm currently trying to execute a stored procedure in Oracle PL SQL. I keep running into the same error for the below with execution.
I've tried both execution with the same error
SET SERVEROUTPUT ON;
EXEC get_phone(200.00,500.00);
OR
SET SERVEROUTPUT ON;
DECLARE
c_minprice products.price%type;
c_maxprice products.price%type;
BEGIN
c_minprice := get_phone(200);
c_maxprice := get_phone(500);
END;
ERROR from executing the above:
c_minprice := get_phone(200);
*
ERROR at line 5:
ORA-06550: line 5, column 15:
PLS-00306: wrong number or types of arguments in call to 'GET_PHONE'
ORA-06550: line 5, column 1:
PL/SQL: Statement ignored
ORA-06550: line 6, column 15:
PLS-00306: wrong number or types of arguments in call to 'GET_PHONE'
ORA-06550: line 6, column 1:
PL/SQL: Statement ignored
****Sample Snip-its form my code:
CREATE OR REPLACE PROCEDURE get_phone
(
c_minprice IN products.price%type,
c_maxprice IN products.price%type,
i_result OUT VARCHAR2
) AS
--Checking if starting price range is valid or not
IF c_minprice IS NULL THEN
i_result := 'Starting price range should be valid and cannot be empty';
RAISE V_MINPRICE; -- Raising exception if starting price is null
END IF;
--Checking if end price range is valid or not
IF c_maxprice IS NULL THEN
i_result := 'End price range should be valid and cannot be empty';
RAISE V_MAXPRICE; -- Raising exception if end price is null
END IF;
Your procedure requires three parameters so you have to pass in three parameters
DECLARE
l_result varchar2(100);
BEGIN
get_phone( 200, 500, l_result );
END;
/
should work. Of course, your procedure seems rather pointless. And if the goal is simply to return a result, you really ought to be using a function rather than a procedure with an out parameter.
get_phone expects 3 arguments, c_minprice, c_maxprice and i_result. You are only passing it one number. Pass it the rest of the arguments.

Resources