Using TABLE as array in PL/SQL - plsql

I am using this anonymous function to test a programming construct for inclusion in a larger script:
DECLARE
TYPE array IS TABLE OF VARCHAR2(255);
g_to array DEFAULT array ();
BEGIN
INSERT INTO g_to VALUES ('myaddy#internet.com');
END;
But, when I run it, I get:
*Error starting at line : 1 in command -
DECLARE
TYPE array IS TABLE OF VARCHAR2(255);
g_to array DEFAULT array ();
BEGIN
INSERT INTO g_to VALUES ('myaddy#internet.com');
END;
Error report -
ORA-06550: line 10, column 17:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 10, column 5:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:*
Now, the array is clearly defined, so why is the INSERT failing?

When you place the array into a place where it needs to be interpreted by the SQL interpreter (as opposed to the PL/SQL interpreter), then the array must be a database object, rather than locally defined. This is the case when you want to select from an array, for instance.
However, in this case you're trying to do something that would be invalid even if the array were a database object. You simply can't specify a variable as the target of an INSERT statement no matter what its declaration is. To do this correctly you need to use SELECT... BULK COLLECT INTO...:
DECLARE
TYPE array IS TABLE OF VARCHAR2(255);
g_to array DEFAULT array ();
BEGIN
SELECT 'myaddy#internet.com' BULK COLLECT INTO g_to FROM dual;
END;
However, if you're just adding a static value into the array, you'd be better off skipping the context switch incurred by using SQL and insert the value directly:
DECLARE
TYPE array IS TABLE OF VARCHAR2(255);
g_to array DEFAULT array ();
BEGIN
g_to.extend
g_to(g_to.last) := 'myaddy#internet.com';
END;

Related

Expression is of wrong type when sending nested array to Function

I want to send a collection to a Function, but I keep getting an error.
I defined the RECORD and TYPES in my Package Header and Implemented the body aswell. I dont understand why I cant send a simple collection as a parameter, the idea is for me to loop through the collection and do some comparisation then return a char within a sql statement.
Been struggling with this for a week now, any help is appreciated.
Exact error:
ORA-06550: line 9, column 45:
PLS-00382: expression is of wrong type
ORA-06550: line 9, column 40:
PLS-00306: wrong number or types of arguments in call to 'TEST_F'
ORA-06550: line 9, column 23:
PL/SQL: ORA-00904: "PACKAGE_SS"."TEST_F": invalid identifier
ORA-06550: line 9, column 3:
PL/SQL: SQL Statement ignored
Header:
create or replace
PACKAGE PACKAGE_SS AS
type t_itemnumber is table of varchar2(100) index by BINARY_INTEGER;
type t_alternative_rec is record
(
itemnumber t_itemnumber
);
type t_alternative_prev is table of t_alternative_rec INDEX BY BINARY_INTEGER;
type t_procestype_rec is record
(
procestype char
);
TYPE result_table IS TABLE OF t_procestype_rec;
FUNCTION test_f(p_items_prev IN t_alternative_prev) RETURN result_table PIPELINED;
END AOPA_VALIDATE_SS;
The package body looks like this:
create or replace
PACKAGE BODY PACKAGE_SS AS
FUNCTION test_f(p_items_prev IN t_alternative_prev) RETURN result_table PIPELINED IS
processType char(1) := 'U';
rec t_procestype_rec :=null;
BEGIN
DBMS_OUTPUT.PUT_LINE('ENTERD ');
if (processType= 'U') then
select 'U' into rec from dual;
end if;
if (processType='C') then
select 'C' into rec from dual;
end if;
if (processType='D') then
select 'D' into rec from dual;
end if;
pipe row (rec);
return;
END test_f;
END PACKAGE_SS;
Usage plsql script:
DECLARE
prev_rev_alternatives PACKAGE_SS.t_alternative_prev;
BEGIN
prev_rev_alternatives(1).itemnumber(10) := 'PR454545';
prev_rev_alternatives(1).itemnumber(20) := 'PR333333';
SELECT * FROM table(PACKAGE_SS.test_f(prev_rev_alternatives));
END;
There are two things which my eyes fall upon:
Usage of SELECT without INTO in an anonymous PLSQL block is not supposed to work.
Usage of types in an SQL statement requires the type defined as an object, not within a package specification.
Try
CREATE TYPE
https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_8001.htm
and
SELECT * INTO ... FROM ...
This might help.

