Iterations in SQL...

Hello:
I am working with Oracle 11g.
I have a situation like this:
-- drop table t;
create table t (id number, cust_id number, pct number, amt number, primary key(id));
insert into t values ( 1,123,27,100);
insert into t values ( 2,123,27,-70);
insert into t values ( 3,123,27,180);
insert into t values ( 4,123,27,-200);
insert into t values ( 5,123,27,20);
insert into t values (10,123,20,-100);
insert into t values (11,123,20,-200);
insert into t values (12,123,20,-50);
insert into t values (13,123,20,10);The table has a primary key (id), a customer identifier (cust_id), a discount percent (pct), and an amount (amt).
The amount may be positive or negative.
When the amount is negative it has to be "balanced" with a positive one, proceeding in order with the primary key, in the group (partition, in analytic terms) of data given by customer code and percent discount.
The first positive amount has to be "balanced" with the first negative amount.
If the result is positive, the remaining will be "balanced" with the second negative amount, proceeding until no more negative amounts, or until the positive value is zeroed.
When the first positive amount is zeroed, I have to proceed with the second positive amount, and "balance" it with the negative amounts not already previously used.
The process ends when I have no more negative amounts to subtract, or when I have zeroed every positive amount.
The "balancing" process should go like this, in the "BALANCED AMOUNT" column i have put the iterations used to compute the values.
ID    CUST_ID   PCT     AMT         BALANCED AMOUNT       
1     123       27      100         30      0      0
2     123       27      -70         0       0      0      
3     123       27      180         180     180    10        
4     123       27      -200        -200    -170   0
5     123       27      20          20      20     20        
10    123       20      -100       -90
11    123       20      -200       -200
12    123       20      -50        -50
13    123       20      10         0In the slice of data with PCT=27 I subtract amount -70 from 100, then I balance the next negative amount (-200) with the remaining 30, and then I balance the remaining -170 with 180. The last iteration represents the data I want to have.
In the slice with PCT=20 I have only one positive amount (10), balanced with the first negative amount (-100).
The result I want to have is:
ID    CUST_ID   PCT     AMT         BALANCED AMOUNT       
1     123       27      100         0
2     123       27      -70         0      
3     123       27      180         10        
4     123       27      -200        0
5     123       27      20          20        
10    123       20      -100       -90
11    123       20      -200       -200
12    123       20      -50        -50
13    123       20      10         0I am wondering if it is possible to produce this result with a single sql statement...
Any suggestions welcome.
Thanks,
Andrea

I think it is possible. However the "iterative" rules that you want to apply are somewhat complex. If I understood correctly it is the same a doing a kind negative cumulation working on the difference between total positive and total negative amounts.
As a starter...
select t.*,
       sum(t.amt) over (partition by cust_id, pct order by id rows between unbounded preceding and unbounded following) total,
       sum(greatest(t.amt,0)) over (partition by cust_id, pct order by id rows between unbounded preceding and unbounded following) total_pos,
       sum(least(t.amt,0)) over (partition by cust_id, pct order by id rows between unbounded preceding and unbounded following) total_neg,
       sign(sum(t.amt) over (partition by cust_id, pct order by id rows between unbounded preceding and unbounded following)) sign_total,
       sum(t.amt) over (partition by cust_id, pct order by id desc rows between unbounded preceding and current row) cum_bottom2top,
       sum(greatest(t.amt,0)) over (partition by cust_id, pct order by id desc rows between unbounded preceding and current row) cum_bottom2top_pos,
       sum(least(t.amt,0)) over (partition by cust_id, pct order by id desc rows between unbounded preceding and current row) cum_bottom2top_neg
from t
order by id;
        ID    CUST_ID        PCT        AMT      TOTAL  TOTAL_POS  TOTAL_NEG SIGN_TOTAL CUM_BOTTOM2TOP CUM_BOTTOM2TOP_POS CUM_BOTTOM2TOP_NEG
         1        123         27        100         30        300       -270          1             30                300               -270
         2        123         27        -70         30        300       -270          1            -70                200               -270
         3        123         27        180         30        300       -270          1              0                200               -200
         4        123         27       -200         30        300       -270          1           -180                 20               -200
         5        123         27         20         30        300       -270          1             20                 20                  0
        10        123         20       -100       -340         10       -350         -1           -340                 10               -350
        11        123         20       -200       -340         10       -350         -1           -240                 10               -250
        12        123         20        -50       -340         10       -350         -1            -40                 10                -50
        13        123         20         10       -340         10       -350         -1             10                 10                  0
9 rows selected.
SQL> If the total is positive, we continue only with the positive numbers. If the total is negative we work only with negative numbers.
select t2.*,
       case when sign(total) = 1 and sign(amt) = 1 then total-cum_bottom2top_pos else 0 end rest_pos,
       nvl(lead(case when sign(total) = 1 and sign(amt) = 1 then total-cum_bottom2top_pos else 0 end,1) over (partition by cust_id, pct, sign(total), sign(amt) order by id),0) distribute_rest,
       greatest(nvl(lead(case when sign(total) = 1 and sign(amt) = 1 then total-cum_bottom2top_pos else 0 end,1) over (partition by cust_id, pct, sign(total), sign(amt) order by id),0),0) balanced_rest,
       case when (case when sign(total) = 1 and sign(amt) = 1 then total-cum_bottom2top_pos else 0 end) < 0  -- rest_pos is negative
          then greatest(nvl(lead(case when sign(total) = 1 and sign(amt) = 1 then total-cum_bottom2top_pos else 0 end,1) over (partition by cust_id, pct, sign(total), sign(amt) order by id),0),0) -- use balanced_rest
       when (case when sign(total) = 1 and sign(amt) = 1 then total-cum_bottom2top_pos else 0 end) > 0    -- rest_pos is positve 
          then amt -- use amt
       else
         0
       end balanced_amount
from (select t.id, t.cust_id, t.pct, t.amt,
       sum(t.amt) over (partition by cust_id, pct order by id rows between unbounded preceding and unbounded following) total,
       sum(t.amt) over (partition by cust_id, pct order by id desc rows between unbounded preceding and current row) cum_bottom2top,
       sum(greatest(t.amt,0)) over (partition by cust_id, pct order by id desc rows between unbounded preceding and current row) cum_bottom2top_pos
       from t
       ) t2
order by id;
        ID    CUST_ID        PCT        AMT      TOTAL CUM_BOTTOM2TOP CUM_BOTTOM2TOP_POS   REST_POS DISTRIBUTE_REST BALANCED_REST BALANCED_AMOUNT
         1        123         27        100         30             30                300       -270            -170             0               0
         2        123         27        -70         30            -70                200          0               0             0               0
         3        123         27        180         30              0                200       -170              10            10              10
         4        123         27       -200         30           -180                 20          0               0             0               0
         5        123         27         20         30             20                 20         10               0             0              20
        10        123         20       -100       -340           -340                 10          0               0             0               0
        11        123         20       -200       -340           -240                 10          0               0             0               0
        12        123         20        -50       -340            -40                 10          0               0             0               0
        13        123         20         10       -340             10                 10          0               0             0               0
9 rows selected.
SQL> supplied only the solution for positive amounts. Let you work out the negative version.
I think there is also much room for optimizing the statements, but at least it seems working.
Edited by: Sven W. on Jul 24, 2009 4:38 PM -- removed some columns

