Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Arun.

Asked: May 19, 2017 - 4:49 pm UTC

Last updated: July 06, 2020 - 2:30 pm UTC

Version: Oracle 11g

Viewed 1000+ times

You Asked

Hi,

In the below example for Associative Array Indexed by String,
set serveroutput on;
DECLARE
-- Associative array indexed by string:
TYPE population IS TABLE OF NUMBER -- Associative array type
INDEX BY VARCHAR2(64); -- indexed by string
city_population population; -- Associative array variable
i VARCHAR2(64); -- Scalar variable
BEGIN
-- Add elements (key-value pairs) to associative array:
city_population('Smallville') := 2000;
city_population('Midland') := 750000;
city_population('Megalopolis') := 1000000;
-- Change value associated with key 'Smallville':
city_population('Smallville') := 2001;
-- Print associative array:
i := city_population.FIRST; -- Get first element of array
WHILE i IS NOT NULL LOOP
DBMS_Output.PUT_LINE
('Population of ' || i || ' is ' || city_population(i));
i := city_population.NEXT(i); -- Get next element of array
END LOOP;
END;
/

OP:
PL/SQL procedure successfully completed.

Population of Megalopolis is 1000000
Population of Midland is 750000
Population of Smallville is 2001

/
What ever the values I change for city_population the FIRST element of this array remain the same to 
'Population of Megalopolis is 1000000'

I dono why.

My problem here is about this line "city_population.FIRST;" here the FIRST keyword refers too.. it refers too highest value associated with elements or ?? the reason is every time I run this block with different combinations I get Megalopolis as output. 

Sorry for the confusion. Please do let me know if any clarifications again!

Thanks

and Connor said...

What do you mean "What ever the values I change for city_population"

You've given us your code - that's great. But you need to give us an example of where you are having your problem as well.

=================

"FIRST" is first in index order.

So "Megalopolis" sorts lower than "Midland" which is lower than "Smallville"

If I created a row with index "Aardvark" it will come out first.

The indexes are not the order in which you add data, they are the order in terms of sorting of the varchar values.

Rating

  (4 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Constructor in Associative array

Rajasekhar, June 30, 2020 - 1:52 pm UTC

Hello Tom,
Can you please help in understanding the values assignment to associative array using constructor?

create table test2(a_id number(10), a_name varchar2(30), a_class varchar2(30), a_rollno number(10));
insert into test2 values(1,'test','first',10);
insert into test2 values(2,'test2','first2',10);

declare
b varchar2(30):='test';
cn number:=0;
type t_test is table of test2%rowtype index by pls_integer;
var_to_assign t_test:=t_test();
begin
for i in (select a_id,a_name,a_rollno from test2)
loop
cn:=cn+1;
b:=b||cn;
var_to_assign(cn).a_id:=i.a_id;
var_to_assign(cn).a_name:=i.a_name;
var_to_assign(cn).a_class:=b;
var_to_assign(cn).a_rollno:=i.a_rollno;
--var_to_assign(cn):=var_to_assign(i.a_id,i.a_name,d,i.a_rollno); how to assign values to associate array using constructor

end loop;
for j in 1..var_to_assign.count
loop
dbms_output.put_line('the value is'||var_to_assign(j).a_class);
end loop;
exception
when others then
raise_application_error(-20000,'The erorr is '||SQLERRM);
end;
/
Chris Saxon
July 02, 2020 - 4:07 pm UTC

You can't use %rowtype with record constructors. And the constructor is the name of the type, not the variable ;)

Something like this should do the job:

declare
  b varchar2(30):='test';
  cn number:=0;
  
  type t_test is record (
    a_id number(10), a_name varchar2(30), 
    a_class varchar2(30), a_rollno number(10)
  );
  
  type t_test_arr is table of t_test index by pls_integer;
  var_to_assign t_test_arr;
begin
  for i in (select a_id,a_name,a_rollno from test2)
  loop
    cn:=cn+1;
    b:=b||cn;
      var_to_assign(cn) := 
        t_test ( 
          a_id => i.a_id, a_name => i.a_name,
          a_class => b, a_rollno => i.a_rollno 
        );

  end loop;
  
  for j in 1..var_to_assign.count
  loop
    dbms_output.put_line('the value is'||var_to_assign(j).a_class);
  end loop;

end;
/ 
the value istest1
the value istest12

PL/SQL

aashi ahmad, July 03, 2020 - 7:13 am UTC

tp know more about PL/SQL Collections and other pl/sql related issues than go to our website
https://www.dba-career.com/

Record Constructors

rajasekhar, July 04, 2020 - 2:54 pm UTC

Hello Tom,

Thank you so much for your answers.

can you explain more about records constructors and how declaring records type with all column names explicitly will be useful instead of defining record with %rowtype?
Connor McDonald
July 06, 2020 - 5:40 am UTC

We didn't say it would be better....it is just for different use cases.

If you record maps to a row in a table, or a row from a cursor, then by all means....use %rowtype

But if your record is a customised object that needs to store specific data that is not mapped to a table, then you can define it explicitly.

Both have uses where appropriate.

Record constructor

Rajasekhar, July 06, 2020 - 11:37 am UTC

Hello Chris,
Why are you defining the record type with all table columns(4 columns) explicitly for values assignment?
And when we can use %rowtype for values assignmnet?



create table test2(a_id number(10), a_name varchar2(30), a_class varchar2(30), a_rollno number(10));
Something like this should do the job:

declare
b varchar2(30):='test';
cn number:=0;

type t_test is record (
a_id number(10), a_name varchar2(30),
a_class varchar2(30), a_rollno number(10)
);

type t_test_arr is table of t_test index by pls_integer;
var_to_assign t_test_arr;
begin
for i in (select a_id,a_name,a_rollno from test2)
loop
cn:=cn+1;
b:=b||cn;
var_to_assign(cn) :=
t_test (
a_id => i.a_id, a_name => i.a_name,
a_class => b, a_rollno => i.a_rollno
);

end loop;

for j in 1..var_to_assign.count
loop
dbms_output.put_line('the value is'||var_to_assign(j).a_class);
end loop;

end;
/

Chris Saxon
July 06, 2020 - 2:30 pm UTC

I thought the question was about qualified expressions - array and record constructors added in 18c.

This doesn't work with %rowtype variables:

https://livesql.oracle.com/apex/livesql/file/content_F9WWD55FZB0LPDH74V0NVBSHU.html

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library