how to use collection type in PLSQL, while receiving multiple value from front end java page?

Actually my requirement is,am having 3 tables so i need to create type for each table or consolidate type to all table. but in java developer have to send the multiple parameter to my Procedure, so how to get the multiple values in single type and insert it into table??
Object type
CREATE OR REPLACE TYPE "POL_QUAT_TYPE"
IS OBJECT (V_POLICY_NO VARCHAR2 (30),
V_FOREIGN_POLICY VARCHAR2 (1));
tabletype
CREATE OR REPLACE TYPE POL_QUAT_table IS TABLE OF POL_QUAT_TYPE
Sample procedure
CREATE OR REPLACE PROCEDURE TEST1 (A POL_QUAT_TYPE) IS
B VARCHAR2(100);
C VARCHAR2(100);
BEGIN
B:=A(1);
C:=A(1);
INSERT INTO TEST ( PART, B )
VALUES (B,C);
COMMIT;
END;
Call this procedure
begin
test1('a','b');
end;
I want to know how get the value (a,b) though procedure from collection type.
Ok, you can insert the contents of an array of objects into the table like so:
CREATE OR REPLACE TYPE "POL_QUAT_TYPE"
IS OBJECT (V_POLICY_NO VARCHAR2 (30),
V_FOREIGN_POLICY VARCHAR2 (1));
/
CREATE OR REPLACE TYPE POL_QUAT_table IS TABLE OF POL_QUAT_TYPE;
/
CREATE OR REPLACE PROCEDURE TEST1 (p_a in POL_QUAT_table)
as
BEGIN
INSERT INTO TEST (PART, B)
select t.v_policy_no,
t.v_foreign_policy
from table(p_a) t;
COMMIT;
END;
/
I've created a test case to demonstrate that it works over on Oracle LiveSQL.
This means you can insert all the content of the array in one go without having to loop through the array and insert one record at a time, so it should be much more performant.

Mixing arrays and queries