Similar Messages

  • Handling iteration in SQL

    Hi
    I have a requirement where, given a contract (site) and part number I need to find the preferred supplier.
    I had asked previously on this forum and thought I had be3en given a working solution with connect by prior and use of nocycle.
    However, my data example was not good enough to test all scenarios, or at least enough scenarios.
    I have a supplier table, which has a vendor number and an acquisition site.
    I also have a purchase part supplier table which has for a given contract and part number, vendor number and whether the supplier is a primary vendor for that contract/part number.
    In essence, for a given contract and part number I need to return the preferred vendor number.
    However, there may be a few iterations to get that, because where the acquisition site for a supplier is not blank, I need to then use this as a link for to get the next supplier.
    As usual, example helps, I think.
    Consider this data:
    Supplier:
    Vendor_no  Acquisition_site
    1000       UK1
    1001       UK3
    1002       UK1
    1003       blank
    1004       UK2
    1005       UK1
    1006       UK2
    1007       blank
    1008       blank
    Purchase_Part_Supplier:
    Contract Part_no Vendor_no Primary_Vendor_db
    UK1      A       1000      N
    UK1      A       1001      N
    UK1      A       1002      Y
    UK2      A       1001      Y
    UK3      A       1000      N
    UK4      A       1006      Y
    UK1      B       1004      Y
    UK2      B       1001      Y
    UK3      B       1007      Y
    UK4      B       1008      YThis can be created as:
    with
    supplier as (
    select 1000 vendor_no, 'UK1' acquisition_site from dual UNION ALL
    select 1001, 'UK3' from dual UNION ALL
    select 1002, 'UK1' from dual UNION ALL
    select 1003, null from dual UNION ALL
    select 1004, 'UK2' from dual UNION ALL
    select 1005, 'UK1' from dual UNION ALL
    select 1006, 'UK2' from dual UNION ALL
    select 1007, null from dual UNION ALL
    select 1008, null from dual
    purchase_part_supplier as (
    select 'UK1' contract, 'A' part_no, 'N' primary_vendor_db, 1000 vendor_no from dual UNION ALL
    select 'UK1', 'A', 'N', 1001 from dual UNION ALL
    select 'UK1', 'A', 'Y', 1002 from dual UNION ALL
    select 'UK2', 'A', 'Y', 1001 from dual UNION ALL
    select 'UK3', 'A', 'N', 1000 from dual UNION ALL
    select 'UK4', 'A', 'Y', 1006 from dual UNION ALL
    select 'UK1', 'B', 'Y', 1004 from dual UNION ALL
    select 'UK2', 'B', 'Y', 1001 from dual UNION ALL
    select 'UK3', 'B', 'Y', 1007 from dual UNION ALL
    select 'UK4', 'B', 'Y', 1008 from dual
    )I create a single list by joining the data as follows:
    select s.vendor_no, s.acquisition_site, pps.contract, pps.part_no
    from  supplier s, purchase_part_supplier pps
    where s.vendor_no=pps.vendor_no(+) and primary_vendor_db(+)='Y'This generates a list like this (I believe!):
    vendor_no  acquisition_site  contract  part_no
    1000       UK1              
    1001       UK3               UK2       A
    1001       UK3               UK2       B
    1002       UK1               UK1       A
    1003       blank            
    1004       UK2               UK1       B
    1005       UK1              
    1006       UK2               UK4       A
    1007       blank             UK3       B
    1008       blank             UK4       BWhere I need to find the preferred vendor number for contract UK4, part number B the acquisition site for UK4/B is blank, so the vendor number is 1008 (the last row is the data set)
    For contract UK2, part number B, the acquisition site (for contract UK2, part number B) is UK3 so we try again with this combination.
    The acquisition site (for contract UK3, part number B) is blank and the vendor number is 1007 so this is returned.
    However, to cater for bad data, consider where we look for contract UK1 and part number A. The acquisition site is UK1 which is the same as the contract, so this would create an infinite loop. Therefore we need to abort as such.
    Also, consider contract UK3, part number A. There is no row at all for this, so again, abort accordingly.
    The following scenarios are, to my knowledge the required results.
    Starting    Result
    Cont  Part 
    UK1   A     Returns vendor_no 1002, acquisition_site UK1.  Since the acquisition_site = contract this is infinite cycle, so abort as 'infinite cycle'.
    UK2   A     Returns vendor_no 1001, acquisition_site UK3.
    UK3   A     No row found, abort as 'no primary supplier found'.
    UK3   A     No row found, abort as 'no primary supplier found'.
    UK4   A     Returns vendor_no 1006, acquisition_site UK2. 
    UK2   A     Returns vendor_no 1001, acquisition_site UK3.
    UK3   A     No row found, abort as 'no primary supplier found'.
    UK1   B     Returns vendor_no 1004, acquisition_site UK2.
    UK2   B     Returns vendor_no 1001, acquisition_site UK3.
    UK3   B     Returns vendor_no 1007, acquisition_site blank.  Return 1007 as vendor number.
    UK2   B     Returns vendor_no 1001, acquisition_site UK3.
    UK3   B     Returns vendor_no 1007, acquisition_site blank.  Return 1007 as vendor number.
    UK3   B     Returns vendor_no 1007, acquisition_site blank.  Return 1007 as vendor number.
    UK4   B     Returns vendor_no 1008, acquisition_site blank.  Return 1008 as vendor number.Can this be done or will I have to resort to PL/SQL?
    Thanks
    Martin

    Well, I believe I have cracked it!
    with
    supplier as (
    select 1000 vendor_no, 'UK1' acquisition_site from dual UNION ALL
    select 1001, 'UK3' from dual UNION ALL
    select 1002, 'UK1' from dual UNION ALL
    select 1003, null from dual UNION ALL
    select 1004, 'UK2' from dual UNION ALL
    select 1005, 'UK1' from dual UNION ALL
    select 1006, 'UK2' from dual UNION ALL
    select 1007, null from dual UNION ALL
    select 1008, null from dual
    purchase_part_supplier as (
    select 'UK1' contract, 'A' part_no, 'N' primary_vendor_db, 1000 vendor_no from dual UNION ALL
    select 'UK1', 'A', 'N', 1001 from dual UNION ALL
    select 'UK1', 'A', 'Y', 1002 from dual UNION ALL
    select 'UK2', 'A', 'Y', 1001 from dual UNION ALL
    select 'UK3', 'A', 'N', 1000 from dual UNION ALL
    select 'UK4', 'A', 'Y', 1006 from dual UNION ALL
    select 'UK1', 'B', 'Y', 1004 from dual UNION ALL
    select 'UK2', 'B', 'Y', 1001 from dual UNION ALL
    select 'UK3', 'B', 'Y', 1007 from dual UNION ALL
    select 'UK4', 'B', 'Y', 1008 from dual
    select nvl(return_value,default_value) return_value from
    select 1 lnk, decode(CONNECT_BY_ISCYCLE,1,'**DataCyc', decode(acquisition_site, null, to_char(vendor_no,999999), '**DataMiss')) return_value
    from
    select s.vendor_no, s.acquisition_site, pps.contract, pps.part_no
    from  supplier s, purchase_part_supplier pps
    where s.vendor_no=pps.vendor_no(+) and primary_vendor_db(+)='Y'
    ) q
    where CONNECT_BY_ISCYCLE=1 or CONNECT_BY_ISLEAF=1
    start with contract='UK3' and part_no='A'
    connect by nocycle
    prior acquisition_site=contract and prior part_no=part_no
    (select 1 dftlnk, '**DataMiss' default_value from dual)
    where dftlnk=lnk(+)

  • Copy hiearchical data using SQL only.

    Is there anyway to copy hiearchical data that use ID's without using a pl/sql loop procedure or a global temporary table?
    Example
    CREATE TABLE DUCK_TREE
    FIRST_NAME VARCHAR2(100 BYTE),
    LAST_NAME VARCHAR2(100 BYTE),
    FAMILY_ID NUMBER,
    PARENT_ID NUMBER
    INSERT INTO DUCK_TREE ( FIRST_NAME, LAST_NAME, FAMILY_ID, PARENT_ID ) VALUES (
    'Louie', 'Duck', 207, 203);
    INSERT INTO DUCK_TREE ( FIRST_NAME, LAST_NAME, FAMILY_ID, PARENT_ID ) VALUES (
    'Dewey', 'Duck', 206, 203);
    INSERT INTO DUCK_TREE ( FIRST_NAME, LAST_NAME, FAMILY_ID, PARENT_ID ) VALUES (
    'Huey', 'Duck', 205, 203);
    INSERT INTO DUCK_TREE ( FIRST_NAME, LAST_NAME, FAMILY_ID, PARENT_ID ) VALUES (
    'Donald', 'Duck', 204, 201);
    INSERT INTO DUCK_TREE ( FIRST_NAME, LAST_NAME, FAMILY_ID, PARENT_ID ) VALUES (
    'Thelma', 'Duck', 203, 201);
    INSERT INTO DUCK_TREE ( FIRST_NAME, LAST_NAME, FAMILY_ID, PARENT_ID ) VALUES (
    'Daphne', 'Duck', 202, 200);
    INSERT INTO DUCK_TREE ( FIRST_NAME, LAST_NAME, FAMILY_ID, PARENT_ID ) VALUES (
    'Quackmore', 'Duck', 201, 200);
    INSERT INTO DUCK_TREE ( FIRST_NAME, LAST_NAME, FAMILY_ID, PARENT_ID ) VALUES (
    'Grandma', 'Duck', 200, NULL);
    INSERT INTO DUCK_TREE ( FIRST_NAME, LAST_NAME, FAMILY_ID, PARENT_ID ) VALUES (
    'Hortense', 'McDuck', 103, 100);
    INSERT INTO DUCK_TREE ( FIRST_NAME, LAST_NAME, FAMILY_ID, PARENT_ID ) VALUES (
    'Scrooge', 'McDuck', 102, 100);
    INSERT INTO DUCK_TREE ( FIRST_NAME, LAST_NAME, FAMILY_ID, PARENT_ID ) VALUES (
    'Matilda', 'McDuck', 101, 100);
    INSERT INTO DUCK_TREE ( FIRST_NAME, LAST_NAME, FAMILY_ID, PARENT_ID ) VALUES (
    'Scotty', 'McDuck', 100, NULL);
    COMMIT;
    Now you would like to copy the hierachical data starting say at Grandma and all children?

    I can't really see a way to get away from iterative PL/SQL or the use of temporary tables (global or otherwise).
    The best solution I've managed to come up with so far is use at least 1 GTT to store a mapping of current FAMILY_IDs to new FAMILY_IDs, then use the map table to translate the old IDs to new IDs during the copy phase.
    DROP TABLE id_map;
    CREATE global TEMPORARY TABLE ID_MAP
        (   old_id NUMBER,
            new_id NUMBER
        ON COMMIT DELETE ROWS;
    DROP SEQUENCE duck_tree_seq;
    CREATE SEQUENCE duck_tree_seq INCREMENT BY 1
        START WITH 208;
    create or replace procedure ADD_DUCK_WITH_DESCENDENTS
          (fName varchar2, lName varchar2, pid number, RootID number) is
        new_id NUMBER;
    begin
        -- Create new Ancestor
        insert into duck_tree values (fname, lname, duck_tree_seq.nextval, pid)
        returning family_id into new_id;
        -- Add root mapping
        insert into id_map values (rootid, new_id);
        -- Map lineage
        INSERT INTO id_map
        WITH t AS
             SELECT d.*
               FROM duck_tree d
              WHERE level <> 1 -- exclude root ancestor
            CONNECT BY d.parent_id = PRIOR d.family_id
              START WITH d.first_name = 'Grandma'
         SELECT family_id, DUCK_TREE_SEQ.nextval newid FROM t;
        -- Copy descendents
        insert into duck_tree (
            first_name,
            last_name,
            family_id,
            parent_id)
        WITH t AS
            (SELECT d.*
               FROM duck_tree d
              WHERE level <> 1 -- exclude root ancestor
            CONNECT BY d.parent_id = PRIOR d.family_id
              START WITH d.first_name = 'Grandma'
         SELECT t.first_name
              , t.last_name
              , m1.NEW_ID
              , m2.NEW_ID
           FROM t
        JOIN id_map m1
             ON t.family_id = m1.old_id
        LEFT JOIN id_map m2
             ON t.parent_id = m2.old_id;
        -- Clear out the map table
        delete from id_map;
    end;
    call add_duck_with_descendents('Grandpa','Duck',null,200);
    /

  • How to use i for if condition in a for i in loop?

    Hi friends,
    I have a question on how to use i for IF condition in a loop, in order to get an efficient programming and results. Here is outlined SQL:
    cursor is
    select c1,c2,c3 from table1; -- 100 rows returned.
    open cursor
    loop
    fetch c1,c2,c3 into v1,v2,v3;
    for i in 1..3 loop
    if 'v'||i between 90 and 100 then
    v_grade := 'Excellent';
    elsif 'v'||i between 80 and 89 then
    elsif 'v'||i between 50 and 59 then
    end if;
    end loop;
    close cursor;
    This way, I don't need to use a lot of if..then for hard code v1,v2,v3,.... actually I have more v..
    But Oracle gave an error of this usage of 'if 'v'||i' or 'v'||to_char(i).
    Thanks for any advice in advance!

    user508774 wrote:
    Thanks for comments and advices. But I didn't get your inputs clearly. Are you saying I don't need to use PL/SQL to achieve this?Correct. Ronel and John showed you the basic approaches. SQL is not a mere I/O language for making read and write calls. It is a very capable, flexible and powerful language. One can solve a problem with a few lines of SQL code, that will take 100's of lines of PL/SQL or Java code.
    So do not underestimate what can be done in SQL.
    v_cmd := 'UPDATE parts_categ_counts SET w1='||v1||', w2='||v2||...||v9||' WHERE seq='||vseq||';
    EXECUTE IMMEDIATE v_cmd;This code is also wrong. Besides the fact that there is no need for dynamic SQL, this approach creates a brand new SQL statement each loop iteration.
    SQL is source code. It needs to be parsed (compiled). The end result is an executable program that is called a cursor. This cursor needs to be stored in server memory (the SQL Shared Pool in the SGA).
    The problem with your code is that it is slow and expensive - it generates lots of unique SQL statements that need CPU for parsing and server memory for storage.
    These add up to a very significant performance overhead. That is the wrong approach. The correct approach is the same one that you would use in any other programming language.
    Let's say you need to use Java to process a bunch of CSV files - exact same CSV layout used by each file. A file needs to be read, processed, and a log file created.
    Will you write a Java program that loops through the files, for each file found, write a Java program for processing that file, compile it, then execute it?
    Or would you write a Java program that takes the name of the file as input, and then process that file and writes the log file?
    The 2nd approach provides a program that can process any of those CSV files - one simply needs to pass the filename as an input parameter.
    Your code and approach use the 1st method. Not the 2nd. And that is why it is wrong.
    To create a SQL program with parameters is done by using bind variables. Instead of
    v_cmd := 'UPDATE parts_categ_counts SET w1='||v1||', w2='||v2||...||v9||' WHERE seq='||vseq||';
    The following SQL source code should be created:
    v_cmd := 'UPDATE parts_categ_counts SET w1=:v1, w2=:v2 ..., w9=:v9 WHERE seq= :vseq';
    The tokens with the colon prefix (such as :v1), are bind variables. Think of these as the parameters to the SQL cursor.
    The server parses this SQL into a cursor. You can now execute the same cursor over and over again, using different bind variables. (just like the 2nd approach above that one would use in Java)
    In PL/SQL, this is made even easier as you can code native SQL code with PL/SQL code and use PL/SQL variables in it. The PL/SQL compiler is clever enough to do the SQL parsing, variable binding, and cursor execution for you. So in PL/SQL, you would use:
    UPDATE parts_categ_counts SET w1=v1, w2=v2 ..., w9=v9 WHERE seq= vseq;
    Where v1 and the others are PL/SQL variables.
    That all said - PL/SQL is only used for data crunching, when the processing of data is too complex for the SQL language to deal with. And this is very seldom the case.
    The main reason for using PL/SQL it to provide processing flow control, conditional processing and error handling, for SQL code. As the SQL language does not have these features.

  • Problem with SQLJ

    I am using SQLJ but cant seem to get the Named Iterators to work.
    // None None
    package db_interface;
    import oracle.jdbc.OracleDriver;
    import oracle.jdbc.*;
    import entity.*;
    import java.sql.SQLException;
    import java.sql.PreparedStatement;
    import java.sql.Statement;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.*;
    import sqlj.runtime.*;
    import oracle.sqlj.runtime.*;
    import sqlj.runtime.ref.DefaultContext;
    #sql public static iterator Employee_Iter
    (int employee_id, String employee_dept, String first_name, String family_name, String login_name, String employee_email);
    public void retrieveEmployee(String username) throws SQLException
    System.out.println("Preparing to insert username: " + username);
    Employee_Iter iter = null;
    #sql [context] iter = { VALUES(comp326_2.retrieveEmployee(:in username)) };
    while (iter.next())
    System.out.println("Employee ID: " + iter.employee_id());
    System.out.println("Employee_Name: " + iter.first_name()
    + " " + iter.family_name());
    iter.close();
    And the program here is fine, and it compiles and run, but i get the error in the program invalid column name, and I am not sure why...
    My schema is this:
    /*==============================================================*/
    /* Table: Employee */
    /*==============================================================*/
    create table Employee
         employee_id INTEGER NOT NULL,
         employee_dept VARCHAR(20) NOT NULL,
         first_name VARCHAR(20),
         family_name VARCHAR(40) NOT NULL,
         login_name VARCHAR(40) NOT NULL,
         employee_email VARCHAR(60) NOT NULL,
         CONSTRAINT PK_Employee PRIMARY KEY (employee_id)
    Now I have tried once and again to get it working...
    But running out of ideas help =)

    Oopsie forgot this:
    create or replace package comp326_2 as
         type ref_cursor is REF CURSOR;
         function retrieveEmployee(username IN varchar) return ref_cursor;
    create or replace package body comp326_2 is
         function retrieveEmployee(username IN VARCHAR) return ref_cursor is
              employee_details ref_cursor;
              user_not_found exception;
         begin
              open employee_details for          
              select * from Employee where login_name = username;
              if employee_details%NOTFOUND then
                   raise user_not_found;
              end if;
              return employee_details;
         exception
              when user_not_found then
                   raise_application_error(-20010, 'User not found!');
         end retrieveEmployee;

  • BUG: Internal compilation error, terminated with a fatal exception

    After downloading the new Oracle JDeveloper 10g production, migrating all my projects, everytime I try to make/rebuild any file or package, I get the following error:
    Internal compilation error, terminated with a fatal exception
    This happens if use either JAVAC or OJC.
    Regards,
    Yaniv Kunda

    I think the error reporting is wrong, since dbMessages.java is a translated SQLJ file, and the specified method exists in the SQLJ file around that line number - and not in the java file resulting from the translation.
    Note that line 2958, in the SQLJ file, was the simple MessageHeader.Iter messageHeaderIter; line.
    The definition of this class, is in a SQLJ file, which content is:
    package telemessage.db.impl.iterators;
    import java.sql.Timestamp;
    * Contains an iterator for viewing message headers in folder view.
    public class MessageHeader {
         #sql public static iterator Iter (
              long          MESSAGE_ID,
              String          RANDOM_KEY,
              Timestamp     DATE_SENT_BY_USER,
              short          TYPE,
              long          MESSAGE_SIZE,
              int               ATTACHMENT_COUNT,
              String          SUBJECT,
              String          FROM_DISPLAY,
              String          TO_DISPLAY,
              Long          POLLER_ACCOUNT_ID,
              long          DEVICE_ID,
              short          DEVICE_STATE,
              short          DEVICE_BLOCKING,
              Integer          DEVICE_BLOCKED_FROM,
              Integer          DEVICE_BLOCKED_UNTIL,
              short          DEVICE_TYPE,
              byte          DEVICE_SUB_TYPE,
              String          DEVICE_VALUE,
              String          DEVICE_DESCRIPTION,
              boolean          READ,
              String          TEXT,
              boolean          ESCALATING,
              int               DESCENDANT_COUNT,
              short          STATUS
    }I have pasted the original source of this method, both before and after SQLJ translation.
    before:
         public static MessageEntries getMessageDescendants(DBThread db, long messageID, boolean isRoot)
                   throws SQLException, DBException {
              List messagesList = new ArrayList();
              MessageHeader.Iter messageHeaderIter;
              #sql [db.ctx] messageHeaderIter = {
                   select
                        m.ID MESSAGE_ID,
                       m.RANDOM_KEY,
                        m.DATE_SENT_BY_USER,
                        m.TYPE,
                        m.MESSAGE_SIZE,
                        m.ATTACHMENT_COUNT,
                        m.SUBJECT,
                        m.FROM_DISPLAY,
                        m.TO_DISPLAY,
                        m.POLLER_ACCOUNT_ID,
                        -1 DEVICE_ID,
                        -1 DEVICE_STATE,
                        -1 DEVICE_BLOCKING,
                        null DEVICE_BLOCKED_FROM,
                        null DEVICE_BLOCKED_UNTIL,
                        -1 DEVICE_TYPE,
                        -1 DEVICE_SUB_TYPE,
                        null DEVICE_VALUE,
                        null DEVICE_DESCRIPTION,
                       1 READ,
                             select     tm.TEXT
                             from     TEXT_MESSAGES tm
                             where     
                                       tm.MESSAGE_ID = m.ID
                                  and     rownum = 1
                        ) TEXT,
                        0 ESCALATING,
                        0 DESCENDANT_COUNT,
                        -1 STATUS
                   from
                        MESSAGES m
                   start with
                        m.ID = decode(:isRoot,
                             1,:messageID,
                                  select          m2.ID
                                  from          MESSAGES m2
                                  where          m2.ORIGINAL_MESSAGE_ID is null
                                  start with     m2.ID = :messageID
                                  connect by     m2.ID = prior m2.ORIGINAL_MESSAGE_ID
                   connect by
                        prior m.ID = m.ORIGINAL_MESSAGE_ID
                   order by
                        m.DATE_SENT_BY_USER desc
              while (messageHeaderIter.next()) {
                   MessageEntry messageEntry = new MessageEntry(
                        messageHeaderIter.FROM_DISPLAY(),
                        messageHeaderIter.TO_DISPLAY(),
                        messageHeaderIter.SUBJECT(),
                        messageHeaderIter.MESSAGE_SIZE(),
                        messageHeaderIter.RANDOM_KEY(),
                        messageHeaderIter.MESSAGE_ID(),
                        messageHeaderIter.DATE_SENT_BY_USER(),
                        messageHeaderIter.TYPE(),
                        messageHeaderIter.ATTACHMENT_COUNT(),
                        null,   // pollerAccount
                        0,          // senderID
                        null,   // sentFromDevice
                        messageHeaderIter.READ(),
                        messageHeaderIter.TEXT(),
                        messageHeaderIter.ESCALATING(),
                    0,          // descendantsCount - not relevant for this query
                        messageHeaderIter.STATUS()
                   messagesList.add(messageEntry);
                   db.checkTimeout(); // potential time-consuming loop
              }//while
              messageHeaderIter.close();
            long[] allEntriesMessageIDs = new long[messagesList.size()];
              for (int i = 0; i < allEntriesMessageIDs.length; i++) {
                   allEntriesMessageIDs[i] = ((MessageEntry)messagesList.get(i)).getMessageContainerID();
              return new MessageEntries(messagesList, 0, allEntriesMessageIDs, null);
         } // getMessageDescendants
    after:
         public static MessageEntries getMessageDescendants(DBThread db, long messageID, boolean isRoot)
                   throws SQLException, DBException {
              List messagesList = new ArrayList();
              MessageHeader.Iter messageHeaderIter;
              /*@lineinfo:generated-code*//*@lineinfo:2959^3*/
    //  #sql [db.ctx] messageHeaderIter = { select
    //                      m.ID MESSAGE_ID,
    //                     m.RANDOM_KEY,
    //                      m.DATE_SENT_BY_USER,
    //                      m.TYPE,
    //                      m.MESSAGE_SIZE,
    //                      m.ATTACHMENT_COUNT,
    //                      m.SUBJECT,
    //                      m.FROM_DISPLAY,
    //                      m.TO_DISPLAY,
    //                      m.POLLER_ACCOUNT_ID,
    //                      -1 DEVICE_ID,
    //                      -1 DEVICE_STATE,
    //                      -1 DEVICE_BLOCKING,
    //                      null DEVICE_BLOCKED_FROM,
    //                      null DEVICE_BLOCKED_UNTIL,
    //                      -1 DEVICE_TYPE,
    //                      -1 DEVICE_SUB_TYPE,
    //                      null DEVICE_VALUE,
    //                      null DEVICE_DESCRIPTION,
    //                     1 READ,
    //                           select     tm.TEXT
    //                           from     TEXT_MESSAGES tm
    //                           where     
    //                                     tm.MESSAGE_ID = m.ID
    //                                and     rownum = 1
    //                      ) TEXT,
    //                      0 ESCALATING,
    //                      0 DESCENDANT_COUNT,
    //                      -1 STATUS
    //                 from
    //                      MESSAGES m
    //                 start with
    //                      m.ID = decode(:isRoot,
    //                           1,:messageID,
    //                                select          m2.ID
    //                                from          MESSAGES m2
    //                                where          m2.ORIGINAL_MESSAGE_ID is null
    //                                start with     m2.ID = :messageID
    //                                connect by     m2.ID = prior m2.ORIGINAL_MESSAGE_ID
    //                 connect by
    //                      prior m.ID = m.ORIGINAL_MESSAGE_ID
    //                 order by
    //                      m.DATE_SENT_BY_USER desc
      sqlj.runtime.ConnectionContext __sJT_connCtx = db.ctx;
      if (__sJT_connCtx == null) sqlj.runtime.error.RuntimeRefErrors.raise_NULL_CONN_CTX();
      sqlj.runtime.ExecutionContext __sJT_execCtx = __sJT_connCtx.getExecutionContext();
      if (__sJT_execCtx == null) sqlj.runtime.error.RuntimeRefErrors.raise_NULL_EXEC_CTX();
      boolean __sJT_1 = isRoot;
      long __sJT_2 = messageID;
      long __sJT_3 = messageID;
      synchronized (__sJT_execCtx) {
        sqlj.runtime.profile.RTStatement __sJT_stmt = __sJT_execCtx.registerStatement(__sJT_connCtx, dbMessages_SJProfileKeys.getKey(0), 39);
        try
          __sJT_stmt.setBoolean(1, __sJT_1);
          __sJT_stmt.setLong(2, __sJT_2);
          __sJT_stmt.setLong(3, __sJT_3);
          sqlj.runtime.profile.RTResultSet __sJT_result = __sJT_execCtx.executeQuery();
          messageHeaderIter = new MessageHeader.Iter(__sJT_result);
        finally
          __sJT_execCtx.releaseStatement();
    /*@lineinfo:user-code*//*@lineinfo:3008^3*/
              while (messageHeaderIter.next()) {
                   MessageEntry messageEntry = new MessageEntry(
                        messageHeaderIter.FROM_DISPLAY(),
                        messageHeaderIter.TO_DISPLAY(),
                        messageHeaderIter.SUBJECT(),
                        messageHeaderIter.MESSAGE_SIZE(),
                        messageHeaderIter.RANDOM_KEY(),
                        messageHeaderIter.MESSAGE_ID(),
                        messageHeaderIter.DATE_SENT_BY_USER(),
                        messageHeaderIter.TYPE(),
                        messageHeaderIter.ATTACHMENT_COUNT(),
                        null,   // pollerAccount
                        0,          // senderID
                        null,   // sentFromDevice
                        messageHeaderIter.READ(),
                        messageHeaderIter.TEXT(),
                        messageHeaderIter.ESCALATING(),
                    0,          // descendantsCount - not relevant for this query
                        messageHeaderIter.STATUS()
                   messagesList.add(messageEntry);
                   db.checkTimeout(); // potential time-consuming loop
              }//while
              messageHeaderIter.close();
            long[] allEntriesMessageIDs = new long[messagesList.size()];
              for (int i = 0; i < allEntriesMessageIDs.length; i++) {
                   allEntriesMessageIDs[i] = ((MessageEntry)messagesList.get(i)).getMessageContainerID();
              return new MessageEntries(messagesList, 0, allEntriesMessageIDs, null);
         } // getMessageDescendants

  • ADF Tree creation

    Hi,
    I am creating a Tree structure from an iterator whose SQL has a Variable, I am setting the Variable through VariableValueManager, I want to execute the query with the SQL.
    But the SQL is not getting updated, i am unable to find an API which propagates the set value. Code is below
    FacesContext fctx = FacesContext.getCurrentInstance();
    Application fapp = fctx.getApplication();
    JUFormBinding adfbc =
    (JUFormBinding)fapp.createValueBinding("#{bindings}").getValue(fctx);
    DCIteratorBinding iter =
    adfbc.findIteratorBinding("Material1Iterator");
    ViewObjectImpl matDetNew = (ViewObjectImpl) iter.getViewObject();
    VariableValueManager valManNew = matDetNew.getVariableManager();
    valManNew.setVariableValue("P_MATID","PX0500005-APT");
    iter.executeQuery();
    the query is
    SELECT * FROM (Select Comp_Mat_Id Mat_Id, Mat_Id Comp_Mat_Id,
    child_level
    From (Select Level child_level,
    a.Mat_Id,
    a.Comp_Mat_Id,
    (Select Mat.Description
    From Materials Mat
    Where Mat.Mat_Id = a.Mat_Id) || ' (' || a.Comp_Qty || ')' Mat_Desc
    From Material_Components a
    Start With a.Mat_Id = :P_MATID
    Connect By Prior a.Comp_Mat_Id = a.Mat_Id))
    Kindly Help
    Thanks in Advance
    Vishnu

    Hi,
    with JDeveloper 10.1.3 VO that have a variable binding are exposed as setRowWithParams (or similar) in the data control palette. This means you can execute it from the middle tier without the need to drill down into the BC code.
    Also, don't cast to ViewObjectImpl but ViewObject, which is the interface. View Objects expose methods to set bind variables in the query.
    Frank

  • [SQLJ] Context Problem

    Hi all,
    I am working on Oracle 9i and I compile with the Oracle Console Entreprise Manager.
    From an instance baseA, I am looking for getting values from other instance baseB :
    Code :
    DefaultContext connB = Oracle.getConnection("jdbc:oracle:thin:@ipServer:1521:baseB","user","pwd");
    DefaultContext connA = Oracle.getConnection("jdbc:oracle:thin:@ipServer:1521:baseA","user","pwd");
    try {
         String result = "";
         #sql [[connB ]] { SELECT lib INTO :result FROM TAB_MESURE WHERE id = 4 };
         RETURN result;
    finally {
         connB.close();
         connA.close();
    When compiling, this error is displayed
    Warning: Impossible de vérifier la clause WHERE. Erreur renvoyée par la base de données : ORA-00942: Table ou vue inexistante (french)
    ORA-00942: Table or view doest not exist
    - all tns are corectly set up
    - Within the same instance,all requests are OK (without using of context)
    - I tried diferent connection method wothout success (Oracle.connect, DefaultContext.setDefaultContext, )
    Thanks for your help
    Merci pour votre aide
    Edited by: user11166064 on 14 mai 2009 02:41
    Edited by: user11166064 on 14 mai 2009 02:49

    Ok,
    So i re-formulate my request, here the acual code executed :
    h5. 1- Java code :
    import java.sql.*;
    import sqlj.runtime.ref.DefaultContext;
    import oracle.sqlj.runtime.Oracle;
    import sqlj.runtime.ExecutionContext;
    #sql iterator MyIter2 (Integer elt_id, String elt_lst_code, String elt_lib, Integer elt_actif);
    public class TestInsert {
    public static void test() throws Exception {
              DefaultContext connB = Oracle.getConnection("jdbc:oracle:thin:@ipServer:1521:baseB","user","pwd");
              DefaultContext connA = Oracle.getConnection("jdbc:oracle:thin:@ipServer:1521:baseA","user","pwd");
              MyIter2 iter;
              Integer ident;
              String listCode;
              String lib;
              String actif;
              try {
                   #sql [[connB]] iter={ select elt_id, elt_lst_code, elt_lib, elt_actif from baseB.<user>.ELT elt_elt_id is NULL };
                   while (iter.next()) {
                        ident =      iter.elt_id();
                        listCode =      iter.elt_lst_code();
                        lib =           iter.elt_lib();
                        actif =          String.valueOf(iter.elt_actif());
                        #sql [connA]] { insert into BIBLIO_0 (ID, LIBELLE) values (:ident, :lib) };
                   #sql [[connA]] { COMMIT};
              } finally {
                   connB.close();
                   connA.close();
    h5. 2- Loadjava
    loadjava -u user/pwd@connA -v -resolve TestInsert.java
    it returns a warning :
    Impossible to check SQL instruction
    +#sql [connB] iter={ select elt_id, elt_lst_code, elt_lib, elt_actif from baseB.<user>.ELT elt_elt_id is NULL };+
    h5. 3- Create and execute stored procedure
    I connect to baseA through sql*plus and execute the command :
    CREATE OR REPLACE PROCEDURE SP_TESTINSERT AS LANGUAGE JAVA  NAME 'TestInsert.test()';
    EXECUTE SP_TESTINSERT;
    I've got the errors :
    ORA-29532: java call terminated by uncaught java exception :
    java.sql.SQLException: ORA-00903: invalid table name
    ORA-06512: at "BASEB.TESTINSERT", ligne 0
    ORA-06512: at ligne 1
    I've changed :
    +#sql [[connB]] iter={ select elt_id, elt_lst_code, elt_lib, elt_actif from baseB.<user>.ELT elt_elt_id is NULL };+
    to
    +#sql [[connB]] iter={ select elt_id, elt_lst_code, elt_lib, elt_actif <user>.ELT elt_elt_id is NULL };+
    but during the compilation (loadjava) I have :
    ORA-29535: source requires recompilation
    TestInsert:23: Impossible to check SQL interrogation. ORA-00903: invalid table name
    #sql [connGeochim] iter={ select elt_id, elt_lst_code, elt_lib, elt_actif from
    <user>.ELT elt_elt_id is NULL };
    ^
    <no file>: Processing source TestInsert encountered sqlj translation failed.
    Info: 2 errors
    The following operations failed
    source TestInsert: resolution
    exiting : Failures occurred during processing
    thanks

  • Select4

    SQL > select4;
    select4
    ERROR at line 1:
    ORA-24333: zero iteration count
    SQL > exec execute immediate 'select4';
    BEGIN execute immediate 'select4'; END;
    ERROR at line 1:
    ORA-00900: invalid SQL statement
    ORA-06512: at line 1
    question: why do I get "ORA-24333: zero iteration count" above ?
    shouldn't it also be "ORA-00900: invalid SQL statement" ?

    If it was server error I'd suspect an »after server error« trigger should fire. But the following shows that it doesn't:
    SQL> create or replace trigger after_server_error_trg
      2     after servererror on database
      3  begin
      4     raise_application_error (-20003, sqlerrm);
      5  end after_server_error_trg;
      6  /
    Trigger created.
    /*    Test it: */
    SQL>
    SQL> select to_number('x') from dual
      2  /
    select to_number('x') from dual
    ERROR at line 1:
    ORA-00604: error occurred at recursive SQL level 1
    ORA-20003: ORA-0000: normal, successful completion
    ORA-06512: at line 2
    ORA-01722: invalid number
    SQL>
    SQL> select#;
    select#
    ERROR at line 1:
    ORA-24333: zero iteration countMy vote therefore goes for a sql*plus internal exception handling .... the statement presumably never reaches the server.

  • Jpub generated collections and SLOW RETRIEVAL

    Oracle 8.1.6 EE
    SQLJ/JDBC 8.1.7
    I use jpub to generate oracle specific usertypes (i.e) -usertypes=oracle. All the classes generate fine and I can use them in my code. The problem is that when I try to use the getArray() or getElement() methods from the generated collection class, it is REALLY SLOW. On the order of two minutes to retrieve 30 records. Using a test harness in SQLPLUS the retrieval is fast. On the order of milliseconds.
    I call a stored procedure that returns the array of objects.
    The object looks like this ...
    CREATE OR REPLACE TYPE account_item AS OBJECT
    id number,
    name varchar2(200),
    tag_id varchar2(50),
    state varchar2(20),
    zip varchar2(20),
    primary_contact varchar2(200),
    phone varchar2(20),
    status varchar2(50),
    broker varchar(200)
    The collection type looks like ...
    CREATE OR REPLACE TYPE account_item_list AS TABLE OF account_item
    Does anyone from the jdbc/sql group have any idea why this would be happening ??
    Thanks.
    Joe
    null

    Ad (1): No idea. Retrieving 9 records each with a nested table of 30 items is practically instantaneous. (Using 9.0.1 client and server and OCI.) Are you using thin or OCI JDBC? Maybe there is an issue connecting between an 8.1.7 client and a 8.1.6 server? (The 8.1.6 JPub runtime had bad performance. 8.1.7 is much improved and should be about equal with 9.0.1.)
    Ad (2): With the SQL definitions of account_item and account_item_list and the following table in the scott/tiger schema:
    create table accounts (id number, account account_item_list)
    nested table account store as accounts_nested_table;
    you can run JPublisher as follows:
    jpub -user=scott/tiger -sql=account_item:AccountItem,account_item_list:AccountItemList
    Then use the following program TestAccount.sqlj (can't resist SQLJ here):
    import java.sql.SQLException;
    import oracle.sqlj.runtime.Oracle;
    import sqlj.runtime.ResultSetIterator;
    public class TestAccount
    { #sql public static iterator Iter (int id, AccountItemList account);
    public static void main(String[] args) throws SQLException
    { Oracle.connect("jdbc:oracle:oci:@","scott","tiger");
    Iter it;
    #sql it = { select id, account from accounts };
    while (it.next())
    printList(it.id(), it.account().getArray());
    it.close(); Oracle.close();
    private static void printList(int id, AccountItem[] items) throws SQLException
    { System.out.print("List "+id+" [");
    for (int i=0; i<items.length; i++)
    { System.out.print(items[i].getId());
    if (i < items.length-1 ) System.out.print(",");
    System.out.println("]");
    Compile everything with:
    sqlj *.java *.sqlj
    And then run:
    java TestAccount

  • 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.

  • Query update on each iteration problem (MS SQL Sever / ODBC / Native Driver

    Hello,
    I�ve been working to learn some Java and now JDBC over the past 10 or so months.
    I think I have a general understanding of how to perform queries and work with data using JDBC. However, I�ve run into a problem. I�m trying to do a query of a set of data in a database based on the value of a status column. I want to loop over the messages and perform various functions with the data then update their status in the database. It�s preferable to do these 250 to 1000 rows at a time, but no more and no less.
    I�m connecting to MS SQL Server 2000, currently with ODBC. I�ve also tried it with the Java SQL Server 2000 drivers provided by Microsoft with the same results.
    I�ve found that I can do a one table query and loop though it with a while (rs.next()) {�} and run an Update statement with executeUpdate on each iteration without any problems, no matter the number of rows returned in query.
    I have not been able to use the updateString and updateRow inside the while loop. I keep getting errors like this at the line with the updateRow():
    Exception in thread "main" java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC]Row update failed.
    This occurs no mater how many rows I select, 1 or more.
    The real problem I�ve been having is that the query I need to loop though joins across several tables and returns some rows from some of those tables. This only seems to work when I query for 38 or less selected rows and I use an Update statement with executeUpdate on each iteration. The updateString and updateRow methods never work. Any number of rows selected greater than 38 causes a deadlock where the Update is waiting for the select to compete on the server and the Update can�t proceed until the Select is complete.
    As I stated above I�ve tried both ODBC and the native SQL Server driver with the same results. I have not tried any other databases, but that�s moot as my data is already in MS SQL.
    Questions:
    How can I avoid or get around this 38 row limit without selecting each row, one at a time?
    What am I doing wrong with the updateString and updateRow?
    Is there a better approach that anyone can suggest?
    Here�s some sample code with the problem:
    import java.sql.*;
    public class db1{
         public static void main(String[] args) throws Exception{
              Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
              String url = "jdbc:odbc:eBrochure_live";
              Connection con = DriverManager.getConnection(url, "sa", "d3v3l0p");
              Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
              Connection con = DriverManager.getConnection("jdbc:microsoft:sqlserver://dcm613u2\\dcm613u2_dev:1433", "sa", "d3v3l0p");
              Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
              Statement stmt2 = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
              stmt.executeUpdate("USE [myDatabase]");
              stmt2.executeUpdate("USE [myDatabase]");
              String qGetMessages = "SELECT TOP 250 t1.messageUUID, t1.subjectHeader, t2.emailAddress as toAddress " +
              "FROM APP_Messages as t1 JOIN APP_addressBook_contacts as t2 " +
              "     On t1.toContactID = t2.contactID " +
              "WHERE t1.statusID = 'queued'";
              ResultSet rs = stmt.executeQuery(qGetMessages);
              while (rs.next()) {
                   String messageUUID = rs.getString("messageUUID");
                   String subjectHeader = rs.getString("subjectHeader");
                   System.out.println(messageUUID + " " + subjectHeader);
                   String updateString = "UPDATE APP_Messages " +
                        "SET statusID = 'sent' " +
                        "WHERE messageUUID = '" + messageUUID + "' ";
                   stmt2.executeUpdate(updateString);
              con.close();
    Thanks for the help,
    Doug Hughes

    // sorry, ps.close() should be outside of if condition
    String sql = "UPDATE APP_Messages SET statusID = 'sent' WHERE messageUUID = ?";
    Statement statement = con.createStatement();
    PreparedStatement ps = con.prepareStatement(sql);
    ResultSet rs = statement.executeQuery("your select SQL");
    if ( rs.next() )
    ps.clearParameters();
    ps.setString(1, rs.getString("your column name"));
    ps.executeUpdate();
    ps.close();
    rs.close();
    statement.close();

  • Plsql/sql iterative delete query help

    I need some help.....I have 4 tables joined by TRANSACTION_ID
    TRANSACTIONS Table
    TRANSACTION_ID NUMBER(20)
    USER_ID NUMBER(20)
    EXPIRY TIMESTAMP
    TX_ATTEMPTS Table
    TX_ATTEMPT_ID NUMBER(20)
    TRANSACTION_ID NUMBER(20)
    TX_ELEMENTS
    TX_ELEMENT_ID NUMBER(20)
    TRANSACTION_ID NUMBER(20)
    CIDENT
    CIDENT_ID NUMBER(20)
    Each TRANSACTION has an associated
    USER_ID - ID identitying a unique person
    EXPIRY - Timestamp to indicate when the TRANSACTION expires in the system.
    A USER_ID can have many TRANSACTIONS associated with it.
    I'm looking for some PL/SQL that will accept a variable (RETAIN_NUM) indicating the number of most recent transactions that need to be retained for all users in the database.
    For example if the RETAIN_NUM is 5, the sql should do the following:
    1) Retain the 5 most recent transactions in the TRANSACTIONS table for each USER_ID (including associated entries in the other 3 tables also). All older entries for each USER_ID should be deleted from the TRANSACTIONS table (including any associated entries in the other 3 tables also).
    2) Before deleting the data in all the tables I want to export it, ideally using expdp in a single execution.
    Is there anyone that could please help me with either part of this??
    Edited by: user12213281 on Jun 4, 2013 3:47 PM

    Thanks for your comments. The way the system works is complicated and I'm not sure how to tackle the overall delete...that is why I have asked for some help.
    I have examined the schema structure again and have identified some useful points to make it easier.
    Each of the tables have several other columns but I had stripped them down for the purpose of making this query easier to understand. Luckily each of the tables in the schema do have a CIDENT_ID column with a cascade delete constraint from the CIDENT table. This works most simply for the TX_ELEMENTS table so I don't think I will need to include that table specifically in any delete. Unfortunately at this time I am not able to create any other new relationships between the tables.
    The tables involved now are:
    TRANSACTIONS Table
    CIDENT_ID NUMBER(20)
    TRANSACTION_ID NUMBER(20)
    USER_ID NUMBER(20)
    EXPIRY TIMESTAMP
    TX_ATTEMPTS Table
    CIDENT_ID NUMBER(20)
    TX_ATTEMPT_ID NUMBER(20)
    TRANSACTION_ID NUMBER(20)
    CIDENT Table
    CIDENT_ID NUMBER(20)
    The difficulty comes with the TRANSACTIONS and TX_ATTEMPTS tables.
    Each TRANSACTIONS and TX_ATTEMPTS entry has a completely separate CIDENT entry. What I was thinking I need to do is:
    1) Generate a list of TRANSACTION_IDs and corresponding CIDENT_IDs from the TRANSACTIONS table that are the most recent "retain_num" entries for each USER_ID (using EXPIRY_DTM).
    2) Then generate a list of CIDENT_IDs from the TX_ATTEMPTS table based on the TRANSACTION_IDs from 1) above
    3) Delete the CIDENT entries using the CIDENT_IDs obtained from 1) and 2) above.
    These individually may not be so bad but I don't know how to combine them....
    Any pointers would really be greatly appreciated...

  • Iterating through the result of a multiple row sql statement

    Hi all,
    I would like to access the results of a multiple row sql-statement. However I can't find out how to do this, can you help me here?
    I have tried using the "node-set" functions in xpath, but I can't seem to get it right.
    How should I approach this scenario?
    Sincerely
    Kim

    The jdbc service has the option of returning xml back to you ...if you do it this way then you can interogate the xml

  • Error while executing a sql query for select

    HI All,
    ORA-01652: unable to extend temp segment by 128 in tablespace PSTEMP i'm getting this error while i'm executing the sql query for selecting the data.

    I am having 44GB of temp space, while executing the below query my temp space is getting full, Expert please let us know how the issue can be resolved..
    1. I dont want to increase the temp space
    2. I need to tune the query, please provide your recomendations.
    insert /*+APPEND*/ into CST_DSA.HIERARCHY_MISMATCHES
    (REPORT_NUM,REPORT_TYPE,REPORT_DESC,GAP,CARRIED_ITEMS,CARRIED_ITEM_TYPE,NO_OF_ROUTE_OF_CARRIED_ITEM,CARRIED_ITEM_ROUTE_NO,CARRIER_ITEMS,CARRIER_ITEM_TYPE,CARRIED_ITEM_PROTECTION_TYPE,SOURCE_SYSTEM)
    select
    REPORTNUMBER,REPORTTYPE,REPORTDESCRIPTION ,NULL,
    carried_items,carried_item_type,no_of_route_of_carried_item,carried_item_route_no,carrier_items,
    carrier_item_type,carried_item_protection_type,'PACS'
    from
    (select distinct
    c.REPORTNUMBER,c.REPORTTYPE,c.REPORTDESCRIPTION ,NULL,
    a.carried_items,a.carried_item_type,a.no_of_route_of_carried_item,a.carried_item_route_no,a.carrier_items,
    a.carrier_item_type,a.carried_item_protection_type,'PACS'
    from CST_ASIR.HIERARCHY_asir a,CST_DSA.M_PB_CIRCUIT_ROUTING b ,CST_DSA.REPORT_METADATA c
    where a.carrier_item_type in('Connection') and a.carried_item_type in('Service')
    AND a.carrier_items=b.mux
    and c.REPORTNUMBER=(case
    when a.carrier_item_type in ('ServicePackage','Service','Connection') then 10
    else 20
    end)
    and a.carrier_items not in (select carried_items from CST_ASIR.HIERARCHY_asir where carried_item_type in('Connection') ))A
    where not exists
    (select *
    from CST_DSA.HIERARCHY_MISMATCHES B where
    A.REPORTNUMBER=B.REPORT_NUM and
    A.REPORTTYPE=B.REPORT_TYPE and
    A.REPORTDESCRIPTION=B.REPORT_DESC and
    A.CARRIED_ITEMS=B.CARRIED_ITEMS and
    A.CARRIED_ITEM_TYPE=B.CARRIED_ITEM_TYPE and
    A.NO_OF_ROUTE_OF_CARRIED_ITEM=B.NO_OF_ROUTE_OF_CARRIED_ITEM and
    A.CARRIED_ITEM_ROUTE_NO=B.CARRIED_ITEM_ROUTE_NO and
    A.CARRIER_ITEMS=B.CARRIER_ITEMS and
    A.CARRIER_ITEM_TYPE=B.CARRIER_ITEM_TYPE and
    A.CARRIED_ITEM_PROTECTION_TYPE=B.CARRIED_ITEM_PROTECTION_TYPE
    AND B.SOURCE_SYSTEM='PACS'
    Explain Plan
    ==========
    Plan
    INSERT STATEMENT ALL_ROWSCost: 129 Bytes: 1,103 Cardinality: 1                                                        
         20 LOAD AS SELECT CST_DSA.HIERARCHY_MISMATCHES                                                   
              19 PX COORDINATOR                                              
                   18 PX SEND QC (RANDOM) PARALLEL_TO_SERIAL SYS.:TQ10002 :Q1002Cost: 129 Bytes: 1,103 Cardinality: 1                                         
                        17 NESTED LOOPS PARALLEL_COMBINED_WITH_PARENT :Q1002Cost: 129 Bytes: 1,103 Cardinality: 1                                    
                             15 HASH JOIN RIGHT ANTI NA PARALLEL_COMBINED_WITH_PARENT :Q1002Cost: 129 Bytes: 1,098 Cardinality: 1                               
                                  4 PX RECEIVE PARALLEL_COMBINED_WITH_PARENT :Q1002Cost: 63 Bytes: 359,283 Cardinality: 15,621                          
                                       3 PX SEND BROADCAST PARALLEL_TO_PARALLEL SYS.:TQ10001 :Q1001Cost: 63 Bytes: 359,283 Cardinality: 15,621                     
                                            2 PX BLOCK ITERATOR PARALLEL_COMBINED_WITH_CHILD :Q1001Cost: 63 Bytes: 359,283 Cardinality: 15,621                
                                                 1 MAT_VIEW ACCESS FULL MAT_VIEW PARALLEL_COMBINED_WITH_PARENT CST_ASIR.HIERARCHY :Q1001Cost: 63 Bytes: 359,283 Cardinality: 15,621           
                                  14 NESTED LOOPS ANTI PARALLEL_COMBINED_WITH_PARENT :Q1002Cost: 65 Bytes: 40,256,600 Cardinality: 37,448                          
                                       11 HASH JOIN PARALLEL_COMBINED_WITH_PARENT :Q1002Cost: 65 Bytes: 6,366,160 Cardinality: 37,448                     
                                            8 BUFFER SORT PARALLEL_COMBINED_WITH_CHILD :Q1002               
                                                 7 PX RECEIVE PARALLEL_COMBINED_WITH_PARENT :Q1002Cost: 1 Bytes: 214 Cardinality: 2           
                                                      6 PX SEND BROADCAST PARALLEL_FROM_SERIAL SYS.:TQ10000 Cost: 1 Bytes: 214 Cardinality: 2      
                                                           5 INDEX FULL SCAN INDEX CST_DSA.IDX$$_06EF0005 Cost: 1 Bytes: 214 Cardinality: 2
                                            10 PX BLOCK ITERATOR PARALLEL_COMBINED_WITH_CHILD :Q1002Cost: 63 Bytes: 2,359,224 Cardinality: 37,448                
                                                 9 MAT_VIEW ACCESS FULL MAT_VIEW PARALLEL_COMBINED_WITH_PARENT CST_ASIR.HIERARCHY :Q1002Cost: 63 Bytes: 2,359,224 Cardinality: 37,448           
                                       13 TABLE ACCESS BY INDEX ROWID TABLE PARALLEL_COMBINED_WITH_PARENT CST_DSA.HIERARCHY_MISMATCHES :Q1002Cost: 0 Bytes: 905 Cardinality: 1                     
                                            12 INDEX RANGE SCAN INDEX PARALLEL_COMBINED_WITH_PARENT SYS.HIERARCHY_MISMATCHES_IDX3 :Q1002Cost: 0 Cardinality: 1                
                             16 INDEX RANGE SCAN INDEX PARALLEL_COMBINED_WITH_PARENT CST_DSA.IDX$$_06EF0001 :Q1002Cost: 1 Bytes: 5 Cardinality: 1

Maybe you are looking for

  • Checking for new mail icon next to mailbox seems to have disapeared

    After upgrading to OS X Mountain Lion I noticed that the icon next to each mailbox that shows when checking for new mail is not there.  I wonder if anyone else has noticed this, and if they have found a fix?

  • ArrayIndexOutOfBoundsException in JDeveloper

    Hi, I am working with JDeveloper for 11.5.10 CU2. I extended a View object for an LOV and created the relevant substitution for it. It was working fine and when I had to create another substitution it did not allow me to go ahead. On the click of the

  • Sending a smartform output as an attachment in RTF format via E-mail

    Hi all,      I have a scenario in which the output displayed using smartforms is to be sent as a e-mail attachment. Also, the attachment should be a word doc(RTF format). Can you please me with this. Warm Regards, Abhijeet

  • User Decision step- Upon reject, auto-popup text for reason

    In a user decision step, when the user clicks the reject button, open text for rejection reason within the workitem. i have done the following 1) Create a new step 2) Create a task based on SOFM.CREATE 3) Binded  WIOBJECT_ID => (append table) ADHOCOB

  • We are unable to process your request - account activation

    Hi I keep getting this error We are unable to process your request. Please go back to the previous page, or quit your browser and try your request again. I keep clicking on the activation link and then Activate and i keep going around in circles. How