Fix PLS-00642: local collection types not allowed in SQL statements

Hi Experts, Please help me resolve the error below.


Errors for PROCEDURE SARS_OF_INT_NRTV_MOD_01:

LINE/COL ERROR
-------- -----------------------------------------------------------------
120/16   PLS-00642: local collection types not allowed in SQL statements
120/36   PLS-00642: local collection types not allowed in SQL statements
120/53   PLS-00642: local collection types not allowed in SQL statements
124/56   PLS-00642: local collection types not allowed in SQL statements
SQL>

--##################################################################

Here is the code:


CREATE OR REPLACE PROCEDURE Sars_Of_Int_NRTV_Mod_01
 IS
  c_row_processed    CONSTANT number(4) := 1000;
  c_row_processed_2  CONSTANT number(4) := 1000;
  v_my_loops        pls_integer;
  v_my_loops_2      pls_integer;
  v_row_count       pls_integer;
  v_Srch_Obj_Nm    Varchar2(2000) := 'NRTV: ';
  v_Error_Code     Number;
  v_Srch_Trm       Varchar2(2000);
  v_Srch_Date      Date;
  v_Srch_Term_Id   Integer;
  v2_Srch_Term_Id  Integer;
  v2_Srch_From     Date;
  v_Concept_Grp    Varchar2(500);
  v_Srch_Typ       Varchar2(128);
  v_Rslvd_Grp_Nm   Varchar2 (250);
  v_Error_Message  Varchar2(100);
  Type sSrch_Trm IS TABLE OF     Varchar2 (2000);
  Type sDoc_Id IS TABLE OF       Number (12);
  Type sSrch_Term_Id is TABLE OF Integer;
  Type sSrch_Date IS TABLE OF    Date;
  Type sFilg_Dt IS Table OF      Date;
  Type sLST_UPD_TS IS Table OF   Date;
  Type sLGL_RAW_PRTY_FULL_NM is TABLE OF Varchar2 (1000);
  Type sConcept_Grp IS TABLE OF  Varchar2 (500);
  Type sSrch_Typ IS TABLE OF     Varchar2(128);
  Type sRslvd_Grp_Nm IS TABLE OF Varchar2 (250);
  Type sSrch_Term_Id_2 IS TABLE OF  Integer;
  Type sSrch_From_2 IS TABLE OF Date;
  Type slst_upd_ts_2 is TABLE OF Date;
  l_sSrch_Trm              sSrch_Trm;
  l_sFilg_Dt               sFilg_Dt;
  l_sDOC_Id                sDoc_Id;
  l_sSrch_Date             sSrch_Date;
  l_sSrch_Term_Id          sSrch_Term_Id;
  l_sLST_UPD_TS            sLST_UPD_TS;
  l_sLGL_RAW_PRTY_FULL_NM  sLGL_RAW_PRTY_FULL_NM;
  l_sConcept_Grp           sConcept_Grp;
  l_sSrch_Typ              sSrch_Typ;
  l_sRslvd_Grp_Nm          sRslvd_Grp_Nm;
  l2_sSrch_Term_Id_2       sSrch_Term_Id_2;
  l2_sSrch_From_2          sSrch_From_2;
  l2_slst_upd_ts_2         slst_upd_ts_2;
  e_no_records_found       Exception;
 
-- Populate Source Table WI_SO_NRTV
   BEGIN
      Execute Immediate ('Truncate Table WI_SO_NRTV');  
    Insert Into WI_SO_NRTV (SRCH_TRM, SRCH_DATE, SRCH_TERM_ID, CONCEPT_GRP, SRCH_TYP, RSLVD_GRP_NM)
      Select WI_SRCH_TERM.SRCH_STRNG_1, WI_SRCH_TERM.SRCH_FROM_INIT, WI_SRCH_TERM.SRCH_TERM_ID, WI_SRCH_TERM.CONCEPT_GRP, WI_SRCH_TERM.SRCH_TYP, WI_SRCH_TERM.RSLVD_GRP_NM
      From WI_SRCH_TERM
      Where WI_SRCH_TERM.SRCH_TYP = 'NRTV';
      Commit;            
