Pl/sql cursor and loop

Hello.
I need help creating a cursor and loop that will update a column based on data from another column. I keep getting the following errors. Any suggestions? These identifiers are valid tables in columns in my data base.
SQL> DECLARE
2
3      CURSOR c1 IS
4           SELECT SectionID, Coursename, StudentID, FinalGrade from Registration, Section, Grade WHERE registration.sectionid = grade.sectionid and registrationid.studentid = grade.studentid;
5
6      v_SectionID number(10);
7      v_CourseName varchar(20);
8      v_StudentID number(10);
9      v_FinalGrade varchar2(5);
10
11 BEGIN
12
13      OPEN c1;
14
15      LOOP
16           FETCH c1
17           INTO v_SectionID, v_CourseName, v_StudentID, v_FinalGrade;
18           EXIT WHEN c1%NOTFOUND;
19
20           update grade
21
22           SET FinalGrade = translate(substr(v_CourseName,-1,1),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','AAAAAABBBBBCCCCCDDDDEEEEEE')
23
24           where Grade.StudentID = Registration.StudentID;
25
26      END LOOP;
27 CLOSE c1;
28 END;
29 /
          SELECT SectionID, Coursename, StudentID, FinalGrade from Registration, Section, Grade WHERE registration.sectionid = grade.sectionid and registrationid.studentid = grade.studentid;
ERROR at line 4:
ORA-06550: line 4, column 140:
PL/SQL: ORA-00904: "REGISTRATIONID"."STUDENTID": invalid identifier
ORA-06550: line 4, column 3:
PL/SQL: SQL Statement ignored
ORA-06550: line 24, column 27:
PL/SQL: ORA-00904: "REGISTRATION"."STUDENTID": invalid identifier
ORA-06550: line 20, column 3:
PL/SQL: SQL Statement ignored

863737 wrote:
I am taking a intro course online so I am trying to teach myself this. The most basic rule for designing and writing good Oracle code that will perform and will scale is to use SQL for what it is good at and using PL/SQL for what it is good at. And between the two, SQL is by far superior when it comes to crunching data in the database.
The simple maxim is Maximize SQL. Minimize PL/SQL.
What you want to do with that PL/SQL code can be done using SQL only. And since you are learning SQL and PL/SQL, it is very important that you learn the correct way to do this.
Have a look at Oracle® Database SQL Language Reference guide.
The update syntax supports:
UPDATE <dml_expression_clause>
Where this +<dml_expression_clause>+ is a SELECT statement (aka an in-line view) - that can contain joins.
Simple example. You join tables t1 and t2 to identify the rows in t1 to update. The +<dml_expression_clause>+ will define this join. The actual update part (using the SET clause) will update the relevant rows in t1.
This is also called an updatable view - though the +<dml_expression_clause>+ does not need to use an actual view.
Have a look at AskTom for a discussion on this. Also note that you can also create a view and define an "instead-of" trigger on the view - this particular feature enhances the ability to update DML expressions - but is not a prerequisite.
Note that there can be very significant performance degradation by NOT using an UPDATE on a +<dml_expression_clause>+ and instead coding that manually via PL/SQL.
So do yourself a favour and learn the CORRECT way to resolve the type of UPDATE problem you have.

Similar Messages

  • Report using cursors and loop

    Hi,
    can anybody suggest what kind of report and in what way I have to use if I want to write query using cursors within loops?
    Thanks!
    Karina.

    Hi,
    I found the solution. I just rewrite all cursors within one SQL statement and it works.
    Karina.

  • How to create store procedure using cursor, and looping condition with exce

    Hi,
    I am new in pl/sql development , please help me for follwoing
    1. I have select query by joining few tables which returns lets say 100 records.
    2. I want to insert records into another table(lets say table name is tbl_sale).
    3. If first record is inserted into tbl_sale,and for next record if value is same as first then update into tbl_sale else
    insert new row
    4. I want to achieve this using store procedure.
    Please help me how to do looping,how to use cursor and all other necessary thing to achieve this.

    DECLARE
       b   NUMBER;
    BEGIN
       UPDATE tbl_sale
          SET a = b
        WHERE a = 1;
       IF SQL%ROWCOUNT = 0
       THEN
          INSERT INTO tbl_sale
                      (a
               VALUES (b
       END IF;
    END;note : handle exceptions where ever needed
    Regards,
    friend
    Edited by: most wanted!!!! on Mar 18, 2013 12:06 AM

  • Learning... cursor and loop... suggestions?

    Although I'm looking for non version specific information...  Here is what I'm running on.
    Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
    PL/SQL Release 11.2.0.3.0 - Production
    CORE    11.2.0.3.0    Production
    TNS for Solaris: Version 11.2.0.3.0 - Production
    NLSRTL Version 11.2.0.3.0 - Production
    I'm trying to figure out the whole relationship and execution of inserting data into a table, manipulating the table and anything else via a procedure using a cursor and a loop.
    Sounds simple, but all the examples I find out there all deal with dbms_output..  obviously because it's 'safe'...
    So I'm trying to use context that my mind makes quick sense of.
    I built a simple table with vehicle makes, with the intention of using exercises to add models, trim levels, engines...pretty much all vehicle specifications.
    CREATE TABLE VEH_COMP
      MAKE          VARCHAR2(20 BYTE),
      MODEL         VARCHAR2(50 BYTE),
      TRIM          VARCHAR2(50 BYTE),
      ENGINE        VARCHAR2(50 BYTE),
      TRANSMISSION  VARCHAR2(50 BYTE),
      HORSEPOWER    NUMBER,
      TORQUE        NUMBER
    TABLESPACE USERS
    RESULT_CACHE (MODE DEFAULT)
    PCTUSED    0
    PCTFREE    10
    INITRANS   1
    MAXTRANS   255
    STORAGE    (
                INITIAL          80K
                NEXT             1M
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                PCTINCREASE      0
                BUFFER_POOL      DEFAULT
                FLASH_CACHE      DEFAULT
                CELL_FLASH_CACHE DEFAULT
    LOGGING
    NOCOMPRESS
    NOCACHE
    NOPARALLEL
    MONITORING;
    Next I tried to build a simple sql block to insert a handful of Auto makes into the table...  I know this is ugly, and here is where I'm looking for suggestions for improvement.
    DECLARE
       CURSOR m1
       IS
       SELECT 'Ford' as make FROM DUAL
    UNION ALL
    SELECT 'Chevy' FROM DUAL
    UNION ALL
    SELECT 'Dodge' FROM DUAL
    UNION ALL
    SELECT 'BMW' FROM DUAL
    UNION ALL
    SELECT 'Audi' FROM DUAL
    UNION ALL
    SELECT 'Mercedes' FROM DUAL;
    BEGIN
       FOR v_make IN m1
       LOOP
          dbms_output.put_line(v_make.make);
          insert into veh_comp (make) values (v_make.make);
       END LOOP;
    END;
    Now I'm looking to add models.  Like Ford Mustang, Ford Lightning, Chevy Corvette, Chevy Camaro, Dodge Charger, Dodge Challenger, Dodge Viper, BMW M5, BMW M3, BMW M6...
    Then I need to add engine sizes...  I6, V8
    Then I need to add transmission... M6, M5, A5, A6, A8
    I'm a little confused as how I should execute this part.  Or better yet, I'm sure there is a better way to include it all at once...
    I've been looking on line on how to do this and again...only really finding dbms_output.put_line.  And I did grasp how I could do something along this lines from using a spool file.  But I really want to learn to be more efficient.
    What's the best way to do this?
    Thanks.

    From what I can gather from the code, if I create some example data, you just want a query that does something like...
    SQL> select * from vw_ta;
           LID        SID         C0         C1         C2         C3
             1          1          1          2          3          4
             1          2          1          2          3          4
             1          3          1          2          3          4
             1          4          1          2          3          4
             1          5          1          2          3          4
             1          6          1          2          3          4
             2          1          1          2          3          4
             2          2          1          2          3          4
             2          3          1          2          3          4
             3          1          1          2          3          4
             3          2          1          2          3          4
             3          3          1          2          3          4
             3          4          1          2          3          4
             3          5          1          2          3          4
             3          6          1          2          3          4
             3          7          1          2          3          4
             4          1          1          2          3          4
             5          1          1          2          3          4
             5          2          1          2          3          4
    19 rows selected.
    SQL> ed
    Wrote file afiedt.buf
      1      SELECT LID, SID, Cnt, Limits, dense_rank() over (order by lid) as grp, Iter
      2      FROM (SELECT LID
      3                  ,SID
      4                  ,COUNT(*) OVER (PARTITION BY LID) Cnt
      5                  ,TRUNC(COUNT(*) OVER (PARTITION BY LID)/4)*4 Limits
      6                  ,row_number() over (partition by LID order by SID desc) iter
      7            FROM VW_TA
      8            WHERE C0 > 0 AND C1 > 0 AND C2 > 0 AND C3 > 0
      9            ORDER BY LID, SID DESC
    10           ) a
    11*     WHERE ITER <= LIMITS
    SQL> /
           LID        SID        CNT     LIMITS        GRP       ITER
             1          6          6          4          1          1
             1          5          6          4          1          2
             1          4          6          4          1          3
             1          3          6          4          1          4
             3          7          7          4          2          1
             3          6          7          4          2          2
             3          5          7          4          2          3
             3          4          7          4          2          4
    8 rows selected.
    You already had the iteration part in your query, you just needed the Group number which is achieved using a dense_rank on the result.

  • Why use cursor and for loop?

    Hi All
    So in general why would we use a cursor and a for loop to do update in a stored procedure?
    Why wouldnt we just use a single update statement ?
    is there compelling reason for using a cursor and a for loop: I am reading some code from a co-worker that the business logic for the select (set need to be updated) is complex but the update logic is simple (just set a flag to (0 or 1 or 2 or 3 or 4).
    But eventually the select come down to a key (row_id) so I re-write it using just a single sql statement.
    The size of the main table is about 2.6 to 3million rows
    Any thoughts on that??
    The code below I just do a google for cursor for update example in case for something to play with
    -Thanks for all your input
    create table f (a number, b varchar2(10));
    insert into f values (5,'five');
    insert into f values (6,'six');
    insert into f values (7,'seven');
    insert into f values (8,'eight');
    insert into f values (9,'nine');
    commit;
    create or replace procedure wco as
      cursor c_f is
        select a,b from f where length(b) = 5 for update;
        v_a f.a%type;
        v_b f.b%type;
    begin
      open c_f;
      loop
        fetch c_f into v_a, v_b;
        exit when c_f%notfound;
        update f set a=v_a*v_a where current of c_f;
      end loop;
      close c_f;
    end;
    exec wco;
    select * from f;
    drop table f;
    drop procedure wco;
    Joining multiple tables
    create table numbers_en (
      id_num  number        primary key,
      txt_num varchar2(10)
    insert into numbers_en values (1, 'one'  );
    insert into numbers_en values (2, 'two'  );
    insert into numbers_en values (3, 'three');
    insert into numbers_en values (4, 'four' );
    insert into numbers_en values (5, 'five' );
    insert into numbers_en values (6, 'six'  );
    create table lang (
       id_lang   char(2) primary key,
       txt_lang  varchar2(10)
    insert into lang values ('de', 'german');
    insert into lang values ('fr', 'french');
    insert into lang values ('it', 'italian');
    create table translations (
      id_num    references numbers_en,
      id_lang   references lang,
      txt_trans varchar2(10) not null
    insert into translations values (1, 'de', 'eins'   );
    insert into translations values (1, 'fr', 'un'     );
    insert into translations values (2, 'it', 'duo'    );
    insert into translations values (3, 'de', 'drei'   );
    insert into translations values (3, 'it', 'tre'    );
    insert into translations values (4, 'it', 'quattro');
    insert into translations values (6, 'de', 'sechs'  );
    insert into translations values (6, 'fr', 'six'    );
    declare
      cursor cur is
          select id_num,
                 txt_num,
                 id_lang,
                 txt_lang,
                 txt_trans
            from numbers_en join translations using(id_num)
                       left join lang         using(id_lang)
        for update of translations.txt_trans;
      rec cur%rowtype;
    begin
      for rec in cur loop
        dbms_output.put (
          to_char (rec.id_num         , '999') || ' - ' ||
          rpad    (rec.txt_num        ,   10 ) || ' - ' ||
          rpad(nvl(rec.txt_trans, ' '),   10 ) || ' - ' ||
                   rec.id_lang                 || ' - ' ||
          rpad    (rec.txt_lang       ,   10 )
        if mod(rec.id_num,2) = 0 then
          update translations set txt_trans = upper(txt_trans)
           where current of cur;
           dbms_output.put_line(' updated');
        else
          dbms_output.new_line;
        end if;
      end loop;
    end;
    /Edited by: xwo0owx on Apr 25, 2011 11:23 AM

    Adding my sixpence...
    PL/SQL is not that different from a SQL perspective than any other SQL client language like Java or C# or C/C++. PL/SQL simply integrates the 2 languages a heck of a lot better and far more transparent than the others. But make no mistake in that PL/SQL is also a "client" language from a SQL perspective. The (internal) calls PL/SQL make to the SQL engine, are the same (driver) calls made to the SQL engine when using Java and C and the others.
    So why a cursor and loops in PL/SQL? For the same reason you have cursors and loops in all these other SQL client languages. There are the occasion that you need to pull data from the SQL engine into the local language to perform some very funky and complex processing that is not possible using the SQL language.
    The danger is using client cursor loop processing as the norm - always pulling rows into the client language and crunching it there. This is not very performant. And pretty much impossible to scale. Developers in this case views the SQL language as a mere I/O interface for reading and writing rows. As they would use the standard file I/O read() and write() interface calls.
    Nothing could be further from the truth. SQL is a very advance and sophisticated data processing language. And it will always be faster than having to pull rows to a client language and process them there. However, SQL is not Turing complete. It is not the procedural type language that most other languages we use, are. For that reason there are things that we cannot do in SQL. And that should be the only reason for using the client language, like PL/SQL or the others, to perform row crunching using a client cursor loop.

  • Use of SQL Server and Oracle Simultaneously

    Hello,
    Is it possible to have Oracle and SQL Server used simultaneously? Here, developers will be accessing both databases at the same time, whereas they are some ease of implementations at one Database, which can't be found in another database.
    Regards,

    user650358 wrote:
    I am able to retrieve with simple OUT Parameters from the stored procedure in the application without having to use refcursor. Is this a bad thing in the use of other data types instead of refcursors?
    I was able to have only a varchar and this worked fine.PL/SQL is a formal procedural language with a number of object orientated programming features. Of course functions can return all kinds of data types - even objects and arrays and collections and pointers (called LOB locators).
    All SQL in Oracle are parsed and stored in the server as cursors. The ref cursor data type in PL/SQL is a variable type that contains the handle of a cursor in the server - its "special ability" is passing this PL/SQL variable structure to a client (like Java or .Net) and have the client consume the output of the cursor.
    Ref cursors allow you to move a lot of business logic and validation and processing into PL/SQL - and have PL/SQL do the complex stuff and create the SQL cursor and then simply pass the cursor handle to the client as a ref cursor data type. You can easily maintain this code, introduces changes, tune for performance, without having to touch a single byte of client code.
    But functions are not there simply to pass ref cursor handles to a client. They can do various other stuff and return all kinds of data types and structures.

  • CR+LF Code at the end of each record selected in sql cursor

    i am selecting some data records in a sql cursor and writing it into a file using UTL_FILE.puT in a plsql procedure.
    at the end of select statement if i add ||chr(13||chr(10) iam getting CR+CR+LF code
    if i add only || chr(10) i am getting LF code.
    What i need is only CR+LF code. Kindly help to use any other commands.
    Thanks,
    Shivaji.
    Edited by: Shivaji M on Apr 22, 2010 12:11 AM
    Edited by: Shivaji M on Apr 22, 2010 12:36 AM

    It's in the book!
    "PUT_LINE terminates the line with the platform-specific line terminator character or characters."
    http://download.oracle.com/docs/cd/E11882_01/appdev.112/e10577/u_file.htm#i997640

  • Ref Cursor and For Loop

    The query below will return values in the form of
    bu     seq     eligible
    22     2345     Y
    22     2345     N
    22     1288     N
    22     1458     Y
    22     1458     N
    22     1234     Y
    22     1333     N
    What I am trying to accomplish is to loop through the records returned.
    for each seq if there is a 'N' in the eligible column return no record for that seq
    eg seq 2345 has 'Y' and 'N' thus no record should be returned.
    seq 1234 has only a 'Y' then return the record
    seq 1333 has 'N' so return no record.
    How would I accomplish this with a ref Cursor and pass the values to the front end application.
    Procedure InvalidNOs(io_CURSOR OUT T_CURSOR)
         IS
              v_CURSOR T_CURSOR;
         BEGIN
    OPEN v_CURSOR FOR
    '     select bu, seq, eligible ' ||
    '     from (select bu, seq, po, tunit, tdollar,eligible,max(eligible) over () re ' ||
    '          from (select bu, seq, po, tunit, tdollar,eligible ' ||
    '          from ( ' ||
    '          select bu, seq, po, tunit, tdollar, eligible, sum(qty) qty, sum(price*qty) dollars ' ||
    '               from ' ||
    '               ( select /*+ use_nl(t,h,d,s) */ ' ||
    '               h.business_unit_id bu, h.edi_sequence_id seq, d.edi_det_sequ_id dseq, ' ||
    '                    s.edi_size_sequ_id sseq, h.po_number po, h.total_unit tUnit, h.total_amount tDollar, ' ||
    '                    s.quantity qty, s.unit_price price,' ||
    '               (select (case when count(*) = 0 then ''Y'' else ''N'' end) ' ||
    '          from sewn.NT_edii_po_det_error ' ||
    '          where edi_det_sequ_id = d.edi_det_sequ_id ' ||
    '               ) eligible ' ||
    '     from sewn.nt_edii_purchase_size s, sewn.nt_edii_purchase_det d, ' ||
    '     sewn.nt_edii_purchase_hdr h, sewn.nt_edii_param_temp t ' ||
    '     where h.business_unit_id = t.business_unit_id ' ||
    '     and h.edi_sequence_id = t.edi_sequence_id ' ||
    '     and h.business_unit_id = d.business_unit_id ' ||
    '     and h.edi_sequence_id = d.edi_sequence_id ' ||
    '     and d.business_unit_id = s.business_unit_id ' ||
    '     and d.edi_sequence_id = s.edi_sequence_id ' ||
    '     and d.edi_det_sequ_id = s.edi_det_sequ_id ' ||
    '     ) group by bu, seq, po, tunit, tdollar, eligible ' ||
    '     ) ' ||
    '     group by bu, seq, po, tunit, tdollar, eligible)) ';
              io_CURSOR := v_CURSOR;
    END     InvalidNOs;

    One remark why you should not use the assignment between ref cursor
    variables.
    (I remembered I saw already such thing in your code).
    Technically you can do it but it does not make sense and it can confuse your results.
    In the opposite to usual variables, when your assignment copies value
    from one variable to another, cursor variables are pointers to the memory.
    Because of this when you assign one cursor variable to another you just
    duplicate memory pointers. You don't copy result sets. What you do for
    one pointer is that you do for another and vice versa. They are the same.
    I think the below example is self-explained:
    SQL> /* usual variables */
    SQL> declare
      2   a number;
      3   b number;
      4  begin
      5   a := 1;
      6   b := a;
      7   a := a + 1;
      8   dbms_output.put_line('a = ' || a);
      9   dbms_output.put_line('b = ' || b);
    10  end;
    11  /
    a = 2
    b = 1
    PL/SQL procedure successfully completed.
    SQL> /* cursor variables */
    SQL> declare
      2   a sys_refcursor;
      3   b sys_refcursor;
      4  begin
      5   open a for select empno from emp;
      6   b := a;
      7   close b;
      8 
      9   /* next action is impossible - cursor already closed */
    10   /* a and b are the same ! */
    11   close a;
    12  end;
    13  /
    declare
    ERROR at line 1:
    ORA-01001: invalid cursor
    ORA-06512: at line 11
    SQL> declare
      2   a sys_refcursor;
      3   b sys_refcursor;
      4   vempno emp.empno%type;
      5 
      6  begin
      7   open a for select empno from emp;
      8   b := a;
      9 
    10   /* Fetch first row from a */
    11   fetch a into vempno;
    12   dbms_output.put_line(vempno);
    13 
    14   /* Fetch from b gives us SECOND row, not first -
    15      a and b are the SAME */
    16 
    17   fetch b into vempno;
    18   dbms_output.put_line(vempno);
    19 
    20 
    21  end;
    22  /
    7369
    7499
    PL/SQL procedure successfully completed.Rgds.
    Message was edited by:
    dnikiforov

  • Problem with Latches and Parallelising PL/SQL Cursors

    In 9i i have process that do the following:
    PROCEDURE LoadClients IS
      CURSOR cChanges IS
        SELECT ...
        WHERE MOD(PK,pnTotalJobs>) = pnThisJob To call this I do the following
      nTOTALJOBS CONSTANT := 2;
    BEGIN
      FOR i IN 1..nTOTALJOBS LOOP
        DBMS_JOB.SUBMIT(LoadClient(pnTotalJobs=>nTOTALJOBS, pnThisJob=>i-1));
      END LOOP;
      COMMIT;So by changing the value of the constant - nTOTALJOBS - I can control the number of instances of LoadClient that run. This means I only need one procedure which can be called multiple times, making maintenance simpler than having multiple procedures.
    This process has been running successfully on several procedures of over a year. However recently I have been having trouble with latches in memory. I think these are related to using the variables in the cursor and part of the oracle treating the different queries as being identical. This results in locks in memory and none of the jobs running. In most cases I'm setting nTOTALJOBS to 2. I'm looking into the further with my DBAs.
    My questions are:
    1. Has anyone come across this sort of problem before?
    2. If so is there something I can do in my code or DB parameters to alleviate or test this?
    Notes.
    1. The process uses row by row processing in PL/SQL This done to get row by row error handling. I'm not going to change this in the short-term
    2. The SQL does a call over a database link, I don't know if this has any effect.
    3. This method does have a proven performance benefit
    4. The code snippets above are just illustrative, I'm not asking for syntax corrections.
    Thank you for taking the time to read through this.

    I would first investigate the "problem with latches" to be sure that it has anything to do with these jobs that you are submitting.
    Your concern seems to be "because I am submitting multiple copies of the same PLSQL procedure to run concurrently, am I running into latching issues ?".
    Take a step back and look at
    a. MultiUser OLTP environments : At any time you can have more than a few users running the same SQL queries submitted through Forms / Client Frontends.
    b. ERP Report Extractions (eg in Oracle EBusiness Suite or Peoplesoft) : At any time (say during the daily batch runs ?) you can have multiple copies of the same report (with different bind variables for different business_units / countries etc) running concurrently and extracting reports.
    The question would be : How many concurrent executions of the same code is too much ?
    I would say that latching issues come up on :
    a. Shared Pool : Multiple sessions attempting to load SQL statements and Parse SQL statements
    You could reduce some of this with reusable SQLs and bind variables instead of literals in quick running jobs / user front end screens etc
    b. Buffer Cache : Hot Blocks being frequently pinned -- eg index root blocks or "busy" table blocks.
    If you are running, say 4-8 concurrent copies of the the same code on a 4 CPU or 8 CPU machine, you may not be running into latching issues on the code -- "may not be" -- we can't be too sure, until we identify which latches are under "issue".
    However, if the queries are executing nested loops and frequently accessing the same index blocks, you may more likely be having issues with latches on cache buffer chains.
    So, this is what I would suggest :
    a. Identify the size and scale of the "issues" -- how much CPU time / wait time is accounted for by the latches in relation to the total response time of each of the jobs
    b. Identify which latches are the ones under contention
    c. On the basis of which latches are the holding up performance, decide your next course of action.
    Hemant K Chitale
    http://hemantoracledba.blogspot.com

  • PL/SQL 101 : Cursors and SQL Projection

    PL/SQL 101 : Cursors and SQL Projection
    This is not a question, it's a forum article, in reponse to the number of questions we get regarding a "dynamic number of columns" or "rows to columns"
    There are two integral parts to an SQL Select statement that relate to what data is selected. One is Projection and the other is Selection:-
    Selection is the one that we always recognise and use as it forms the WHERE clause of the select statement, and hence selects which rows of data are queried.
    The other, SQL Projection is the one that is less understood, and the one that this article will help to explain.
    In short, SQL Projection is the collective name for the columns that are Selected and returned from a query.
    So what? Big deal eh? Why do we need to know this?
    The reason for knowing this is that many people are not aware of when SQL projection comes into play when you issue a select statement. So let's take a basic query...
    First create some test data...
    create table proj_test as
      select 1 as id, 1 as rn, 'Fred' as nm from dual union all
      select 1,2,'Bloggs' from dual union all
      select 2,1,'Scott' from dual union all
      select 2,2,'Smith' from dual union all
      select 3,1,'Jim' from dual union all
      select 3,2,'Jones' from dual
    ... and now query that data...
    SQL> select * from proj_test;
             ID         RN NM
             1          1 Fred
             1          2 Bloggs
             2          1 Scott
             2          2 Smith
             3          1 Jim
             3          2 Jones
    6 rows selected.
    OK, so what is that query actually doing?
    To know that we need to consider that all queries are cursors and all cursors are processed in a set manner, roughly speaking...
    1. The cursor is opened
    2. The query is parsed
    3. The query is described to know the projection (what columns are going to be returned, names, datatypes etc.)
    4. Bind variables are bound in
    5. The query is executed to apply the selection and identify the data to be retrieved
    6. A row of data is fetched
    7. The data values from the columns within that row are extracted into the known projection
    8. Step 6 and 7 are repeated until there is no more data or another condition ceases the fetching
    9. The cursor is closed
    The purpose of the projection being determined is so that the internal processing of the cursor can allocate memory etc. ready to fetch the data into. We won't get to see that memory allocation happening easily, but we can see the same query being executed in these steps if we do it programatically using the dbms_sql package...
    CREATE OR REPLACE PROCEDURE process_cursor (p_query in varchar2) IS
      v_sql       varchar2(32767) := p_query;
      v_cursor    number;            -- A cursor is a handle (numeric identifier) to the query
      col_cnt     integer;
      v_n_val     number;            -- numeric type to fetch data into
      v_v_val     varchar2(20);      -- varchar type to fetch data into
      v_d_val     date;              -- date type to fetch data into
      rec_tab     dbms_sql.desc_tab; -- table structure to hold sql projection info
      dummy       number;
      v_ret       number;            -- number of rows returned
      v_finaltxt  varchar2(100);
      col_num     number;
    BEGIN
      -- 1. Open the cursor
      dbms_output.put_line('1 - Opening Cursor');
      v_cursor := dbms_sql.open_cursor;
      -- 2. Parse the cursor
      dbms_output.put_line('2 - Parsing the query');
      dbms_sql.parse(v_cursor, v_sql, dbms_sql.NATIVE);
      -- 3. Describe the query
      -- Note: The query has been described internally when it was parsed, but we can look at
      --       that description...
      -- Fetch the description into a structure we can read, returning the count of columns that has been projected
      dbms_output.put_line('3 - Describing the query');
      dbms_sql.describe_columns(v_cursor, col_cnt, rec_tab);
      -- Use that description to define local datatypes into which we want to fetch our values
      -- Note: This only defines the types, it doesn't fetch any data and whilst we can also
      --       determine the size of the columns we'll just use some fixed sizes for this example
      dbms_output.put_line(chr(10)||'3a - SQL Projection:-');
      for j in 1..col_cnt
      loop
        v_finaltxt := 'Column Name: '||rpad(upper(rec_tab(j).col_name),30,' ');
        case rec_tab(j).col_type
          -- if the type of column is varchar2, bind that to our varchar2 variable
          when 1 then
            dbms_sql.define_column(v_cursor,j,v_v_val,20);
            v_finaltxt := v_finaltxt||' Datatype: Varchar2';
          -- if the type of the column is number, bind that to our number variable
          when 2 then
            dbms_sql.define_column(v_cursor,j,v_n_val);
            v_finaltxt := v_finaltxt||' Datatype: Number';
          -- if the type of the column is date, bind that to our date variable
          when 12 then
            dbms_sql.define_column(v_cursor,j,v_d_val);
            v_finaltxt := v_finaltxt||' Datatype: Date';
          -- ...Other types can be added as necessary...
        else
          -- All other types we'll assume are varchar2 compatible (implicitly converted)
          dbms_sql.DEFINE_COLUMN(v_cursor,j,v_v_val,2000);
          v_finaltxt := v_finaltxt||' Datatype: Varchar2 (implicit)';
        end case;
        dbms_output.put_line(v_finaltxt);
      end loop;
      -- 4. Bind variables
      dbms_output.put_line(chr(10)||'4 - Binding in values');
      null; -- we have no values to bind in for our test
      -- 5. Execute the query to make it identify the data on the database (Selection)
      -- Note: This doesn't fetch any data, it just identifies what data is required.
      dbms_output.put_line('5 - Executing the query');
      dummy := dbms_sql.execute(v_cursor);
      -- 6.,7.,8. Fetch the rows of data...
      dbms_output.put_line(chr(10)||'6,7 and 8 Fetching Data:-');
      loop
        -- 6. Fetch next row of data
        v_ret := dbms_sql.fetch_rows(v_cursor);
        -- If the fetch returned no row then exit the loop
        exit when v_ret = 0;
        -- 7. Extract the values from the row
        v_finaltxt := null;
        -- loop through each of the Projected columns
        for j in 1..col_cnt
        loop
          case rec_tab(j).col_type
            -- if it's a varchar2 column
            when 1 then
              -- read the value into our varchar2 variable
              dbms_sql.column_value(v_cursor,j,v_v_val);
              v_finaltxt := ltrim(v_finaltxt||','||rpad(v_v_val,20,' '),',');
            -- if it's a number column
            when 2 then
              -- read the value into our number variable
              dbms_sql.column_value(v_cursor,j,v_n_val);
              v_finaltxt := ltrim(v_finaltxt||','||to_char(v_n_val,'fm999999'),',');
            -- if it's a date column
            when 12 then
              -- read the value into our date variable
              dbms_sql.column_value(v_cursor,j,v_d_val);
              v_finaltxt := ltrim(v_finaltxt||','||to_char(v_d_val,'DD/MM/YYYY HH24:MI:SS'),',');
          else
            -- read the value into our varchar2 variable (assumes it can be implicitly converted)
            dbms_sql.column_value(v_cursor,j,v_v_val);
            v_finaltxt := ltrim(v_finaltxt||',"'||rpad(v_v_val,20,' ')||'"',',');
          end case;
        end loop;
        dbms_output.put_line(v_finaltxt);
        -- 8. Loop to fetch next row
      end loop;
      -- 9. Close the cursor
      dbms_output.put_line(chr(10)||'9 - Closing the cursor');
      dbms_sql.close_cursor(v_cursor);
    END;
    SQL> exec process_cursor('select * from proj_test');
    1 - Opening Cursor
    2 - Parsing the query
    3 - Describing the query
    3a - SQL Projection:-
    Column Name: ID                             Datatype: Number
    Column Name: RN                             Datatype: Number
    Column Name: NM                             Datatype: Varchar2
    4 - Binding in values
    5 - Executing the query
    6,7 and 8 Fetching Data:-
    1     ,1     ,Fred
    1     ,2     ,Bloggs
    2     ,1     ,Scott
    2     ,2     ,Smith
    3     ,1     ,Jim
    3     ,2     ,Jones
    1     ,3     ,Freddy
    1     ,4     ,Fud
    9 - Closing the cursor
    PL/SQL procedure successfully completed.
    So, what's really the point in knowing when SQL Projection occurs in a query?
    Well, we get many questions asking "How do I convert rows to columns?" (otherwise known as a pivot) or questions like "How can I get the data back from a dynamic query with different columns?"
    Let's look at a regular pivot. We would normally do something like...
    SQL> select id
      2        ,max(decode(rn,1,nm)) as nm_1
      3        ,max(decode(rn,2,nm)) as nm_2
      4  from proj_test
      5  group by id
      6  /
            ID NM_1   NM_2
             1 Fred   Bloggs
             2 Scott  Smith
             3 Jim    Jones
    (or, in 11g, use the new PIVOT statement)
    but many of these questioners don't understand it when they say their issue is that, they have an unknown number of rows and don't know how many columns it will have, and they are told that you can't do that in a single SQL statement. e.g.
    SQL> insert into proj_test (id, rn, nm) values (1,3,'Freddy');
    1 row created.
    SQL> select id
      2        ,max(decode(rn,1,nm)) as nm_1
      3        ,max(decode(rn,2,nm)) as nm_2
      4  from proj_test
      5  group by id
      6  /
            ID NM_1   NM_2
             1 Fred   Bloggs
             2 Scott  Smith
             3 Jim    Jones
    ... it's not giving us this 3rd entry as a new column and we can only get that by writing the expected columns into the query, but then what if more columns are added after that etc.
    If we look back at the steps of a cursor we see again that the description and projection of what columns are returned by a query happens before any data is fetched back.
    Because of this, it's not possible to have the query return back a number of columns that are based on the data itself, as no data has been fetched at the point the projection is required.
    So, what is the answer to getting an unknown number of columns in the output?
    1) The most obvious answer is, don't use SQL to try and pivot your data. Pivoting of data is more of a reporting requirement and most reporting tools include the ability to pivot data either as part of the initial report generation or on-the-fly at the users request. The main point about using the reporting tools is that they query the data first and then the pivoting is simply a case of manipulating the display of those results, which can be dynamically determined by the reporting tool based on what data there is.
    2) The other answer is to write dynamic SQL. Because you're not going to know the number of columns, this isn't just a simple case of building up a SQL query as a string and passing it to the EXECUTE IMMEDIATE command within PL/SQL, because you won't have a suitable structure to read the results back into as those structures must have a known number of variables for each of the columns at design time, before the data is know. As such, inside PL/SQL code, you would have to use the DBMS_SQL package, just like in the code above that showed the workings of a cursor, as the columns there are referenced by position rather than name, and you have to deal with each column seperately. What you do with each column is up to you... store them in an array/collection, process them as you get them, or whatever. They key thing though with doing this is that, just like the reporting tools, you would need to process the data first to determine what your SQL projection is, before you execute the query to fetch the data in the format you want e.g.
    create or replace procedure dyn_pivot is
      v_sql varchar2(32767);
      -- cursor to find out the maximum number of projected columns required
      -- by looking at the data
      cursor cur_proj_test is
        select distinct rn
        from   proj_test
        order by rn;
    begin
      v_sql := 'select id';
      for i in cur_proj_test
      loop
        -- dynamically add to the projection for the query
        v_sql := v_sql||',max(decode(rn,'||i.rn||',nm)) as nm_'||i.rn;
      end loop;
      v_sql := v_sql||' from proj_test group by id order by id';
      dbms_output.put_line('Dynamic SQL Statement:-'||chr(10)||v_sql||chr(10)||chr(10));
      -- call our DBMS_SQL procedure to process the query with it's dynamic projection
      process_cursor(v_sql);
    end;
    SQL> exec dyn_pivot;
    Dynamic SQL Statement:-
    select id,max(decode(rn,1,nm)) as nm_1,max(decode(rn,2,nm)) as nm_2,max(decode(rn,3,nm)) as nm_3 from proj_test group by id order by id
    1 - Opening Cursor
    2 - Parsing the query
    3 - Describing the query
    3a - SQL Projection:-
    Column Name: ID                             Datatype: Number
    Column Name: NM_1                           Datatype: Varchar2
    Column Name: NM_2                           Datatype: Varchar2
    Column Name: NM_3                           Datatype: Varchar2
    4 - Binding in values
    5 - Executing the query
    6,7 and 8 Fetching Data:-
    1     ,Fred                ,Bloggs              ,Freddy
    2     ,Scott               ,Smith               ,
    3     ,Jim                 ,Jones               ,
    9 - Closing the cursor
    PL/SQL procedure successfully completed.
    ... and if more data is added ...
    SQL> insert into proj_test (id, rn, nm) values (1,4,'Fud');
    1 row created.
    SQL> exec dyn_pivot;
    Dynamic SQL Statement:-
    select id,max(decode(rn,1,nm)) as nm_1,max(decode(rn,2,nm)) as nm_2,max(decode(rn,3,nm)) as nm_3,max(decode(rn,4,nm)) as nm_4 from proj_test group by id order by id
    1 - Opening Cursor
    2 - Parsing the query
    3 - Describing the query
    3a - SQL Projection:-
    Column Name: ID                             Datatype: Number
    Column Name: NM_1                           Datatype: Varchar2
    Column Name: NM_2                           Datatype: Varchar2
    Column Name: NM_3                           Datatype: Varchar2
    Column Name: NM_4                           Datatype: Varchar2
    4 - Binding in values
    5 - Executing the query
    6,7 and 8 Fetching Data:-
    1     ,Fred                ,Bloggs              ,Freddy              ,Fud
    2     ,Scott               ,Smith               ,                    ,
    3     ,Jim                 ,Jones               ,                    ,
    9 - Closing the cursor
    PL/SQL procedure successfully completed.
    Of course there are other methods, using dynamically generated scripts etc. (see Re: 4. How do I convert rows to columns?), but the above simply demonstrates that:-
    a) having a dynamic projection requires two passes of the data; one to dynamically generate the query and another to actually query the data,
    b) it is not a good idea in most cases as it requires code to handle the results dynamically rather than being able to simply query directly into a known structure or variables, and
    c) a simple SQL statement cannot have a dynamic projection.
    Most importantly, dynamic queries prevent validation of your queries at the time your code is compiled, so the compiler can't check that the column names are correct or the tables names, or that the actual syntax of the generated query is correct. This only happens at run-time, and depending upon the complexity of your dynamic query, some problems may only be experienced under certain conditions. In effect you are writing queries that are harder to validate and could potentially have bugs in them that would are not apparent until they get to a run time environment. Dynamic queries can also introduce the possibility of SQL injection (a potential security risk), especially if a user is supplying a string value into the query from an interface.
    To summarise:-
    The projection of an SQL statement must be known by the SQL engine before any data is fetched, so don't expect SQL to magically create columns on-the-fly based on the data it's retrieving back; and, if you find yourself thinking of using dynamic SQL to get around it, just take a step back and see if what you are trying to achieve may be better done elsewhere, such as in a reporting tool or the user interface.
    Other articles in the PL/SQL 101 series:-
    PL/SQL 101 : Understanding Ref Cursors
    PL/SQL 101 : Exception Handling

    excellent article. However there is one thing which is slightly erroneous. You don't need a type to be declared in the database to fetch the data, but you do need to declare a type;
    here is one of my unit test scripts that does just that.
    DECLARE
    PN_CARDAPPL_ID NUMBER;
    v_Return Cci_Standard.ref_cursor;
    type getcardapplattrval_recordtype
    Is record
    (cardappl_id ci_cardapplattrvalue.cardappl_ID%TYPE,
    tag ci_cardapplattrvalue.tag%TYPE,
    value ci_cardapplattrvalue.value%TYPE
    getcardapplattrvalue_record getcardapplattrval_recordtype;
    BEGIN
    PN_CARDAPPL_ID := 1; --value must be supplied
    v_Return := CCI_GETCUSTCARD.GETCARDAPPLATTRVALUE(
    PN_CARDAPPL_ID => PN_CARDAPPL_ID
    loop
    fetch v_return
    into getcardapplattrvalue_record;
    dbms_output.put_line('Cardappl_id=>'||getcardapplattrvalue_record.cardappl_id);
    dbms_output.put_line('Tag =>'||getcardapplattrvalue_record.tag);
    dbms_output.put_line('Value =>'||getcardapplattrvalue_record.value);
    exit when v_Return%NOTFOUND;
    end loop;
    END;

  • PL/SQL block to create temporary table + load via cursor for loop

    Assume I have a table that contains a subset of data that I want to load into a temporary table within a cursor for-loop. Is it possible to have a single statement to create the table and load based on the results of the fetch?
    I was thinking something like:
    Declare CURSOR xyz is
    CREATE TABLE temp_table as
    select name, rank, serial number from
    HR table where rank = 'CAPTAIN'
    BEGIN
    OPEN xyz
    for name in xyz
    LOOP
    END LOOP
    What I see wrong with this is that the table would be created multiple times which is why this syntax is not acceptable. I'd prefer not to have to define the temporary table then load in two sepearte SQL statements and am hoping a single statement can be used.
    Thanks!

    What is the goal here?
    If you're just going to iterate over the rows that are returned in a cursor, a temporary table is unnecessary and only adds complexity. If you truly need a temporary table, you would declare it exactly once, at install time when you create all your other tables. You'd INSERT data into the temp table and the data would only be visible to the session that inserted it.
    Justin

  • Cursor For Loop SQL/PL right application? Need help with PL Performance

    I will preface this post by saying that I am a novice Oracle PL user, so an overexplanation would not be an issue here.
    Goal: Run a hierarchial query for over 120k rows and insert output into Table 1. Currently I am using a Cursor For Loop that takes the first record and puts 2 columns in "Start" section and "connect by" section. The hierarchial query runs and then it inserts the output into another table. I do this 120k times( I know it's not very efficient). Now the hierarchial query doesn't take too long ( run by itself for many parts) but this loop process is taking over 9 hrs to run all 120k records. I am looking for a way to make this run faster. I've read about "Bulk collect" and "forall", but I am not understanding how they function to help me in my specific case.
    Is there anyway I can rewrite the PL/SQL Statement below with the Cursor For loop or with another methodology to accomplish the goal significantly quicker?
    Below is the code ( I am leaving some parts out for space)
    CREATE OR REPLACE PROCEDURE INV_BOM is
    CURSOR DISPATCH_CSR IS
    select materialid,plantid
    from INV_SAP_BOM_MAKE_UNIQUE;
    Begin
    For Row_value in Dispatch_CSR Loop
    begin
    insert into Table 1
    select column1
    ,column2
    ,column3
    ,column4
    from( select ..
    from table 3
    start with materialid = row_value.materialid
    and plantid = row_value.plantid
    connect by prior plantid = row.value_plantid
    exception...
    end loop
    exception..
    commit

    BluShadow:
    The table that the cursor is pulling from ( INV_SAP_BOM_MAKE_UNIQUE) has only 2 columns
    Materialid and Plantid
    Example
    Materialid Plantid
    100-C 1000
    100-B 1010
    X-2 2004
    I use the cursor to go down the list 1 by 1 and run a hierarchical query for each row. The only reason I do this is because I have 120,000 materialid,plantid combinations that I need to run and SQL has a limit of 1000 items in the "start with" if I'm semi-correct on that.
    Structure of Table it would be inserted into ( Table 1) after Hierarchical SQL Statement runs:
    Materialid Plantid User Create Column1 Col2
    100-C 1000 25 EA
    The Hierarchical query ran gives the 2 columns at the end.
    I am looking for a way to either just run a quicker SQL or a more efficient way of running all 120,000 materialid, plantid rows through the Hierarchial Query.
    Any Advice? I really appreciate it. Thank You.

  • Help with if statement in cursor and for loop to get output

    I have the following cursor and and want to use if else statement to get the output. The cursor is working fine. What i need help with is how to use and if else statement to only get the folderrsn that have not been updated in the last 30 days. If you look at the talbe below my select statement is showing folderrs 291631 was updated only 4 days ago and folderrsn 322160 was also updated 4 days ago.
    I do not want these two to appear in my result set. So i need to use if else so that my result only shows all folderrsn that havenot been updated in the last 30 days.
    Here is my cursor:
    /*Cursor for Email procedure. It is working Shows userid and the string
    You need to update these folders*/
    DECLARE
    a_user varchar2(200) := null;
    v_assigneduser varchar2(20);
    v_folderrsn varchar2(200);
    v_emailaddress varchar2(60);
    v_subject varchar2(200);
    Cursor c IS
    SELECT assigneduser, vu.emailaddress, f.folderrsn, trunc(f.indate) AS "IN DATE",
    MAX (trunc(fpa.attemptdate)) AS "LAST UPDATE",
    trunc(sysdate) - MAX (trunc(fpa.attemptdate)) AS "DAYS PAST"
    --MAX (TRUNC (fpa.attemptdate)) - TRUNC (f.indate) AS "NUMBER OF DAYS"
    FROM folder f, folderprocess fp, validuser vu, folderprocessattempt fpa
    WHERE f.foldertype = 'HJ'
    AND f.statuscode NOT IN (20, 40)
    AND f.folderrsn = fp.folderrsn
    AND fp.processrsn = fpa.processrsn
    AND vu.userid = fp.assigneduser
    AND vu.statuscode = 1
    GROUP BY assigneduser, vu.emailaddress, f.folderrsn, f.indate
    ORDER BY fp.assigneduser;
    BEGIN
    FOR c1 IN c LOOP
    IF (c1.assigneduser = v_assigneduser) THEN
    dbms_output.put_line(' ' || c1.folderrsn);
    else
    dbms_output.put(c1.assigneduser ||': ' || 'Overdue Folders:You need to update these folders: Folderrsn: '||c1.folderrsn);
    END IF;
    a_user := c1.assigneduser;
    v_assigneduser := c1.assigneduser;
    v_folderrsn := c1.folderrsn;
    v_emailaddress := c1.emailaddress;
    v_subject := 'Subject: Project for';
    END LOOP;
    END;
    The reason I have included the folowing table is that I want you to see the output from the select statement. that way you can help me do the if statement in the above cursor so that the result will look like this:
    emailaddress
    Subject: 'Project for ' || V_email || 'not updated in the last 30 days'
    v_folderrsn
    v_folderrsn
    etc
    [email protected]......
    Subject: 'Project for: ' Jim...'not updated in the last 30 days'
    284087
    292709
    [email protected].....
    Subject: 'Project for: ' Kim...'not updated in the last 30 days'
    185083
    190121
    190132
    190133
    190159
    190237
    284109
    286647
    294631
    322922
    [email protected]....
    Subject: 'Project for: Joe...'not updated in the last 30 days'
    183332
    183336
    [email protected]......
    Subject: 'Project for: Sam...'not updated in the last 30 days'
    183876
    183877
    183879
    183880
    183881
    183882
    183883
    183884
    183886
    183887
    183888
    This table is to shwo you the select statement output. I want to eliminnate the two days that that are less than 30 days since the last update in the last column.
    Assigneduser....Email.........Folderrsn...........indate.............maxattemptdate...days past since last update
    JIM.........      jim@ aol.com.... 284087.............     9/28/2006.......10/5/2006...........690
    JIM.........      jim@ aol.com.... 292709.............     3/20/2007.......3/28/2007............516
    KIM.........      kim@ aol.com.... 185083.............     8/31/2004.......2/9/2006.............     928
    KIM...........kim@ aol.com.... 190121.............     2/9/2006.........2/9/2006.............928
    KIM...........kim@ aol.com.... 190132.............     2/9/2006.........2/9/2006.............928
    KIM...........kim@ aol.com.... 190133.............     2/9/2006.........2/9/2006.............928
    KIM...........kim@ aol.com.... 190159.............     2/13/2006.......2/14/2006............923
    KIM...........kim@ aol.com.... 190237.............     2/23/2006.......2/23/2006............914
    KIM...........kim@ aol.com.... 284109.............     9/28/2006.......9/28/2006............697
    KIM...........kim@ aol.com.... 286647.............     11/7/2006.......12/5/2006............629
    KIM...........kim@ aol.com.... 294631.............     4/2/2007.........3/4/2008.............174
    KIM...........kim@ aol.com.... 322922.............     7/29/2008.......7/29/2008............27
    JOE...........joe@ aol.com.... 183332.............     1/28/2004.......4/23/2004............1585
    JOE...........joe@ aol.com.... 183336.............     1/28/2004.......3/9/2004.............1630
    SAM...........sam@ aol.com....183876.............3/5/2004.........3/8/2004.............1631
    SAM...........sam@ aol.com....183877.............3/5/2004.........3/8/2004.............1631
    SAM...........sam@ aol.com....183879.............3/5/2004.........3/8/2004.............1631
    SAM...........sam@ aol.com....183880.............3/5/2004.........3/8/2004.............1631
    SAM...........sam@ aol.com....183881.............3/5/2004.........3/8/2004.............1631
    SAM...........sam@ aol.com....183882.............3/5/2004.........3/8/2004.............1631
    SAM...........sam@ aol.com....183883.............3/5/2004.........3/8/2004.............1631
    SAM...........sam@ aol.com....183884.............3/5/2004.........3/8/2004............     1631
    SAM...........sam@ aol.com....183886.............3/5/2004.........3/8/2004............     1631
    SAM...........sam@ aol.com....183887.............3/5/2004.........3/8/2004............     1631
    SAM...........sam@ aol.com....183888.............3/5/2004.........3/8/2004............     1631
    PAT...........pat@ aol.com.....291630.............2/23/2007.......7/8/2008............     48
    PAT...........pat@ aol.com.....313990.............2/27/2008.......7/28/2008............28
    NED...........ned@ aol.com.....190681.............4/4/2006........8/10/2006............746
    NED...........ned@ aol.com......95467.............6/14/2006.......11/6/2006............658
    NED...........ned@ aol.com......286688.............11/8/2006.......10/3/2007............327
    NED...........ned@ aol.com.....291631.............2/23/2007.......8/21/2008............4
    NED...........ned@ aol.com.....292111.............3/7/2007.........2/26/2008............181
    NED...........ned@ aol.com.....292410.............3/15/2007.......7/22/2008............34
    NED...........ned@ aol.com.....299410.............6/27/2007.......2/27/2008............180
    NED...........ned@ aol.com.....303790.............9/19/2007.......9/19/2007............341
    NED...........ned@ aol.com.....304268.............9/24/2007.......3/3/2008............     175
    NED...........ned@ aol.com.....308228.............12/6/2007.......12/6/2007............263
    NED...........ned@ aol.com.....316689.............3/19/2008.......3/19/2008............159
    NED...........ned@ aol.com.....316789.............3/20/2008.......3/20/2008............158
    NED...........ned@ aol.com.....317528.............3/25/2008.......3/25/2008............153
    NED...........ned@ aol.com.....321476.............6/4/2008.........6/17/2008............69
    NED...........ned@ aol.com.....322160.............7/3/2008.........8/21/2008............4
    MOE...........moe@ aol.com.....184169.............4/5/2004.......12/5/2006............629
    [email protected]/27/2004.......3/8/2004............1631
    How do I incorporate a if else statement in the above cursor so the two days less than 30 days since last update are not returned. I do not want to send email if the project have been updated within the last 30 days.
    Edited by: user4653174 on Aug 25, 2008 2:40 PM

    analytical functions: http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96540/functions2a.htm#81409
    CASE
    http://download.oracle.com/docs/cd/B10501_01/appdev.920/a96624/02_funds.htm#36899
    http://download.oracle.com/docs/cd/B10501_01/appdev.920/a96624/04_struc.htm#5997
    Incorporating either of these into your query should assist you in returning the desired results.

  • How to add cursor and for loop

    PROCEDURE "TEST" is
    bala number;
    ins1 number;
    ins2 number;
    BEGIN
    select sum(bal) into bala from (select sum(acp.acp_totbal) bal,acp_instruid from cs_strmap_t map,cs_instru_strips strip,cs_acpos_bkp acp
    where c_int_instruid=c_srm_prncplinsid
    and c_srm_prncplinsid=acp_instruid
    and acp_acntnum!='SG030001'
    group by acp_instruid
    union
    select sum(acp.acp_totbal) bal,acp_instruid from cs_strmap_t map,cs_instru_strips strip,cs_acpos_bkp acp
    where c_int_instruid=c_srm_prncplinsid
    and acp_acntnum!='SG030001'
    and acp_instruid=c_srm_prntinsid
    group by acp_instruid)view1;
    dbms_output.put_line(bala);
    select acp_instruid into ins1 from cs_strmap_t map,cs_instru_strips strip,cs_acpos_bkp acp
    where c_int_instruid=c_srm_prncplinsid
    and c_srm_prncplinsid=acp_instruid
    and acp_acntnum='SG030001';
    dbms_output.put_line('principal'||ins1);
    select acp_instruid into ins2 from cs_strmap_t map,cs_instru_strips strip,cs_acpos_bkp acp
    where c_int_instruid=c_srm_prncplinsid
    and acp_acntnum='SG030001'
    and acp_instruid=c_srm_prntinsid;
    dbms_output.put_line('parent'||ins2);
    update cs_acpos_bkp
    set acp_totbal=-bala
    where acp_instruid=ins2
    and acp_acntnum='SG030001';
    END;
    i have written this code,i need to use cursor and for loops to get more than one rows and update also.
    if there are more than 1 rows in cs_strmap_t,then the procedure throws an error stating that it cannot take 2 rows.
    Edited by: 850836 on Apr 7, 2011 11:43 PM

    PROCEDURE "TEST" is
    bala number;
    ins1 number;
    ins2 number;
    CURSOR cur_1 IS
    select sum(bal) bala from (select sum(acp.acp_totbal) bal,acp_instruid from cs_strmap_t map,cs_instru_strips strip,cs_acpos_bkp acp
    where c_int_instruid=c_srm_prncplinsid
    and c_srm_prncplinsid=acp_instruid
    and acp_acntnum='SG030001'
    group by acp_instruid
    union
    select sum(acp.acp_totbal) bal,acp_instruid from cs_strmap_t map,cs_instru_strips strip,cs_acpos_bkp acp
    where c_int_instruid=c_srm_prncplinsid
    and acp_acntnum='SG030001'
    and acp_instruid=c_srm_prntinsid
    group by acp_instruid)view1;
    BEGIN
    select acp_instruid into ins1 from cs_strmap_t map,cs_instru_strips strip,cs_acpos_bkp acp
    where c_int_instruid=c_srm_prncplinsid
    and c_srm_prncplinsid=acp_instruid
    and acp_acntnum='SG030001';
    dbms_output.put_line('principal'||ins1);
    select acp_instruid into ins2 from cs_strmap_t map,cs_instru_strips strip,cs_acpos_bkp acp
    where c_int_instruid=c_srm_prncplinsid
    and acp_acntnum='SG030001'
    and acp_instruid=c_srm_prntinsid;
    dbms_output.put_line('parent'||ins2);
    for var_for in cur_1
    loop
    update cs_acpos_bkp
    set acp_totbal=var_for.bala
    where acp_instruid=ins2
    and acp_acntnum='SG030001'
    and abs(acp_totbal)>abs(bala);
    dbms_output.put_line(bala);
    end loop;
    END;
    i wrote the following procedure,but the balance is not getting updated.
    Getting this errors when there are more than 1 row in cs_strmap_t table
    ORA-01422: exact fetch returns more than requested number of rows
    ORA-06512: line 22
    ORA-06512: at line 2

  • Ref cursors and dynamic sql..

    I want to be able to use a fuction that will dynamically create a SQL statement and then open a cursor based on that SQL statement and return a ref to that cursor. To achieve that, I am trying to build the sql statement in a varchar2 variable and using that variable to open the ref cursor as in,
    open l_stmt for refcurType;
    where refcurType is a strong ref cursor. I am unable to do so because I get an error indication that I can not use strong ref cursor type. But, if I can not use a strong ref cursor, I will not be able to use it to build the report based on the ref cursor because Reports 9i requires strong ref cursors to be used. Does that mean I can not use dynamic sql with Reports 9i ref cursors? Else, how I can do that? Any documentation available?

    Philipp,
    Thank you for your reply. My requirement is that, sometimes I need to construct a whole query based on some input, and sometimes not. But the output record set would be same and the layout would be more or less same. I thought ref cursor would be ideal. Ofcourse, I could do this without dynamic SQL by writing the SQL multiple times if needed. But, I think dynamic SQL is a proper candidate for this case. Your suggestion to use lexical variable is indeed a good alternative. In effect, if needed, I could generate an entire SQL statement and place in some place holder (like &stmt) and use it as a static SQL query in my data model. In that case, why would one ever need ref cursor in reports? Is one more efficient over the other? My guess is, in the lexical variable case, part of the processing (like parsing) is done on the app server while in a function based ref cursor, the entire process takes place in the DB server and there is probably a better chance for re-use(?)
    Thanks,
    Murali.

Maybe you are looking for