PL/SQL Associative Arrays Plus.
Hello, in the next version of ODP.NET support for PL/SQL Associative Arrays of Records ?
Roberto.
It's not a direct example of calling a SP that takes a VARRAY of OBJECTs, but it should get you headed down the right path:
http://www.oracle.com/technology/obe/hol08/dotnet/udt/udt_otn.htm
However, for performance reasons you should certainly consider using Associative Arrays even if this means slicing up your RECORDs into multiple arrays of each one containing a field of the RECORD. You can do a performance comparison of this technique vs using VARRAYS with your particular data to see if this is required.
Similar Messages
-
PL/SQL Associative Array as INPUT Parameter
Hi,
Just wondering if anyone out there has a good example of how to get VB.NET (using ODP.NET 9.2.0.4) to pass an Associative Array as an Input parameter to a stored procedure (not for bulk binds)? Specifically, I'm looking for an example of how a VB Strong Typed Collection would be passed through the PLSQLAssociativeArray Collection Type.
I've managed to get a test to work by passing a 1-D String Array through the ODP.NET layer to the PL/SQL AssociativeArray parameter. But I've had zero success trying to get the Collection from VB through ODP.NET.
Thanks in advance for any help.
Todd.For example, if I wanted to return a list of customer ids and names into A PLSQL Associative Array, how would I do it. I know how to return a list of customer ids into a PLSQL associative aray using the code below but I have to specify the maximum number of elements and the maximum size of each of the elements. Is there any way around this?
Dim prmOutCustomerIdList As New OracleParameter
With prmOutCustomerIdList
.ParameterName = "oCustomerIdList"
.CollectionType = OracleCollectionType.PLSQLAssociativeArray
.OracleDbType = OracleDbType.Varchar2
.Direction = ParameterDirection.Output
.Size = 5
.ArrayBindSize = New Integer(4) {10, 10, 10, 10, 10}
End With -
Would PL/SQL Associative Arrays solve my problem
Hi guys,
I'm new to PL/SQL development really, although i have some limited knowledge that i've relied on for the last couple of years to get by. Anyway, i'll try my best to describe my problem and how i'd like to solution it ...........
I have a table of information that holds a column for decscriptive names of payments and another column holding a difference value, for example :
employee_number | payment_name | difference
00001 | salary | 200.20
00001 | shift | 20.21
00002 | salary | 10.01
00002 | shift | 5.02
00003 | salary | 15.02
00003 | shift | 4.00I'd like to manipulate the way this data is presented, via DBMS_OUTPUT in a summary fashion counting the number of differences between ranges, for example :
payment_name | 0.00 to 10.00 | 10.01 to 100.00 | 100.01 to 99999.99
salary | | 2 | 1
shift | 2 | 1 |I thought it might be possible to use an approach in PL/SQL to mimic this table structure and populate it via a cursor looping through my initial recordset and posting the total count in the associated columns as required. Once the cursor had finished populating the PL/SQL table / array etc i could base my DBMS_OUTPUT on this data.
Or am i completely barking up the wrong tree, would there be a better, more efficient way to solution the problem. I've been reading up on PL/SQL Collections http://docs.oracle.com/cd/B10501_01/appdev.920/a96624/05_colls.htm#19661 but can't really determine is this is a) the correct approach or b) should i try using an associative array, nested table or varray?
Thanks in advance guys, just need a pointer in the right direction.It sounds like you can just pivot the data
SELECT payment_name,
SUM( CASE WHEN difference BETWEEN 0 and 10 THEN 1 ELSE 0 END ) "0.00 to 10.00",
SUM( CASE WHEN difference BETWEEN 10.01 and 100 THEN 1 ELSE 0 END ) "10.01 to 100.00",
SUM( CASE WHEN difference BETWEEN 100.01 and 99999.99 THEN 1 ELSE 0 END ) "100.01 to 99999.99"
FROM table_name
GROUP BY payment_nameYou can then do whatever you want with the data this query returns.
Justin -
Associative Arrays, Indexes vs. Full Table Scans
Hello,
I just started using ODP.Net to connect my .Net Web Service to our Oracle Database. The reason why I switched to ODP.Net is support for arrays. If I wanted to pass in arrays to the procedure I had to pass it in through a varchar2 in a CSV formatted string.
ex. "123,456,789"
So now I'm using ODP.net, passing in PL/SQL Associative Arrays then converting those arrays to nested tables to use within queries.
ex.
OPEN OUT_CURSOR FOR
SELECT COLUMN1, COLUMN2
WHERE COLUMN_ID IN (SELECT ID FROM TABLE(CAST(ASSOC_ARR_TO_NESTED(IN_ASSOC_ARR) AS NESTED_TBL_TYPE)))
It uses the array successfully however what it doesn't do is use the index on the table. Running the same query without arrays uses the index.
My colleague who works more on the Oracle side has posted this issue in the database general section (link below). I'm posting here because it does seem that it is tied to ODP.Net.
performance - index not used when call from service
Has anyone ever experienced this before?You have to use a cardinality hint to force Oracle to use the index:
/*+ cardinality(tab 10) */See How to use OracleParameter whith the IN Operator of select statement -
REF CURSOR to Associative Array
I have a procedure that builds up a collection (associative array / index-by table). Is there any way to hand the collection over to ODP.NET without putting the contents into a temporary table? REF CURSOR seems to fit, but I cannot find the syntax to OPEN a REF CURSOR for the collection.
I am trying to turn the GetResourceGroup() a_Resources parameter into a ref cursor in the example below (which, as I understand it, would also hold the collection in memory until the cursor is closed).
Alternatively, is there a direct method? I.e. is it possible to get the collection directly into a DataTable or similar?
Any advice gratefully received,
Peter
TYPE RsrcRow IS RECORD
ResourceId Resource.ResourceId%TYPE,
ResourceName Resource.ResourceName%TYPE
TYPE Resources IS TABLE OF RsrcRow INDEX BY VARCHAR2(80);
PROCEDURE GetResourceGroup(
a_ResourceType IN VARCHAR2,
a_Resources OUT Resources
IS
l_LocalCollection Resources;
BEGIN
GetResourcesByType(a_ResourceType, l_LocalCollection);
-- Return resource set (need to port this to ODP.NET).
a_Resources := l_LocalCollection;
RETURN;
END GetResourceGroup;odp.net does not have collection support right now.
PL/SQL Associative Array should be available in next release (see other forum threads)
1. Support for Varchar2 indexes is unlikely (since OCI does not provide such functionality). Which means you can only return an C style "array" like structure at best.
2. Your 'GetResourceGroup' need to return REF CURSOR (or other primitive type like VARCHAR2), until Associative Array become available.
FB -
How do u create a datatable from PLSQL Associative Arrays returned from SP
Using C# 4.0 ODP.NET 11g, vs2010 on Windows XP.
Have a procedure that takes two input values and returns 35 PL\SQL Associative Arrays (pl/sql tables). I am currently able to call the proc and have it returned the values. i end up with 35 arrays each 35 elements in length.
I want to create a datatable from them but am at a lost on how to do so.
This what i have
Oracle.DataAccess.Client.OracleCommand oCommand = new Oracle.DataAccess.Client.OracleCommand();
oCommand.CommandText = ProcName;
oCommand.CommandType = CommandType.StoredProcedure;
//Input Parameters
OracleParameter param1 = oCommand.Parameters.Add("p_orderid",OracleDbType.Int32);
param1.Direction = ParameterDirection.Input;
param1.Value = OrderID;
OracleParameter param2 = oCommand.Parameters.Add("p_testinstanceid", OracleDbType.Int32);
param2.Direction = ParameterDirection.Input;
param2.Value = TestInstanceID;
//Output Parameters
OracleParameter param3 = oCommand.Parameters.Add("program_id", OracleDbType.Int32);
param3.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
param3.Direction = ParameterDirection.Output;
param3.Size = 50;
OracleParameter param4 = oCommand.Parameters.Add("normyear", OracleDbType.Varchar2);
param4.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
param4.Direction = ParameterDirection.Output;
param4.Size = 50;
param4.ArrayBindSize = new int[50];
// set the bind size value for each element
for (int i = 0; i < 50; i++)
param4.ArrayBindSize[i] = 10;
...33 more output parameters all PLSQLAssociativeArray type
oCommand.ExecuteNonQuery();
OracleDataAdapter da = new OracleDataAdapter(oCommand);
//Fill the DataTable
da.Fill(dt);
The datatable is empty. What am i doing wrong? Or this there a better way to get the output values to end up in a datatable. Note that when i examine the parameters in oCommand i see that they all the the right out values.I have multiple where conditions which needs the same subqueryThat is where the Subquery Factoring Clause comes in handy, because then
»Oracle Database optimizes the query by treating the query name as either an inline view or as a temporary table«
with temp as (
subquery
select 1
from table1
where col1 in (select * from temp)
and col2 in (select * from temp)
and col3 in (select * from temp) -
Returning collection-associative array from pl-sql procedure
CREATE OR REPLACE procedure test_ganesh( p_deptno IN number,gana out PARTIES_RESULT)
is
query varchar2(200);
PARTY_ID varchar2(200);
PARTY_CODE varchar2(200);
PARTY_NAME varchar2(200);
PARTY_SEQ VARCHAR2(200);
counter number;
TYPE PARTIES IS TABLE OF varchar2(2000) index by binary_integer;
txn_parties PARTIES;
type PARTIES_RESULT IS TABLE OF PARTIES index by binary_integer;
total_result PARTIES_RESULT;
TYPE EmpTyp IS REF CURSOR;
p_du EmpTyp;
p_cursor EmpTyp;
global_counter number;
begin
global_counter:=1;
counter:=1;
open p_cursor FOR
select A.ref_no
from ot_lc_txn_details A
where rownum <12;
LOOP
FETCH p_cursor INTO query;
EXIT WHEN p_cursor%NOTFOUND;
counter:=1;
open p_du FOR
select party_id,party_code,seq_no,party_name from ot_txn_party where ref_no=query;
LOOP
FETCH p_du INTO PARTY_ID,PARTY_CODE,PARTY_SEQ,PARTY_NAME;
EXIT WHEN p_du%NOTFOUND;
txn_parties(counter):=PARTY_ID || '&&&' || PARTY_CODE || '&&&'||PARTY_SEQ || '&&&' || PARTY_NAME;
counter:=counter+1;
END LOOP;
CLOSE p_du;
total_result(global_counter):=txn_parties;
global_counter:=global_counter+1;
END LOOP;
CLOSE p_cursor;
--open gana FOR SELECT * FROM table(cast(total_result as PARTIES_RESULT)) ;
end;
The error comes at line one, PLS-00905- object PARTIES_RESULT is invalid.
i have used the create type thing to create this type.
if i remove the out parameter it works, no compilation error.
Questions i) How to return the associative array as out parameter?
ii)Am i doing aynthing qrong here?
iii) Can i open a ref cursor to this associative array and then return that ref_cursor?
Please anyone reply back, Thanks in advance
Message was edited by:
user649602As an example:
SQL> create type PARTIES is table of varchar2(2000);
2 /
Type created.
SQL> create or replace procedure proc1(p_deptno number,gana out parties) as
2 begin
3 select ename
4 bulk collect into gana
5 from emp
6 where deptno = p_deptno;
7 end;
8 /
Procedure created. -
Error in the pl/sql block using associative arrays
Hi
I tried the following block of code using associative arrays.
DECLARE
TYPE NumTab IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
CURSOR c1 IS SELECT empno FROM emp;
empnos NumTab;
rows NATURAL := 10;
BEGIN
OPEN c1;
FOR i in empnos.first..empnos.last LOOP
/* The following statement fetches 10 rows (or less). */
FETCH c1 BULK COLLECT INTO empnos LIMIT rows;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE ( empnos.next(i));
END LOOP;
CLOSE c1;
END;and the error is
DECLARE
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at line 8could you please let me know where i'm wrong
and please guide me where we use these associative arrays.
ThanksSomething like this. Do minor modification in your code.
DECLARE
TYPE NumTab IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
CURSOR c1 IS SELECT empno FROM emp;
empnos NumTab;
rows NATURAL := 5;
BEGIN
OPEN c1;
LOOP
/* The following statement fetches 5 rows (or less). */
FETCH c1 BULK COLLECT INTO empnos LIMIT rows;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE ( empnos.count);
END LOOP;
CLOSE c1;
END;
/ -
How to use Associative Array in sql query?
Hello,
I have a problem on using Associative Array variable on query; and my query is similar to the one below;
TYPE OTHERGENERICS IS TABLE OF NUMBER(10) INDEX BY BINARY_INTEGER;
othersGenerics OTHERGENERICS;
CURSOR cursor_othersGenerics IS
select master.GENERICCODEID
from ASMTRG_ARTICLEMASTER master
join ASMTRG_ARTICLEMAP map on MAP.ARTICLECODEID = MASTER.ID
group by MASTER.GENERICCODEID
minus
select FGG.GENERICCODEID
from asmtrg_icfocusgroup fg
join asmtrg_icfocusgrpchannel fgc on FGC.GROUPID = FG.ID and fgc.isactive=1
join asmtrg_icfocusgengroup fgg on FGG.GROUPID = FG.ID and FGg.ISACTIVE=1
where fgc.channelid=1 and fg.isactive = 1
group by FGG.GENERICCODEID;
BEGIN
OPEN cursor_othersGenerics;
FETCH cursor_othersGenerics BULK COLLECT INTO othersGenerics;
CLOSE cursor_othersGenerics;
SELECT icfrd.*,
CASE
WHEN EXISTS(select ta.genericcodeid from <???XXX???> ta where ta.genericcodeid = icfgrp.genericcodeid) THEN -1
ELSE icfrd.icfgroupid
END CLASSIFICATION
FROM ASMTRGVIW_ICFOCUSREPORTDATA icfrd
LEFT JOIN ASMTRG_ICFOCUSGROUP icfgrp on icfrd.ICFGROUPID = icfgrp.ID
WHERE (channelId IS NULL OR icfrd.CHANNELID = channelId)
AND (asmCodeId IS NULL OR icfrd.ASMCODEID = asmCodeId)
AND (yearId IS NULL OR icfrd.YEARID = yearId)
AND (monthId IS NULL OR icfrd.MONTHID = monthId)
END;
By the way this is a part of my function.
The "othersGenerics" is my associative array variable and <???XXX???> is the place where I need to use my "othersGenerics" array to check. So far I've tried
"select ta.genericcodeid from table(cast(otherGenerics as OTHERGENERICS)) ta where ta.genericcodeid = icfgrp.genericcodeid",
"select ta.genericcodeid from table(otherGenerics) ta where ta.genericcodeid = icfgrp.genericcodeid",
"select ta.genericcodeid from otherGenerics ta where ta.genericcodeid = icfgrp.genericcodeid"
and these are not working.
What is your suggestions?Your type will have to be created as an independent object in your schema. So CREATE TYPE cannot be in your function declaration, it has to be outside it. (And then the line inside your declaration that defines the type will have to be removed.)
But now I can see that you use this array as a kind of "temporary lookup table" - you populate the array and then use it for lookup in your select statement. An alternative way of doing this could be like this completely without arrays:
with othergenerics as (
select master.GENERICCODEID
from ASMTRG_ARTICLEMASTER master
join ASMTRG_ARTICLEMAP map on MAP.ARTICLECODEID = MASTER.ID
group by MASTER.GENERICCODEID
minus
select FGG.GENERICCODEID
from asmtrg_icfocusgroup fg
join asmtrg_icfocusgrpchannel fgc on FGC.GROUPID = FG.ID and fgc.isactive=1
join asmtrg_icfocusgengroup fgg on FGG.GROUPID = FG.ID and FGg.ISACTIVE=1
where fgc.channelid=1 and fg.isactive = 1
group by FGG.GENERICCODEID
SELECT icfrd.*,
CASE
WHEN EXISTS(select ta.genericcodeid from othergenerics ta where ta.genericcodeid = icfgrp.genericcodeid) THEN -1
ELSE icfrd.icfgroupid
END CLASSIFICATION
FROM ASMTRGVIW_ICFOCUSREPORTDATA icfrd
LEFT JOIN ASMTRG_ICFOCUSGROUP icfgrp on icfrd.ICFGROUPID = icfgrp.ID
WHERE (channelId IS NULL OR icfrd.CHANNELID = channelId)
AND (asmCodeId IS NULL OR icfrd.ASMCODEID = asmCodeId)
AND (yearId IS NULL OR icfrd.YEARID = yearId)
AND (monthId IS NULL OR icfrd.MONTHID = monthId)
...The with clause (subquery factoring) you can think of as a kind of temp table called othergenerics created "on-the-fly".
The optimizer may decide to actually create a temp table for you and use in the lookup, or it may decide to rewrite the query into suitable joins or nested loops or hashing - whatever the optimizer decides will be the optimal way of doing things :-)
So unless you use your array other places in your function, I would recommend dropping the array completely, skip populating an array, and instead use a with clause for your temporary lookup. -
How to Print all values stored in an Associative array
DB version:10gR2
There can be multiple results(multiple rows) for the below query. So, i'll have to declare the variables v_sid_serial, v_orauser, v_objectname,v_objecttype as associative arrays.
SELECT l.session_id||','||v.serial# sid_serial, l.ORACLE_USERNAME,o.object_name,o.object_type,
into v_sid_serial, v_orauser, v_objectname,v_objecttype
FROM dba_objects o, v$locked_object l, v$session v
WHERE o.object_id = l.object_id
and l.SESSION_ID=v.sid;But I want to store the results from the above query in flat file. I want the result set to look like
SID_SERIAL ORA_USER OBJECT_NAME
742,32914 SCOTT EMP
873,49832 HR EMPLOYEES
893,9437 mytestschema emp_dtls
. .How can i print the values in Associative arrays in the above manner so that i can spool the result set to a flat file?
Edited by: user10373231 on Sep 29, 2008 5:19 AMuser10373231 wrote:
is there any way to print all values stored in an Associative arrayPrint to where?
You could use DBMS_OUTPUT to get the output on the screen within SQL*Plus.
You could also output (pipe) the data from PL/SQL using a pipelined function that you select from SQL. An example of a pipelined function...
SQL> CREATE OR REPLACE TYPE myrec AS OBJECT
2 ( col1 VARCHAR2(10),
3 col2 VARCHAR2(10)
4 )
5 /
Type created.
SQL>
SQL> CREATE OR REPLACE TYPE myrectable AS TABLE OF myrec
2 /
Type created.
SQL>
SQL> CREATE OR REPLACE FUNCTION pipedata(p_str IN VARCHAR2) RETURN myrectable PIPELINED IS
2 v_str VARCHAR2(4000) := REPLACE(REPLACE(p_str, '('),')');
3 v_obj myrec := myrec(NULL,NULL);
4 BEGIN
5 LOOP
6 EXIT WHEN v_str IS NULL;
7 v_obj.col1 := SUBSTR(v_str,1,INSTR(v_str,',')-1);
8 v_str := SUBSTR(v_str,INSTR(v_str,',')+1);
9 IF INSTR(v_str,',')>0 THEN
10 v_obj.col2 := SUBSTR(v_str,1,INSTR(v_str,',')-1);
11 v_str := SUBSTR(v_str,INSTR(v_str,',')+1);
12 ELSE
13 v_obj.col2 := v_str;
14 v_str := NULL;
15 END IF;
16 PIPE ROW (v_obj);
17 END LOOP;
18 RETURN;
19 END;
20 /
Function created.
SQL>
SQL> create table mytab (col1 varchar2(10), col2 varchar2(10));
Table created.
SQL>
SQL> insert into mytab (col1, col2) select col1, col2 from table(pipedata('(1,2),(2,3),(4,5)'));
3 rows created.
SQL>
SQL> select * from mytab;
COL1 COL2
1 2
2 3
4 5... which you can easily adapt to output whatever data you want e.g. you could loop through your associative array and pipe out the values within it. -
Parsing XMLType into an associative array
I'm try to build a procedure that can take an XMLType as a parameter. What I would like to do be able to extract both the node names and the string values from each tag of the XML and put them into basically a key --> value associative array.
Ex:
<envelope>
<node1>value1</node1>
<node2>value2</node2>
</envelope>
Would be put into an array structured like: array['node1'] = 'value1', array['node2'] = 'value2', etc.
I'm not entirely sure how I go about looping through the XMLType and extracting each node name and its value. I'm not worried about repeating tag names.. I know that will not be an issue in any of the XMLTypes that I'm using.
Would anyone be able to offer any suggestions? If not how to go about doing exactly that, then at least some insight as to how I can loop through and extract nodes and/or values without specifying the specific XPaths?
Thanks in advance!Hi Roger,
This is a good description of your process. Just add your Oracle DB Version somewhere. Want you want is a method to map your XML to a relationship design (some special variant of object-relational-modelling).
I still see two choices:
The programmatic approach (as you described):
Have multiple procedures where you input an XML. Each procedure is reflecting a different part of the transformation process. So it depends from the Message which procedure you will call.
Example
SQL*Plus: Release 9.2.0.2.0 - Production on Thu Aug 14 17:53:25 2008
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.8.0 - 64bit Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production
SQL> create table testtab (username varchar2(100));
Table created.
/* the following insert part should be in some packaged procedure, */
/* this just don't work on my 9i version, but should in 10g */
SQL> insert into testtab (username)
2 select substr(extractvalue(column_value,'*/text()'),1,100)
3 from table(xmlsequence(extract( xmltype('<envelope>'||
4 '<username>Roger</username>'||
5 '<username>Sven</username>'||
6 '</envelope>'),'envelope/username')));
2 rows created.
SQL> select * from testtab;
USERNAME
Roger
Sven
SQL> The declarative approach:
Insert the XML into a SchemaBased Table. The XML Schema will provide the mapping to your relational tables automagically. Problem here is the writing, handling and evolving of the XML Schema (Sub schemas are allowed too). -
Associative array related problem
Hi All,
When I am trying to use assotiative array in a select statement I recieve the following error:
ORA-06550: line 9, column 22:
PLS-00201: identifier 'COL1' must be declared
ORA-06550: line 9, column 22:
PLS-00201: identifier 'COL1' must be declared
ORA-06550: line 9, column 10:
PL/SQL: ORA-00904: : invalid identifier
ORA-06550: line 9, column 3:
PL/SQL: SQL Statement ignored
Here is the example
--create table MyTable (col1 varchar2(255), col2 varchar2(255))
declare
type m_ttMyTable
is table of MyTable%rowtype index by MyTable.col1%type;
m_tMyTable m_ttMyTable;
m_sCol2 varchar2(255);
begin
select m_tMyTable (col1).col2 /* works with ocntant: select m_tMyTable */('col1').col2
into m_sCol2
from MyTable
where rownum = 1;
end;
--drop table MyTableAny ideas how to workaround this?
ThanksThe only collection types SQL can query are ones defined in SQL using CREATE TYPE. That excludes associative arrays, as they are PL/SQL-only constructs. I'd recommend a nested table collection.
Some more suggestions:
www.williamrobertson.net/documents/collection-types.html -
Associative Array our only option?
Hello,
I'm having a problem accepting associative arrays as the only option I have for getting data from a stored procedure. I have a good reason for not wanting to use ref cursors as I am using the stored procedure to manipulate data which I in turn would like to pass back to VB through the stored procedure and would rather not have to insert he data into a table just to re-select it for a ref cursor.
My main concern is that with associative arrays I am expected to define the number of return results before I even generate the data. Also from what I can see I am required to set the data length for each and every item in said array one at a time. All this overhead seems like more work than what I would have to do to utilizer a reference cursor. Is there a right way to do this? I would really like to do the most straight forward way I can without the extra processing.Hi,
Here's a blog post of mine that illustrates using pipelined functions and PL/SQL to return results:
http://oradim.blogspot.com/2007/10/odpnet-tip-using-pipelined-functions.html
Not sure if that will be helpful in your case, but perhaps it might be a place to start anyway.
- Mark -
I am using a couple associative arrays in my code and comparing the data in one, and if it is an asterisk, I change it to use the data in the other. Here is the meat of my code. I am running into an error at the bolded line saying I have too many values, which I don't understand because the code is the exact same as the block of code right before it where I populate the first array. FYI, the table it is pulling from only has one row. The error is listed below the code.
Code
DECLARE
TYPE refresh_file_t IS TABLE OF test.loading_dock%ROWTYPE ;
refresh_data refresh_file_t ;
prospect_data refresh_file_t ;
TYPE CV_TYPE IS REF CURSOR ;
c_id CV_TYPE ;
v_id NUMBER(10) ;
v_phone VARCHAR2(10) ;
v_project VARCHAR2(10) ;
BEGIN
OPEN c_id FOR
'SELECT id
FROM test.loading_dock
WHERE rownum = 1' ;
LOOP
FETCH c_id INTO v_id ;
EXIT WHEN c_id%NOTFOUND ;
SELECT * BULK COLLECT
INTO refresh_data
FROM test.loading_dock
WHERE id = v_id ;
SELECT * BULK COLLECT
INTO prospect_data
FROM test.prospects
WHERE id_number = v_id ;
IF refresh_data(1).home_phone = '*' THEN
v_phone := prospect_data(1).phone ;
ELSE
v_phone := refresh_data(1).home_phone ;
END IF ;
DBMS_OUTPUT.PUT_LINE(v_phone) ;
END LOOP ;
CLOSE c_id ;
END ;
Error
ORA-06550: line 29, column 13:
PL/SQL: ORA-00913: too many values
ORA-06550: line 27, column 13:
PL/SQL: SQL Statement ignored
ORA-06550: line 34, column 46:
PLS-00302: component 'PHONE' must be declared
ORA-06550: line 34, column 13:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"Collection prospect_data is of type refresh_file_t, which is a table of records of test.loading_dock%TYPE. Most likely tables test.loading_dock and test.prospects have different structure - test.prospects has fewer columns. So when you try to fetch from test.prospects into prospect_data you get the error Try replacing
prospect_data refresh_file_t ;with
TYPE prospect_data_t IS TABLE OF test.prospects%ROWTYPE ;
prospect_data prospect_data_t ;SY. -
Associative Array vs Table Scan
Still new to PL/SQL, but very keen to learn. I wondered if somebody could advise me whether I should use a collection (such as an associative array) instead of repeating a table scan within a loop for the example below. I need to read from an input table of experiment data and if the EXPERIMENT_ID does not already exist in my EXPERIMENTS table, then add it. Here is the code I have so far. My instinct is that it my code is inefficient. Would it be more efficient to scan the EXPERIMENTS table only once and store the list of IDs in a collection, then scan the collection within the loop?
-- Create any new Experiment IDs if needed
open CurExperiments;
loop
-- Fetch the explicit cursor
fetch CurExperiments
into vExpId, dExpDate;
exit when CurExperiments%notfound;
-- Check to see if already exists
select count(id)
into iCheckExpExists
from experiments
where id = vExpId;
if iCheckExpExists = 0 then
-- Experiment ID is not already in table so add a row
insert into experiments
(id, experiment_date)
values(vExpId, dExpDate);
end if;
end loop;Except that rownum is assigned after the result set
is computed, so the whole table will have to be
scanned.really?
SQL> explain plan for select * from i;
Explained.
SQL> select * from table( dbms_xplan.display );
PLAN_TABLE_OUTPUT
Plan hash value: 1766854993
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 910K| 4443K| 630 (3)| 00:00:08 |
| 1 | TABLE ACCESS FULL| I | 910K| 4443K| 630 (3)| 00:00:08 |
8 rows selected.
SQL> explain plan for select * from i where rownum=1;
Explained.
SQL> select * from table( dbms_xplan.display );
PLAN_TABLE_OUTPUT
Plan hash value: 2766403234
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 5 | 2 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | TABLE ACCESS FULL| I | 1 | 5 | 2 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - filter(ROWNUM=1)
14 rows selected.
Maybe you are looking for
-
Super BOM doesn't generate while run MRP from Sales Order
Hi all, I am trying to make a Super BOM where i have a material x as finished product, and i have 2 material as component for that finish product ( A and B ) i already create characteristic and assign it to the class 300, i also have created the conf
-
[SOLVED] Arch not showing up in grub after ArchBang install
I have a triple booting machine with Windows7, Arch, and ArchBang. Windows 7's system partition is where I have the bootloader installed. I recently installed Archbang and now my other Arch is not showing up in grub. I tried updating the grub menu
-
Strange noise appears when printing
I am running into some issues when trying to print a post card I designed for a client. I created the card in photoshop cs5 with a resolution of 300. After creating it as a psd I exported it as a pdf and then printed it through acroabt x on a xerox 7
-
Weird and freaky. And no, i wasn't eating the last time i used it. I was testing my new headphone then though...
-
How to convert Mpeg 2 to usable format for imovie
I have been trying for months, and am completely frustrated. I have a 2x2.8 Ghz Quad Core Tower running 10.6.8. I have all three imovies installed - Imovie HD, imovie 7.1 and imovie 9. All have the most recent updates. I had trouble importing severa