-- Empty Destination Table WI_SO_NRTV_OUT  
     Execute Immediate ('Truncate Table WI_SO_NRTV_OUT');
     v_my_loops := 0;
   -- If the source table (WI_SO_NRTV) has no records, Raise exeception,
   -- Enter "No Record Found" in WI_SO_NO_REC  
        Select count (*) into v_row_count FROM WI_SO_NRTV ;
        If     v_row_count = 0 Then
           RAISE e_no_records_found;
   -- Create a cursor to hold values from table WI_SO_NRTV          
    Else
       DECLARE
         CURSOR c1_cur
    IS
       SELECT A.Srch_Trm, NVL (B.Srch_UPTO, B.SRCH_FROM) Srch_Date, A.Srch_Term_Id, A.Concept_Grp, A.Srch_typ, A.Rslvd_Grp_Nm
       INTO v_Srch_Trm, v_Srch_Date, v_Srch_Term_Id, v_Concept_Grp, v_Srch_typ, v_Rslvd_Grp_Nm
       FROM WI_SO_NRTV A, WI_SO_SRCH_FROM_NRTV B
       WHERE A.Srch_Term_Id = B.Srch_Term_Id;
     BEGIN
        For c1_rec IN c1_cur
    -- Loop through WI_SO_NRTV to find matching records in Tables
    -- AABASE.NRTV, AABASE.DOC And populate table WI_SO_NRTV_OUT
      LOOP
          BEGIN          
       SELECT
          c1_rec.Srch_Trm, N.DOC_ID, D.FILG_DT, D.LST_UPD_TS,
          upper(F.LGL_RAW_PRTY_FULL_NM), c1_rec.Srch_Date, c1_rec.Srch_Term_Id, c1_rec.Concept_Grp, c1_rec.Srch_Typ, c1_rec.Rslvd_Grp_Nm    
          BULK COLLECT INTO  l_sSrch_Trm, l_sDoc_Id, l_sFilg_Dt, l_sLST_UPD_TS, l_sLGL_RAW_PRTY_FULL_NM, l_sSrch_Date, l_sSrch_Term_Id,
          l_sConcept_Grp, l_sSrch_Typ, l_sRslvd_Grp_Nm        
          FROM AABASE.NRTV N,  AABASE.FILG_NSTUTN F, AABASE.DOC D
          WHERE CONTAINS (N.NRTV_TXT, C1_REC.Srch_Trm)>0
          AND N.DOC_ID=F.DOC_ID
          AND N.DOC_ID=D.DOC_ID
          AND D.LST_UPD_TS > C1_REC.Srch_Date;        
          FORALL i IN 1..l_sSrch_Trm.count
          INSERT INTO WI_SO_NRTV_OUT (SRCH_TRM, SRCH_DATE, SRCH_TERM_ID, CONCEPT_GRP, SRCH_TYP, RSLVD_GRP_NM, DOC_ID, FILG_DT, LAST_UPDATE, LGL_RAW_PRTY_FULL_NM, TRIGGER_TXT, RUN_DATE)
          VALUES (l_sSrch_Trm(i), l_sSrch_Date(i), l_sSrch_Term_Id(i), l_sConcept_Grp(i), l_sSrch_Typ(i), l_sRslvd_Grp_Nm(i), l_sDoc_Id(i), l_sFilg_Dt(i), l_sLST_UPD_TS(i), l_sLGL_RAW_PRTY_FULL_NM(i), v_Srch_Obj_Nm||l_sSrch_Trm(i), sysdate);                  
      v_my_loops := v_my_loops +1;      
      If mod(c1_cur%rowcount, c_row_processed) =0 Then
         NULL;
      End If;
     
      EXCEPTION
             When Others then
             v_Error_Code := SQLCODE;
       v_Error_Message := Substr (SQLERRM, 1, 75);
       Insert Into WI_SO_ERRM (Search_Term, code, message, info, Record_Source, Record_Time)
         Values  (c1_rec.SRCH_TRM,v_Error_Code, v_Error_Message, 'Oracle error occured', 'Sars_Of_Int_NRTV', sysdate);        
           Commit;
        End;  
    End Loop;
    Commit;
   End;
  End If;
  -- Update Table WI_SO_SRCH_FROM_NRTV