I have a set of product that I want to tag to a certain value so what I did this:
declare
type array_produit_auto is varray(3) of varchar(50);
array array_produit_auto := array_produit_auto('code_product1', 'code_product2', 'code_product3');
begin
for i in 1..array.count loop
update F_PRODUITASS pas
set PAS_NONGES_IDA = 0
WHERE PAS.PAS_CODE_PRODUIT = array(i;
end loop;
end;
commit;
however, the list of these products is too long. Instead I'd like to do this:
declare
type array_produit_auto is varray(3) of varchar(50);
array array_produit_auto := array_produit_auto('code_product4', 'code_product5', 'code_product6');
begin
update F_PRODUITASS pas
set PAS_NONGES_IDA = 1
WHERE PAS.PAS_CODE_PRODUIT NOT IN array;
end;
commit;
except this doesn't work since apparently I can't mix a query and an array this way.
Any idea of how I could make this work?
If you used a nested table then you could query from the nested table, something like this:
DECLARE
v_exclude_list t_array_produit_auto :=
t_array_produit_auto('code_product4', 'code_product5', 'code_product6');
BEGIN
UPDATE F_PRODUITASS pas
SET PAS_NONGES_IDA = 1
WHERE PAS.PAS_CODE_PRODUIT NOT IN ( SELECT *
FROM TABLE(v_exclude_list) )
;
END;
/
Also, you meant varchar2, right?
Update regarding the Opaque error: The type declaration would need to be an object type (create with the CREATE OR REPLACE TYPE syntax rather than a local plsql type as in the DDL below.
CREATE TABLE F_PRODUITASS(PAS_NONGES_IDA number, PAS_CODE_PRODUIT VARCHAR2(50));
INSERT INTO F_PRODUITASS VALUES(3, 'code_product3');
INSERT INTO F_PRODUITASS VALUES(4, 'code_product4');
CREATE OR REPLACE TYPE t_array_produit_auto IS TABLE OF VARCHAR2(50);
If you did not wish to create your own object type, you could use pre-existing varchar2 or number types such as sys.odcivarchar2list as described here:
Anonymous TABLE or VARRAY type in Oracle

How do I query table type in oracle package

i want to use sql to query an object like following code.
PACKAGE:
PACKAGE DRAWING AS
TYPE AWARD_NUMBER_ROW IS RECORD (
A_NUMBER VARCHAR2 (10),
A_TYPE char (1)
);
TYPE AWARD_ROW IS RECORD (
A_NUMBER VARCHAR2 (10),
A_NAME VARCHAR2 (50)
);
TYPE AWARD_NUMBER_TABLE IS TABLE OF AWARD_NUMBER_ROW INDEX BY PLS_INTEGER;
TYPE AWARD_TABLE IS TABLE OF AWARD_ROW INDEX BY PLS_INTEGER;
AWARD AWARD_TABLE;
AWARD_T AWARD_TABLE;
PROCEDURE DRAWING (AWARD_NUMBER IN AWARD_NUMBER_TABLE);
END DRAWING;
BODY:
create or replace
PACKAGE BODY DRAWING AS
PROCEDURE DRAWING (AWARD_NUMBER IN AWARD_NUMBER_TABLE) AS
BEGIN
EXECUTE IMMEDIATE
'SELECT * FROM AWARD_INF'
BULK COLLECT INTO AWARD_T;
/*
error is from here. AWARD_T does not exist or is marked for delete
*/
SELECT T.* bulk collect into AWARD FROM TABLE(AWARD_T ) T WHERE T.A_NAME = '123456789' ;
END DRAWING;
END INVOICE_DRAWING
here is exception message.
ORA-21700: object does not exist or is marked for delete
"object does not exist or is marked for delete"
*Cause: User attempted to perform an inappropriate operation to
an object that is non-existent or marked for delete.
Operations such as pinning, deleting and updating cannot be
applied to an object that is non-existent or marked for delete.
*Action: User needs to re-initialize the reference to reference an
existent object or the user needs to unmark the object.
how do i fix it??

Populate Text Fields on APEX Form using Array

I am using a barcode scanner to scan in barcodes (that consist of the order^location - I use the ^ as a separator) which i then need to separate and put the two values into two text fields. The idea is to scan the barcode into a third text field and then its separated using a process after save is pressed - These are then saved into separate table columns. I have the below which separates the text but I am now trying to get the values held in the array into the text fields on the APEX form.
I have the below code which works in SQL developer with the following lines however when i changed them to try put the value into a text field it fails. I wondered whether i have it correct or maybe incorrect syntax?
dbms_output.put_line(v_array(1)); -- This works in SQL Developer
:P1_ORDER := dbms_output.put_line(v_array(1)); -- Fails in SQL Developer & APEX
I get the following when i attempt to run the below in SQL developer. Please can someone help me pass the values in my array to the text fields on my APEX Form. Thanks.
ORA-06550: line 17, column 13:
PLS-00222: no function with name 'PUT_LINE' exists in this scope
ORA-06550: line 17, column 5:
PL/SQL: Statement ignored
declare
v_array apex_application_global.vc_arr2;
P1_ORDER number;
P1_LOCATION number;
begin
-- Convert delimited string to array
v_array := apex_util.string_to_table(:P1_JOB_NUMBER,'^');
--dbms_output.put_line(v_array(1));
--dbms_output.put_line(v_array(2));
:P1_ORDER := dbms_output.put_line(v_array(1));
:P1_LOCATION := dbms_output.put_line(v_array(2));
end;
See put_line is not a function ,its a procedure in dbms_output package .
You can't assign dbms_output.put_line to any variable .
Try this
declare
v_array apex_application_global.vc_arr2;
P1_ORDER number;
P1_LOCATION number;
begin
-- Convert delimited string to array
v_array := apex_util.string_to_table(:P1_JOB_NUMBER,'^');
--dbms_output.put_line(v_array(1));
--dbms_output.put_line(v_array(2));
P1_ORDER := v_array(1);
P1_LOCATION := v_array(2);
end;

Resources