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.

Similar Messages

  • Associative array comparison and INSERT upon IF condition

    Hi Guys,
    I have written this pl sql code to identify non existing sellers and insert their sales channel information into the dimension table (dimensional table update).
    Somehow,......nothing is inserted and this script runs for 12 hours+ without any result. the sql autotrace shows no result and the explain plan (button on sql developer throws upon clicking "missing keyword". I have no
    information what is going on/wrong. Does anyone spot an error?
    UNDEFINE DimSales;
    UNDEFINE FactTable;
    DEFINE DimSales = 'testsales';
    DEFINE FactTable = 'testfact';
    DECLARE
    v_SellerNo VarChar(9);
    v_error_code T_ERRORS.v_error_code%TYPE;
    v_error_message T_ERRORS.v_error_message%TYPE;
    TYPE assoc_array_str_type1 IS TABLE OF VARCHAR2(32) INDEX BY PLS_INTEGER;
         v1 assoc_array_str_type1;
    TYPE assoc_array_str_type2 IS TABLE OF VARCHAR2(32) INDEX BY PLS_INTEGER;
         v2 assoc_array_str_type2;
    BEGIN
    --Collect all distinct SellerNo into associative array (hash table)
    select distinct SellerNo bulk collect into v1 from &FactTable;
    select distinct seller_id bulk collect into v2 from &DimSales;
    v_SellerNo := v1.first;
    loop
    exit when v1 is null;
    --1 Check if v_SellerNo already exists in DIM_Sales (if NOT/FALSE, its a new seller and we can insert all records for that seller
    if (v2.exists(v_SellerNo)=false) THEN
    INSERT INTO &DimSales (K_Sales,REG,BVL,DS, VS,RS,GS,VK)
    (SELECT DISTINCT trim(leading '0' from RS||GS) ,REG BVL,DS,VS,RS,GS,VK from &FactTable where SellerNo =v_SellerNo);
    --ELSE
    end if;
    v_SellerNo := v1.next(v_SellerNo);
    end loop;
    EXCEPTION
    WHEN OTHERS THEN
    ROLLBACK;
    --v_error_code := SQLCODE
    --v_error_message := SQLERRM
    --INSERT INTO t_errors VALUES ( v_error_code, v_error_message);
    END;
    ---------------------------------------------------------------

    Distinct clause requires a sort. Sorts can be very expensive.
    Bulk collects that are not constrained in fetch size, can potentially fetch millions of rows - requiring that data to be wholly read into server memory. I have seen how this can degrade performance so badly that the kernel reboots the server.
    Using PL/SQL loops to process and insert/update/delete data is often problematic due to its row-by-row approach - also called slow-by-slow approach. It is far more scalable letting SQL do the "loop" processing, by using joins, sub-selects and so on.
    Where the conditional processing is too complex for SQL to handle, then PL/SQL is obviously an alternative to use. Ideally one should process data sets as oppose to rows in PL//SQL. Reduce context switching by using bulk fetches and bulk binds.
    But PL/SQL cannot execute in parallel as the SQL it fires off can. If after all the optimisation, the PL/SQL process still needs to hit a million rows to process, it will be slow irrespective of how optimal that PL/SQL approach and design - simply because of the number of rows and the processing overheads per row.
    In that case, the PL/SQL code itself need to be parallelised. There are a number of ways to approach this problem - the typical one is to create unique and distinct ranges of rows to process, spawn multiple P/SQL processes, and provide each with a unique range of rows to process. In parallel.
    So you need to look close at what you are trying to achieve, what the workloads are, and how to effectively decrease the workloads and increase the processing time of a workload.
    For example - finding distinct column values. You can pay for that workload when wanting that distinct list. And each time afterward repeat that workload when wanting that distinct list. Or you can pay for that workload up-front with the DML that creates/updates those values - and use (for example) a materialised view to maintain a ready to use distinct list of values.
    Same workload in essence - but paying once for it and up-front as oppose to each time you execute your code that needs to dynamically build that distinct list.
    Kent Crotty did tests and showed stunning performance improvements with bulk collect and forall, up to 30x faster:Bulk processing is not a magical silver bullet. It is a tool. And when correctly use, the tool does exactly what it was designed to do.
    The problem is using a hammer to drive in screws - instead of a screwdriver. There's nothing "stunning" about using a screwdriver. It is all about using the correct tool.
    If the goal of the swap daemon is to free up "idle" chunks of memory, and try to use that memory for things like file cache instead, what does that have to do with bulk processing?The swap daemon reads virtual memory pages from swap space into memory, and writes virtual pages from memory to swap space.
    What does it have to do with bulk processing? A bulk fetch reads data from the SGA (buffer cache) into the PGA (private process memory space). The larget the fetch, the more memory is required. If for example 50% of server memory is required for a bulk collection that is 2GB in size, then that will force in-use pages from memory to swap space.. only to be swapped back again as it is needed, thereby forcing other in-use pages to swap. The swap daemon will consume almost all the CPU time swapping hot pages continually in and out of memory.

  • 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

  • Associative array type for each blob column in the table

    i am using the code in given link
    http://www.oracle.com/technology/oramag/oracle/07-jan/o17odp.html
    i chnages that code like this
    CREATE TABLE JOBS
    JOB_ID VARCHAR2(10 BYTE),
    JOB_TITLE VARCHAR2(35 BYTE),
    MIN_SALARY NUMBER(6),
    MAX_SALARY NUMBER(6),
    JOBPIC BLOB
    CREATE OR REPLACE PACKAGE associative_array
    AS
    -- define an associative array type for each column in the jobs table
    TYPE t_job_id IS TABLE OF jobs.job_id%TYPE
    INDEX BY PLS_INTEGER;
    TYPE t_job_title IS TABLE OF jobs.job_title%TYPE
    INDEX BY PLS_INTEGER;
    TYPE t_min_salary IS TABLE OF jobs.min_salary%TYPE
    INDEX BY PLS_INTEGER;
    TYPE t_max_salary IS TABLE OF jobs.max_salary%TYPE
    INDEX BY PLS_INTEGER;
    TYPE t_jobpic IS TABLE OF jobs.jobpic%TYPE
    INDEX BY PLS_INTEGER;
    -- define the procedure that will perform the array insert
    PROCEDURE array_insert (
    p_job_id IN t_job_id,
    p_job_title IN t_job_title,
    p_min_salary IN t_min_salary,
    p_max_salary IN t_max_salary,
    p_jobpic IN t_jobpic
    END associative_array;
    CREATE OR REPLACE package body SHC_OLD.associative_array as
    -- implement the procedure that will perform the array insert
    procedure array_insert (p_job_id in t_job_id,
    p_job_title in t_job_title,
    p_min_salary in t_min_salary,
    p_max_salary in t_max_salary,
    P_JOBPIC IN T_JOBPIC
    ) is
    begin
    forall i in p_job_id.first..p_job_id.last
    insert into jobs (job_id,
    job_title,
    min_salary,
    max_salary,
    JOBPIC
    values (p_job_id(i),
    p_job_title(i),
    p_min_salary(i),
    p_max_salary(i),
    P_JOBPIC(i)
    end array_insert;
    end associative_array;
    this procedure is called from .net. from .net sending blob is posiible or not.if yes how

    Ok, that won't work...you need to generate an image tag and provide the contents of the blob column as the src for the image tag.
    If you look at my blog entry -
    http://jes.blogs.shellprompt.net/2007/05/18/apex-delivering-pages-in-3-seconds-or-less/
    and download that Whitepaper that I talk about you will find an example of how to do what you want to do. Note the majority of that whitepaper is discussing other (quite advanced) topics, but there is a small part of it that shows how to display an image stored as a blob in a table.

  • Associative Array to Nested Table: Anything faster?

    (First Post! Some ASP.NET references, but I think this really is a PL/SQL question)
    I work on a team that runs an Oracle instance for data warehousing and reporting along with an ASP.NET based website for display.
    Sometimes, I may want to have many parameters come in and only show records that match those parameters. For example, I may want to show all employees who are Managers or Developers and not show employees who are Accountants or Scientists. Typically, I send a parameter into my PL/SQL stored procedures as an associative array (as declared in my package specification). Once in the procedure, I convert that associative array into another associative array (as a user created SQL type) and then I'm able to use it like a nested table to join on.
    My question is: in your experience, is there any way to get around this type conversion or another faster way?
    For example:
    -- Create the sql type
    CREATE OR REPLACE TYPE DIM.sql_string_table AS TABLE OF VARCHAR2(255);
    --pretend that this works and it's in a package body
    declare
    type string_table is table of varchar2(255) index by binary_integer;
    l_job_types string_table; -- Keep in mind I'd normally be sending this via ASP.NET
    l_job_types_nested sql_string_table := sql_string_table();
    begin
    -- Add some data
    l_job_types(0) := 'Manager';
    l_job_types(1) := 'Developer';
    -- Do the conversion
    for i in l_job_types.first .. l_job_types.last
    loop
    l_job_types_nested.extend;
    l_job_types_nested(l_job_types_nested.count) := l_job_types(i);
    end loop;
    -- get some data out (we're pretending)
    open fake_ref_cursor for
    Select e.*
    from employees e,
    the(select cast(l_job_types_nested as sql_string_table) from dual) jobs_types_wanted
    where e.type = value(jobs_types_wanted);
    end;
    The result would be all employees whose have a type that was input into the l_job_types associatve array.
    See: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:110612348061
    for additional reference

    > I convert that associative array into another associative array (as a user created SQL type)
    Just so we're clear, Oracle use the term 'associative array' to refer to the exclusively PL/SQL sparse collection type ("table of x index by pls_integer" etc) as distinct from the common nested table collection type.
    Also I could be wrong but I think
    SELECT ..
    FROM   the(select cast(l_job_types_nested as sql_string_table) from dual) jobs_types_wantedis generally the same as
    SELECT ..
    FROM   TABLE(l_job_types_nested) jobs_types_wantedthough "SELECT *" and implicitly collection casting don't always mix. The "THE()" syntax is deprecated.

  • Associative array two variable comparison :update table error

    Hi,
    i am using associative array to update the version number of table
    -i declare two associative array to compare the column from two table (temp,main tables)values in loop
    -if id's of both variable(for temp and main table) are equal and column of either of table not matching then it should update the version no of temp table
    -if id's not equal i.e record only exists temp table then update null version number annd increment it by 1
    -following is the structure and procedure --it shows the matching and non matching records but for the update statement it not giving expected output i.e it updates all records irrespective of the condition provided
    -i tried to put condition in update as well as in the  if statement but it updates all record
    ....suggestion and help highly appreciate. thankx in advance !!!
    /*--table structure and data--*/
    CREATE TABLE "TEMP_TABLE"
       ( "ID" NUMBER NOT NULL ENABLE,
      "COL1" VARCHAR2(20 BYTE),
      "COL2" VARCHAR2(20 BYTE),
      "VERSION" NUMBER
       INSERT INTO TEMP_TABLE VALUES (101,'A','B',NULL);
       INSERT INTO TEMP_TABLE VALUES (102,'x','y',NULL);
       INSERT INTO TEMP_TABLE VALUES (103,'r','t',NULL);
       CREATE TABLE "MAIN_TABLE"
       ( "ID" NUMBER NOT NULL ENABLE,
      "COL1" VARCHAR2(20 BYTE),
      "COL2" VARCHAR2(20 BYTE),
      "VERSION" NUMBER
       INSERT INTO MAIN_TABLE VALUES (101,'A','B',1);
    /*------update version procedure----------*/
    DECLARE
      TYPE T_tmp_table IS TABLE OF tmp_table %ROWTYPE INDEX BY PLS_INTEGER;
      TYPE T_main_table IS TABLE OF main_table%ROWTYPE INDEX BY PLS_INTEGER;
      l_tmp_table T_tmp_table;
      l_main_table T_main_table;
      BEGIN
        SELECT * BULK COLLECT INTO l_tmp_table FROM tmp_table;
        SELECT * BULK COLLECT INTO l_main_table FROM main_table;
        FOR i IN 1 .. l_tmp_table.count
        LOOP
          FOR j IN 1 .. l_main_table.count
         LOOP
      if(l_tmp_table(i).ID = l_main_table(j).ID AND l_tmp_table(i).VERSION IS NULL) then     
      ---this first if loop updates temp table version irrespective of l_tmp_table.ID=l_main_table.ID orl_tmp_table. ID<>l_main_table.ID  .it display proper matching and non-matching records.
       dbms_output.put_line('matching ids from tmp and main are :'||l_tmp_table(i).ID||'  '||l_main_table(j).ID);
       UPDATE tmp_table SET VERSION = l_tmp_table(i).version +1;
       --where l_tmp_table(i).ID = l_main_table(j).ID     --
       end if;
      if (l_tmp_table(i).ID <> l_main_table(j).ID) then
       dbms_output.put_line('non matching ids from tmp and main are :'||l_tmp_table(i).ID||'  '||l_main_table(j).ID);
       UPDATE tmp_table SET VERSION = l_tmp_table(i).version +1;
       --where l_tmp_table(i).ID <> l_main_table(j).ID    
        end if;
              END LOOP;
              END LOOP;
        EXCEPTION
        WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('OTHER');
    END;

    Hello user8937641
    I think there is a problem with the logic of your SQL-Code.
    But maybe in this formatted structure you can see where your problem is. -> I can not say it because I do not know what is the requirement.
    I hope it helps...
    /*------update version procedure----------*/
    DECLARE
      TYPE T_tmp_table IS TABLE OF tmp_table %ROWTYPE INDEX BY PLS_INTEGER;
      TYPE T_main_table IS TABLE OF main_table%ROWTYPE INDEX BY PLS_INTEGER;
      l_tmp_table T_tmp_table;
      l_main_table T_main_table;
      BEGIN
        SELECT * BULK COLLECT INTO l_tmp_table FROM tmp_table;
        SELECT * BULK COLLECT INTO l_main_table FROM main_table;
        FOR i IN 1 .. l_tmp_table.count
        LOOP
          FOR j IN 1 .. l_main_table.count
          LOOP
            IF     l_tmp_table(i).ID = l_main_table(j).ID
               AND l_tmp_table(i).VERSION IS NULL
             THEN
                 ---this first if loop updates temp table version irrespective of l_tmp_table.ID=l_main_table.ID orl_tmp_table. ID<>l_main_table.ID  .it display proper matching and non-matching records.
                 dbms_output.put_line('matching ids from tmp and main are :'||l_tmp_table(i).ID||'  '||l_main_table(j).ID);
                 UPDATE tmp_table
                    SET version = l_tmp_table(i).version +1;
                  WHERE id = l_tmp_table(i).ID
            END IF;
            IF l_tmp_table(i).ID <> l_main_table(j).ID
             THEN
               dbms_output.put_line('non matching ids from tmp and main are :'||l_tmp_table(i).ID||'  '||l_main_table(j).ID);
               -- Maybe you do not need this update:
               UPDATE tmp_table
                  SET version = l_tmp_table(i).version +1;
                WHERE id =  l_tmp_table(i).ID
            END IF;
            COMMIT;
           END LOOP;
        END LOOP;
      EXCEPTION WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('Error at Executing the PLSQL-Block - ' || SQLERRM);
    END;

  • Inserting a associative array into a table

    Hi,
    I am working on a process where I want to store the temporary results in an associative array. At the end of the process I plan to write the contents of the array into a table that has the same structure. (the array is defined as a %rowtype of the table)
    Is it possible to execute ONE sql statement that transfers the array into the table? I am on 10g (10.2.0.4.0)
    Here's what I have now:
    declare
      type t_emp is table of emp%rowtype index by pls_integer;
      v_emp t_emp;
    begin
      -- a process that fills v_emp with lots of data
      for i in v_emp.first .. v_emp.last
      loop
        insert into emp values v_emp(i);
      end loop;  
    end;But it would be better if the loop could be replaced by sql one statement that inserts all of v_emp into emp. Is that possible?
    Thanks!
    PS: I'm not sure whether it's a good idea to use this approach... building a table in memory and inserting it into the database at the end of the process. Maybe it's better to insert every record directly into the table... but in any case I'm curious to see if it is possible in theory :)
    Edited: Added version info

    True, SQL cannot access the PL/SQL type.
    So you can not do something like this:
    insert into emp
    select * from table(v_emp)That is not possible.
    But FORALL is possible:
    FORALL i in v_emp.first .. v_emp.last
        insert into emp values v_emp(i);FORALL makes just one "round trip" to SQL bulk binding the entire contents of the array.
    It is much more efficient than the normal FOR loop, though it is mostly a PL/SQL optimization - even the FORALL actually inserts the rows "one at the time", it just hands the entire array to the SQL engine in one go.
    If the logic has to be done procedurally, FORALL is efficient.
    If the logic can be changed so arrays can be avoided completely and everything done in a single "insert into ... select ..." statement, that is the most efficient.

  • Object tables/associative arrays are using lots of memory what is alternate

    I'm using mostly object tables/associative arrays in my package and it is using lots of server memorey so i want to use a different technicque to save momorey .
    like using create global temporary table or nested Table Store as or creating table run time at the start and droping it in the end .
    do have any suggestion for this ?
    for this package i'm retriving data from different table into object tables and do calculation in memorey before i send data to front end for reporting using reference cursor .
    give me your suggetion or if you know any example code for this type of process using different technique please let us know .
    thank you very much
    regards
    shailen Patel

    You can create a global temporary table like this:
    CREATE GLOBAL TEMPORARY TABLE AR_TRIAL_RCPT(
      LOC_ACCT_ID NUMBER(12),  
      ACCT_ID NUMBER(12),  
      CURRENCY_ID NUMBER(12),  
      AMT NUMBER(13,   4),  
      AMT_PRIMARY NUMBER(13,   4)
    [ON COMMIT PRESERVE ROWS]
    ;If you want the table truncated on COMMITs leave out the part in brackets other wise leave off the brackets and the table won't be truncated until your session terminates or you explicitly truncate the table.
    You can also define indexes, primary keys, foreign keys, check constraints, etc. on your temporary table if need be to improve processing.
    Now when it comes to inserting into your newly minted global temporary table, you should be able to use one of insert statements from the following anonymous PL/SQL block:
    CREATE GLOBAL TEMPORARY TABLE AR_TRIAL_RCPT(
      LOC_ACCT_ID NUMBER(12),  
      ACCT_ID NUMBER(12),  
      CURRENCY_ID NUMBER(12),  
      AMT NUMBER(13,   4),  
      AMT_PRIMARY NUMBER(13,   4)
    --[ON COMMIT PRESERVE ROWS]
    CREATE GLOBAL succeeded.
    declare
    l_open_receipt_select_1 varchar2(4000) :=
        'select 1, 1, 1, 12.05, 12.05 from dual';
    l_open_receipt_select_2 varchar2(4000) :=
        'select 2, 2, 1, 17.05, 17.05 from dual';
    l_open_receipt_select_3 varchar2(4000) :=
        'select 3 loc_acct_id,
      1 currency_id,
      27.05 amt,
      3 acct_id,
      27.05 amt_primary
      from dual';
    l_open_receipt_select_4 varchar2(4000) :=
        'select 4 loc_acct_id,
      1 currency_id,
      24.35 amt,
      4 acct_id,
      24.35 amt_primary
      from dual';
    l_ins_stmt varchar2(4000);
    begin
      -- If the column order is known ahead of time and is consistent
      -- You can use this form:
      l_ins_stmt :=
        'insert into ar_trial_rcpt (
      loc_acct_id, acct_id, currency_id, amt, amt_primary
      ) '||l_open_receipt_select_1||
      ' union all '||
      l_open_receipt_select_2;
      execute immediate l_ins_stmt;
      -- If the column order is NOT known ahead of time or is INconsistent
      -- You can use this form:
      l_ins_stmt :=
        'insert into ar_trial_rcpt (
      loc_acct_id, acct_id, currency_id, amt, amt_primary
      select loc_acct_id
      , acct_id
      , currency_id
      , amt
      , amt_primary
      from ('||l_open_receipt_select_3||')
      union all
      select loc_acct_id
      , acct_id
      , currency_id
      , amt
      , amt_primary
      from ('||l_open_receipt_select_4||')';
      execute immediate l_ins_stmt;
    end;
    anonymous block completed
    select * from ar_trial_rcpt
    LOC_ACCT_ID ACCT_ID  CURRENCY_ID AMT    AMT_PRIMARY
    1           1        1           12.05  12.05      
    2           2        1           17.05  17.05      
    3           3        1           27.05  27.05      
    4           4        1           24.35  24.35      
    4 rows selected

  • Multiplication table using Associative arrays

    DB Version:10.2.0.1.0
    Below is a code for multiplication table of 14 upto 100. How can i store these values in an Associative array and display each element of the array so that it produces the same output as the code below.
    Declare
    --TYPE v_number_type IS TABLE OF number INDEX BY PLS_INTEGER;
    v_number     number:= 14;
    v_multiplied_by     number:= 1;
    v_result     number;
    begin
         for i in 1..100
         loop
              v_result:=     v_number * v_multiplied_by;
              dbms_output.put_line(v_number||' multiplied by '||v_multiplied_by||' = '||v_result);
              v_multiplied_by:=v_multiplied_by + 1;
         end loop;
    end;
    /Result would be
    14 multiplied by 1 = 14
    14 multiplied by 2 = 28
    14 multiplied by 3 = 42
    14 multiplied by 4 = 56
    14 multiplied by 5 = 70
    Edited by: user609308 on Mar 12, 2009 3:09 AM
    Including the tags                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

    Why bother using PL/SQL when you can do it easily in a SQL statement?
    select '14 multiplied by '||to_char(level)||' = '||14*level result
    from   dual
    connect by level <= 100
    order by level;
    RESULT                                                                         
    14 multiplied by 1 = 14                                                        
    14 multiplied by 2 = 28                                                        
    14 multiplied by 3 = 42                                                        
    14 multiplied by 4 = 56                                                        
    14 multiplied by 5 = 70                                                        
    14 multiplied by 6 = 84                                                        
    14 multiplied by 7 = 98    
    ....

  • SELECT Command on Associative Array

    Guys,
    I have a question on associative arrays in ORACLE.
    I m working on one assignment where I am not allowed to create any object into the database e.g. Create temporary tables, use of cursors etc.
    For data manipulation i used associative array, but at the end i want to show that result in pl/SQL developer.
    I know that I can't use select command on associative arrays.
    Any alternative/solution for it?
    Also is there any way that i can write the contents of associative array to a .csv file?

    user13478417 wrote:
    I m working on one assignment where I am not allowed to create any object into the database e.g. Create temporary tables, use of cursors etc.Then cease to use Oracle - immediately. As you are violating your assignment constraints.
    ALL SQL and anonymous PL/SQL code blocks you send to Oracle are parsed as cursors. And as you are not allowed to use cursors, it will be impossible to use Oracle as cursors is exactly what Oracle creates... and creates a lot of. For every single SQL statement. And every single anonymous PL./SQL block.
    For data manipulation i used associative array, Why? Arrays is a poor choice in Oracle as a data structure most times as it is inferior in almost every single way to using a SQL table structure instead.
    Pumping data into an array? That already severely limits scalability as the array requires expensive dedicated server (PGA) memory. It does not use the more scalable shared server (SGA) memory.
    Manipulating data in an array? That requires a "+full structure scan+" each time as it does not have the indexing and partitioning features of a SQL table.
    Running a SQL select on an array? That is using a cursor. That also means copying the entire array structure, as bind variable, from the PL/SQL engine to the SQL engine. An excellent way to waste memory resources and slow down performance... but hey you can still shout "+Look Ma, no --brains-- hands, I'm not using any SQL tables as dictated by my assignment!+".... +<sigh>+
    Any alternative/solution for it?You mean besides using Oracle correctly ?
    You could reload the shotgun and shoot yourself in the other foot too. That should distract you for from the pain in the first foot.

  • 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?
    Thanks

    The 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

  • Associative Array error

    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 Question

    Hi All,
    I've searched through this forum trying to find information I'm needing on associative arrays with a varchar2 index without luck. What I'm looking for is a way to get the index or "key" values of the array without knowing what they are. Meaning, I wouldn't have to know the index value when designing the array but would be able to utilize them values at runtime. For those familiar with Java it would be like calling the keySet() method from a Map object.
    So, if I have an array of TYPE COLUMN_ARRAY IS TABLE OF VARCHAR2(4000) INDEX BY VARCHAR2(100) is there any way to dynamically get the index values without knowing what they are?
    Any help is appreciated.
    Thanks

    Thanks for the response.
    I am aware of using FIRST and NEXT for iterating the array but can I extract the index value of the current element into a variable when I don't know what the index value is at runtime ?
    Thanks

Maybe you are looking for