DECLARE
     CURSOR c2_cur
        IS
       SELECT SRCH_TERM_ID, SRCH_FROM
       INTO v2_Srch_Term_Id, v2_Srch_From
       FROM WI_SO_SRCH_FROM_NRTV;
    BEGIN
        For c2_rec IN c2_cur
      LOOP
        BEGIN
          SELECT c2_rec.SRCH_TERM_ID, c2_rec.SRCH_FROM, Max(E.LST_UPD_TS)
          INTO l2_sSrch_Term_Id_2, l2_sSrch_From_2, l2_slst_upd_ts_2
          FROM WI_SO_SRCH_FROM_NRTV A, WI_SO_NRTV_OUT B, AABASE.DOC E
          WHERE A.SRCH_TERM_ID = B.SRCH_TERM_ID
          AND   B.DOC_ID = E.DOC_ID;
          UPDATE WI_SO_SRCH_FROM_NRTV SET SRCH_UPTO =  l2_slst_upd_ts_2;
        v_my_loops_2 := v_my_loops_2 +1;
             If mod(c2_cur%rowcount, c_row_processed_2) = 0 Then
                NULL;
             End If;
         End;
    End Loop;
        Commit;
    End;

EXCEPTION
    When e_no_records_found Then
        Insert Into WI_SO_NO_REC (out_Put_SARS, Record_Source, Record_Time) VALUES ('Input_Table has no records to process', 'Sars_Of_Int_NRTV',sysdate);
        Commit;
End Sars_Of_Int_NRTV_Mod_01;
/
Kamal AgnihotriAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

slightwv (䄆 Netminder) Commented:
l2_sSrch_Term_Id_2       sSrch_Term_Id_2;
...
SELECT ...
           INTO l2_sSrch_Term_Id_2



l2_sSrch_Term_Id_2 is declared local to the pl/sql code.

When you issue a select statement from inside pl/sql, it executes in the sql engine (outside the local code).  Thus, no access to local variables.

You might try adding 'bulk collect' to the into...

If that doesn't work, you can create the types external to the procedure or rework the code to not select into the type.
0
Kamal AgnihotriAuthor Commented:
Hi slightwv,

Following your suggestion, I modified the code an it compiled. Up execution, the code is producing the desired result upto the line above the code below. At this point I am getting

ORA-06531: Reference to uninitialized collection

Line: 133

Cause: An element or member function of a nested table or varray was referenced (where an initialized collection is needed)
without the collection having been initialized.

Action: Initialize the collection with an appropriate constructor or whole-object assignment.

Another suggestion/pointer for you and the entire code will work. Please. I have uploded the entire code as an attchment. Thanks a lot.

  -- Update Table WI_SO_SRCH_FROM_NRTV
  v_my_loops_2 := 0;
DECLARE
     CURSOR c2_cur
        IS
       SELECT SRCH_TERM_ID, SRCH_FROM
       INTO v2_Srch_Term_Id, v2_Srch_From
       FROM WI_SO_SRCH_FROM_NRTV;
    BEGIN
        For c2_rec IN c2_cur
      LOOP
        BEGIN
          SELECT c2_rec.SRCH_TERM_ID, c2_rec.SRCH_FROM, Max(E.LST_UPD_TS)
          BULK COLLECT INTO l2_sSrch_Term_Id_2, l2_sSrch_From_2, l2_slst_upd_ts_2
          FROM WI_SO_SRCH_FROM_NRTV A, WI_SO_NRTV_OUT B, AABASE.DOC E
          WHERE A.SRCH_TERM_ID = B.SRCH_TERM_ID
          AND   B.DOC_ID = E.DOC_ID;
          FORALL i IN 1.. l2_sSrch_Trm_2.count
          UPDATE WI_SO_SRCH_FROM_NRTV SET SRCH_UPTO =  l2_sSrch_Trm_2(i);
        v_my_loops_2 := v_my_loops_2 +1;
             If mod(c2_cur%rowcount, c_row_processed_2) = 0 Then
                NULL;
             End If;
         End;
    End Loop;
        Commit;
    End;
0
slightwv (䄆 Netminder) Commented:
I don't have your tables or data so I cannot set up a test.

I did create a test loosely based on your code and it runs for me.

--drop table tab1 purge;
create table tab1(col1 char(1));

insert into tab1 values('a');
insert into tab1 values('b');
commit;

DECLARE 
      vjunk char(1);

      CURSOR c2_cur
         IS 
        SELECT col1
        INTO vjunk
        FROM tab1;

   Type v_my_type IS TABLE OF  char(1);
   junk v_my_type;
     BEGIN
         For c2_rec IN c2_cur
       LOOP
       	dbms_output.put_line (c2_rec.col1);

       	select c2_rec.col1 bulk collect into junk from dual;

     End Loop;
End;
/

Open in new window

0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

Kamal AgnihotriAuthor Commented:
Hi Slightwv,

I think we are Very close. I modified the code as you suggested. I am getting error as below. I have annotated  the line wher ethe error is occuring. I think it has to do something with referencing the variable.  

ORA-06531: Reference to uninitialized collection

Line: 144

Cause: An element or member function of a nested table or varray was referenced (where an initialized collection is needed)
without the collection having been initialized.

Action: Initialize the collection with an appropriate constructor or whole-object assignment.


v_my_loops_2 := 0;
DECLARE
  v2_Srch_Term_Id          Integer;
  v2_Srch_From             Date;
     CURSOR c2_cur
        IS
       SELECT SRCH_TERM_ID, SRCH_FROM
       INTO v2_Srch_Term_Id, v2_Srch_From
       FROM WI_SO_SRCH_FROM_NRTV;
  Type sSrch_Trm_2 IS TABLE OF       Varchar2 (2000);
  Type sSrch_Term_Id_2 IS TABLE OF   Integer;
  Type sSrch_From_2 IS TABLE OF      Date;
  Type slst_upd_ts_2 is TABLE OF     Date;
  l2_sSrch_Term_Id_2       sSrch_Term_Id_2;
  l2_sSrch_From_2          sSrch_From_2;
  l2_slst_upd_ts_2         slst_upd_ts_2;
  l2_sSrch_Trm_2           sSrch_Trm_2;  
    BEGIN
        For c2_rec IN c2_cur
      LOOP
        BEGIN
          SELECT c2_rec.SRCH_TERM_ID, c2_rec.SRCH_FROM, Max(E.LST_UPD_TS)
          BULK COLLECT INTO l2_sSrch_Term_Id_2, l2_sSrch_From_2, l2_slst_upd_ts_2
          FROM WI_SO_SRCH_FROM_NRTV A, WI_SO_NRTV_OUT B, AABASE.DOC E
          WHERE A.SRCH_TERM_ID = B.SRCH_TERM_ID
          AND   B.DOC_ID = E.DOC_ID;
          FORALL i IN 1.. l2_sSrch_Trm_2.count   -- (HERE IS WHERE THE COD E IS THROWING THE ERROR)
          UPDATE WI_SO_SRCH_FROM_NRTV SET SRCH_UPTO =  l2_slst_upd_ts_2(i);
        v_my_loops_2 := v_my_loops_2 +1;
             If mod(c2_cur%rowcount, c_row_processed_2) = 0 Then
                NULL;
             End If;
         End;
    End Loop;
        Commit;
    End;
0
slightwv (䄆 Netminder) Commented:
>>FORALL i IN 1.. l2_sSrch_Trm_2.count   -- (HERE IS WHERE THE COD E IS THROWING THE ERROR)

Where do you initialize l2_sSrch_Trm_2?
0
Kamal AgnihotriAuthor Commented:
Hi Slightwv,

Thanks for the quick reply. I am going by the intial and simalr code that worked. In the first cursor c1_cur, I am using the variable l_sSrch_Trm.count which has been declared in the variables declaration section. The variable too was not initialized.

Following the same patern, I have declared  variable  l2_sSrch_Trm_2  and created a Type as follows:

Type sSrch_Trm_2       IS TABLE OF       Varchar2 (2000);
l2_sSrch_Trm_2           sSrch_Trm_2;

And then have created the cursor  c2_rec.

If I have to initialize  l2_sSrch_Trm_2, please tell me where and how do I do that. Thanks a lot.
0
slightwv (䄆 Netminder) Commented:
>>If I have to initialize  l2_sSrch_Trm_2, please tell me where and how do I do that. Thanks a lot.

I cannot tell you how to do it since I don't know your code.

What I can tell you is that to reference l2_sSrch_Trm_2.count in the forall loop, l2_sSrch_Trm_2 must have data in it.

Given the code you posted, I don't see where you 'bulk collect' into it nor do I see where you select anything into it.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Kamal AgnihotriAuthor Commented:
Hi slightwv,

You are 100% correct. After your suggestion, below is the modified code. And it is doing what it is supposed to do.

 BEGIN
        For c2_rec IN c2_cur
      LOOP
        BEGIN
          SELECT c2_rec.SRCH_TERM_ID, c2_rec.SRCH_FROM, Max(E.LST_UPD_TS)
          BULK COLLECT INTO l2_sSrch_Term_Id_2, l2_sSrch_From_2, l2_slst_upd_ts_2
          FROM WI_SO_SRCH_FROM_NRTV A, WI_SO_NRTV_OUT B, AABASE.DOC E
          WHERE A.SRCH_TERM_ID = B.SRCH_TERM_ID
          AND   B.DOC_ID = E.DOC_ID;
          FORALL i IN 1.. l2_sSrch_Term_Id_2.count
          UPDATE WI_SO_SRCH_FROM_NRTV SET SRCH_UPTO = l2_slst_upd_ts_2(i);
        v_my_loops_2 := v_my_loops_2 +1;
             If mod(c2_cur%rowcount, c_row_processed_2) = 0 Then
                NULL;
             End If;
         End;
    End Loop;
        Commit;
    End;

--#############################################

Thanks a lot. You truly are an expert. I will continue to learn from you. One last question, I declared the variables for the 2nd cursor,  c2_cur, right above the cursor. Then I do not have to look for the varibles at the top. Is this a good practice??

Your comments and then I will close the question.
0
slightwv (䄆 Netminder) Commented:
I still wish you would rethink the use of in-memory tables.  I'm still betting you don't need them and native DML might be faster and consume less resources.

>> I declared the variables for the 2nd cursor,  c2_cur, right above the cursor. Then I do not have to look for the varibles at the top. Is this a good practice??


To be honest, I don't know the 'correct' coding practice for this.  I've also been out of school way too long to care about 'theory'.

I tend to declare all mine at the top but this may not work in all cases.

I would say it has more to do with need more than any standards.

Declaring them the way you did has scope issues and may impact execution time.

If you don't need a variable until way down in the code, why declare it at the top and have it hang around
versus
Create the variable when you need it and have it destroyed as soon as you don't.

If it is a char(1), probably makes no difference.  If it is a LOT of LOBs or tables like you have, it might be an issue.
0
Kamal AgnihotriAuthor Commented:
Hi Slightwv,

Please elaborate on your comment.

I still wish you would rethink the use of in-memory tables.  I'm still betting you don't need them and native DML might be faster and consume less resources.

Here are my questions/comments:

-- Which in-memory tables are you refering to

--Please suggest an alternative.

Thanks.

Kamal
0
slightwv (䄆 Netminder) Commented:
>>-- Which in-memory tables are you refering to

All of them.

This is an in-memory table:
Type sSrch_Trm IS TABLE OF     Varchar2 (2000);

These are normally used for data that is constantly reused many times in code where going to the base tables every time causes undo resource usage.  I don't see in your code where you keep reusing the same table over and over.

It looks like you populate the in-memory table once, loop through all the rows then repopulate it with new data.

I see this and automatically think it is the incorrect path.

>>--Please suggest an alternative.

I don't know your requirements.  If you can create a very simplified test case that shows what you need, complete with tables, sample data and expected results, I'll try to come up with an example based on what I think you need.

What I'm not going to do is take your entire set of tables and requirements and complete your entire project for you.

Well, I would if I was looking for a contracting job but I am not.
0
Kamal AgnihotriAuthor Commented:
Hi Slightwv,

My requirements are to have the procedure running as efficiently as possible.

Following your suggestion above, how  would you replace the variables below so as to make the code efficient according to you. Thanks a lot.

  Type sSrch_Trm   IS TABLE OF            Varchar2 (2000);  
  Type sDoc_Id     IS TABLE OF               Number (12);
  Type sSrch_Term_Id IS TABLE OF       Integer;
  Type sSrch_Date IS TABLE OF             Date;

Another question is regarding Bulk collect into. What modification would you suggest to the code below, to put a limit clause for 100 rows to be processed each time. I will open another question, if you wold like.

 v_my_loops_2 := 0;
DECLARE
  v2_Srch_Term_Id          Integer;
  v2_Srch_From             Date;
     CURSOR c2_cur
        IS
       SELECT SRCH_TERM_ID, SRCH_FROM
       INTO v2_Srch_Term_Id, v2_Srch_From
       FROM WI_SO_SRCH_FROM_NRTV;
  Type sSrch_Trm_2 IS TABLE OF       Varchar2 (2000);
  Type sSrch_Term_Id_2 IS TABLE OF   Integer;
  Type sSrch_From_2 IS TABLE OF      Date;
  Type slst_upd_ts_2 is TABLE OF     Date;
  l2_sSrch_Term_Id_2       sSrch_Term_Id_2;
  l2_sSrch_From_2          sSrch_From_2;
  l2_slst_upd_ts_2         slst_upd_ts_2;
  l2_sSrch_Trm_2           sSrch_Trm_2;  
    BEGIN
        For c2_rec IN c2_cur
      LOOP
        BEGIN
          SELECT c2_rec.SRCH_TERM_ID, c2_rec.SRCH_FROM, Max(E.LST_UPD_TS)
          BULK COLLECT INTO l2_sSrch_Term_Id_2, l2_sSrch_From_2, l2_slst_upd_ts_2
          FROM WI_SO_SRCH_FROM_NRTV A, WI_SO_NRTV_OUT B, AABASE.DOC E
          WHERE A.SRCH_TERM_ID = B.SRCH_TERM_ID
          AND   B.DOC_ID = E.DOC_ID;
          FORALL i IN 1.. l2_sSrch_Term_Id_2.count
          UPDATE WI_SO_SRCH_FROM_NRTV SET SRCH_UPTO = l2_slst_upd_ts_2(i);
        v_my_loops_2 := v_my_loops_2 +1;
             If mod(c2_cur%rowcount, c_row_processed_2) = 0 Then
                NULL;
             End If;
         End;
    End Loop;
        Commit;
    End;
0
slightwv (䄆 Netminder) Commented:
>>Following your suggestion above, how  would you replace the variables below so as to make the code efficient according to you. Thanks a lot.

That doesn't help me set up a test case in any way.  To remove the in-memory tables, just use explicit or implicit cursor loops to do the work.  I don't see a need to take the results from a select, store them in memory, loop through the stored values and take some action.

It seems to me it would be better to:
loop through a selects cursor and process the rows as you get them.

To show what I mean as it relates to your code I need a table definition, sample data, your sample code that produces results.  That way I can set up the same tables and data, then rework the code sample to produce the same results.

Remember:  I don't want 500 lines of your code to rewrite.  Just a small sample.

An example cursor loop:
...
for I in (select some_col from some_table) loop
     dbms_output.put_line('Process: ' || i.come_col);
end loop;
...

or a regular cursor that has an open, fetch and close.



>>What modification would you suggest to the code below, to put a limit clause for 100 rows to be processed each time.

The same as the other question you asked about LIMIT.  Just add LIMIT and loop until you are out of rows.
0
slightwv (䄆 Netminder) Commented:
To add:
I know you have search terms stored in one table.  Dummy up a small sample of that.

You have documents stored in another table with a Text index on them.  Dummy up a small sample of that.

Looks like you are storing the results in some other table.  Small sample...

Then I can build the same model and we can both work from the same samples...
0
Kamal AgnihotriAuthor Commented:
I will keep this question open for some time as I have to build the test data.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Oracle Database

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.