Is there table type object in PL/SQL?

Hi.
What I'm trying to do is, according to the some conditions, aggregate data as an object type( I am not sure that there's a similar thing)
There are 5-6 conditions. then at last join those table type object.
FYI, Here is an example
Company will give bonus to a person who meet these conditions
1. Salary is less than 1000$ - salary table
2. More than 5 persons in his family - staff table
3. gross sale is over 10000$
In PL/SQL Package, I'll get those data as an object type and join those object just like in-line query.
select emp_no
from sal_tbl , staff_tbl, sale_tbl
where sal_tbl = staff_tbl
and sal_tbl = sale_tbl
In my opinion I can get employee list who get bonus. because they meet all conditions.
Reason why bonus condition will be updated continuously. I want to make them easy to maintanence. what if I need to add new conditions. Just add a new procedure that calculate new result and pass as an table type object.
select emp_no
from sal_tbl , staff_tbl, sale_tbl, new_tbl*
where sal_tbl = staff_tbl
and sal_tbl = sale_tbl
and sal_tbl = new_tbl*
Is there any thing just like what I think?
Thanks in advance
Message was edited by: me
allbory
I have read Oracle user guide - Collection, Record, and Cursor. But I can't get anything that I want.
Give me some clues

> In PL/SQL Package, I'll get those data as an object type and join those object just like
in-line query.
Not the best of ideas. If I'm getting what you're saying, you want to use the following approach:
SQL> create or replace type TStrings as table of varchar2(4000);
2 /
Type created.
SQL>
SQL>
SQL> create or replace procedure BadIdea( collection TStrings ) is
2 minVal string(4000);
3 maxVal string(4000);
4 begin
5 -- in the procedure we now run SQLs against the collection
6 select
7 MIN( column_value ) into minVal
8 from TABLE( collection );
9
10 select
11 MAX( column_value ) into maxVal
12 from TABLE( collection );
13 end;
14 /
Procedure created.
SQL> show errors
No errors.
SQL>
SQL>
SQL> -- and then we call this procedure to do our "SQL" processing for us
SQL> declare
2 list TStrings;
3 begin
4 select
5 object_name bulk collect into list
6 from user_objects;
7
8 BadIdea( list );
9 end;
10 /
PL/SQL procedure successfully completed.A collection of objects resides in (non-sharable and expensive) PL/SQL memory. Running SQL, requires the PL/SQL engine copying the data to the SQL engine into a structure and format that the SQL engine will understand.
This is slow. This is expensive. This does not scale.
It makes little sense to copy data from the very fast and hot and good and scalable db buffer cache into an expensive memory structure in the PGA and then run SQLs against that.
> Reason why bonus condition will be updated continuously. I want to make them easy
to maintanence. what if I need to add new conditions. Just add a new procedure that
calculate new result and pass as an table type object.
The way I read your SQL, your new_tbl* requires dynamic SQL. Which means you also need to dynamically cater for the correct column names to join on, to filter on, and to select from.
Also not the best of ideas. Dynamic SQL like that requires a lot of code to deal correctly with bind variables. Lot of exception handling as there can easily be run-time errors as the code itself that is executed in turn creates new dynamic code to execute.
If this is to be truly dynamic, then one approach would be that each rule needs to be executable as a SQL or PL/SQL block. Each rule needs to have an input like an employee number. Each rule needs to returns a boolean like value, saying whether the rule has passed or failed.
Only when all the rules have been passed, can the bonus be allocated.
This will deal fine with the "dynamic rule" requirement. Performance wise and scalability wise.. it may not be the best of ideas. 10 dynamic and very slow and expensive rules, could very well be rewritten as a one very fast and very cheap static SQL statement.
Anyway, the dynamic rule approach can look something like the following:
SQL> create or replace type TBonusRule is object
2 (
3 result# char(1),
4 member function Passed return boolean
5 )
6 not final;
7 /
Type created.
SQL> show errors
No errors.
SQL>
SQL>
SQL> create or replace type body TBonusRule is
2 member function Passed return boolean is
3 begin
4 return( UPPER(self.result#) = 'Y' );
5 end;
6 end;
7 /
Type body created.
SQL> show errors
No errors.
SQL>
SQL>
SQL> create or replace type TBonusSQLRule under TBonusRule
2 (
3 constructor function TBonusSQLRule( empNo number, sqlStatement varchar2 ) return self as result
4 ) final;
5 /
Type created.
SQL> show errors
No errors.
SQL>
SQL>
SQL> create or replace type body TBonusSQLRule is
2 constructor function TBonusSQLRule( empNo number, sqlStatement varchar2 ) return self as result is
3 begin
4 execute immediate sqlStatement
5 into self.result#
6 using IN empNo;
7
8 return;
9 end;
10
11 end;
12 /
Type body created.
SQL> show errors
No errors.
SQL>
SQL> set serveroutput on
SQL> declare
2 rule1 TBonusSQLRule;
3 rule2 TBonusSQLRule;
4 empNo number;
5 begin
6 empNo := 7369; -- we process employee 7369
7
8 -- we apply bonus rule 1 that check if the employee is a clerk (of course,
9 -- we could be reading these rules from a rules table - this example simply
10 -- creates them dynamically)
11 rule1 := new TBonusSQLRule( empNo, 'select ''Y'' from emp where empno = :0 and job=''CLERK''' );
12
13 if rule1.Passed then
14 DBMS_OUTPUT.put_line( 'Rule 1. PASSED' );
15 else
16 DBMS_OUTPUT.put_line( 'Rule 1. FAILED' );
17 end if;
18
19 -- rule 2 can for example check if the employee has been working for at least 5 years for the
20 -- company
21 rule2 := new TBonusSQLRule( empNo, 'select ''Y'' from emp where empno = :0 and (SYSDATE-hiredate)>5*365' );
22
23 if rule2.Passed then
24 DBMS_OUTPUT.put_line( 'Rule 2. PASSED' );
25 else
26 DBMS_OUTPUT.put_line( 'Rule 2. FAILED' );
27 end if;
28
29 end;
30 /
Rule 1. PASSED
Rule 2. PASSED
PL/SQL procedure successfully completed.
SQL>
PL/SQL rules can in a similar fashion be subclassed from the base/asbtract class. And rules can be persisted in a table too.
But even though I did this example to illustrate just how flexible Oracle can be, I would personally think hard before using the above approach myself.
Why?
Because rules 1 and 2 resulted in two SQLs being fired. A single SQL could have done the job.
2 SQLs were used for a single employee. I can use a single SQL to find ALL employees that matches the rule criteria.
So... not very scalable and not very fast.

Similar Messages

  • Sporadically getting error "string or binary data would be truncated" in SQL server 2008 while inserting in a Table Type object

    I am facing a strange SQL exception:-
    The code flow is like this:
    .Net 4.0 --> Entity Framework --> SQL 2008 ( StoredProc --> Function {Exception})
    In the SQL Table-Valued Function, I am selecting a column (nvarchar(50)) from an existing table and (after some filtration using inner joins and where clauses) inserting the values in a Table Type Object having a column (nvarchar(50))
    This flow was working fine in SQL 2008 but now all of sudden the Insert into @TableType is throwing  "string or binary data would be truncated"  exception. 
    Insert Into @ObjTableType
    Select * From dbo.Table
    The max length of data in the source column is 24 but even then the insert statement into nvarchar temp column is failing.
    Moreover, the same issue started coming up few weeks back and I was unable to find the root cause, but back then it started working properly after few hours
    (issue reported at 10 AM EST and was automatically resolved post 8 PM EST). No refresh activity was performed on the database.
    This time however the issue is still coming up (even after 2 days) but is not coming up in every scenario. The data set, for which the error is thrown, is valid and every value in the function is fetched from existing tables. 
    Due to its sporadic nature, I am unable to recreate it now :( , but still unable to determine why it started coming up or how can i prevent such things to happen again.
    It is difficult to even explain the weirdness of this bug but any help or guidance in finding the root cause will be very helpful.
    I also Tried by using nvarchar(max) in the table type object but it didn't work.
    Here is a code similar to the function which I am using:
    BEGIN
    TRAN
    DECLARE @PID
    int = 483
    DECLARE @retExcludables
    TABLE
        PID
    int NOT
    NULL,
        ENumber
    nvarchar(50)
    NOT NULL,
        CNumber
    nvarchar(50)
    NOT NULL,
        AId
    uniqueidentifier NOT
    NULL
    declare @PSCount int;
    select @PSCount =
    count('x')
    from tblProjSur ps
    where ps.PID
    = @PID;
    if (@PSCount = 0)
    begin
    return;
    end;
    declare @ExcludableTempValue table (
            PID
    int,
            ENumber
    nvarchar(max),
            CNumber
    nvarchar(max),
            AId
    uniqueidentifier,
            SIds
    int,
            SCSymb
    nvarchar(10),
            SurCSymb
    nvarchar(10)
    with SurCSymbs as (
    select ps.PID,
                   ps.SIds,              
                   csl.CSymb
    from tblProjSur ps
                right
    outer join tblProjSurCSymb pscs
    on pscs.tblProjSurId
    = ps.tblProjSurId
    inner join CSymbLookup csl
    on csl.CSymbId
    = pscs.CSymbId 
    where ps.PID
    = @PID
        AssignedValues
    as (
    select psr.PID,
                   psr.ENumber,
                   psr.CNumber,
                   psmd.MetaDataValue
    as ClaimSymbol,
                   psau.UserId
    as AId,
                   psus.SIds
    from PSRow psr
    inner join PSMetadata psmd
    on psmd.PSRowId
    = psr.SampleRowId
    inner join MetaDataLookup mdl
    on mdl.MetaDataId
    = psmd.MetaDataId
    inner join PSAUser psau
    on psau.PSRowId
    = psr.SampleRowId
                inner
    join PSUserSur psus
    on psus.SampleAssignedUserId
    = psau.ProjectSampleUserId
    where psr.PID
    = @PID
    and mdl.MetaDataCommonName
    = 'CorrectValue'
    and psus.SIds
    in (select
    distinct SIds from SurCSymbs)         
        FullDetails
    as (
    select asurv.PID,
    Convert(NVarchar(50),asurv.ENumber)
    as ENumber,
    Convert(NVarchar(50),asurv.CNumber)
    as CNumber,
                   asurv.AId,
                   asurv.SIds,
                   asurv.CSymb
    as SCSymb,
                   scs.CSymb
    as SurCSymb
    from AssignedValues asurv
    left outer
    join SurCSymbs scs
    on    scs.PID
    = asurv.PID
    and scs.SIds
    = asurv.SIds
    and scs.CSymb
    = asurv.CSymb
    --Error is thrown at this statement
    insert into @ExcludableTempValue
    select *
    from FullDetails;
    with SurHavingSym as (   
    select distinct est.PID,
                            est.ENumber,
                            est.CNumber,
                            est.AId
    from @ExcludableTempValue est
    where est.SurCSymb
    is not
    null
    delete @ExcludableTempValue
    from @ExcludableTempValue est
    inner join SurHavingSym shs
    on    shs.PID
    = est.PID
    and shs.ENumber
    = est.ENumber
    and shs.CNumber
    = est.CNumber
    and shs.AId
    = est.AId;
    insert @retExcludables(PID, ENumber, CNumber, AId)
    select distinct est.PID,
    Convert(nvarchar(50),est.ENumber)
    ENumber,
    Convert(nvarchar(50),est.CNumber)
    CNumber,
                            est.AId      
    from @ExcludableTempValue est 
    RETURN
    ROLLBACK
    TRAN
    I have tried by converting the columns and also validated the input data set for any white spaces or special characters.
    For the same input data, it was working fine till yesterday but suddenly it started throwing the exception.

    Remember, the CTE isn't executing the SQL exactly in the order you read it as a human (don't get too picky about that statement, it's at least partly true enough to say it's partly true), nor are the line numbers or error messages easy to read: a mismatch
    in any of the joins along the way leading up to your insert could be the cause too.  I would suggest posting the table definition/DDL for:
    - PSMetadata, in particular PSRowID, but just post it all
    - tblProjectSur, in particularcolumns CSymbID and TblProjSurSurID
    - cSymbLookup, in particular column CSymbID
    - PSRow, in particular columns SampleRowID, PID,
    - PSAuser and PSUserSur, in particualr all the USERID and RowID columns
    - SurCSymbs, in particular colum SIDs
    Also, a diagnostic query along these lines, repeat for each of your tables, each of the columns used in joins leading up to your insert:
    Select count(asurv.sid) as count all
    , count(case when asurv.sid between 0 and 9999999999 then 1 else null end) as ctIsaNumber
    from SurvCsymb
    The sporadic nature would imply that the optimizer usually chooses one path to the data, but sometimes others, and the fact that it occurs during the insert could be irrelevant, any of the preceding joins could be the cause, not the data targeted to be inserted.

  • Error while doing Bulk Collect to a table type

    I'm using a Table type to accumulate resultset from a loop and finally return the records in the table type as a ref cursor to the front end.
    But when I'm using Bult collect to insert into the table type object it keeps throwing an error
    'PLS-00597: expression 'TAB_CALENDAR_AVAIL_RESULTSET' in the INTO list is of wrong type'. Can someone help me to let me know what could be the reason for this error. I'm not able to proceed further, please help.
    Here is the code.
    CREATE OR REPLACE PACKAGE hotel
    AS
    TYPE calendar_cursor IS REF CURSOR;
    TYPE type_calendar_avail is RECORD(
    HOTEL_ID AVAILABILITY_CALENDAR.hotel_id%TYPE,--varchar2(4), --AVAILABILITY_CALENDAR.hotel_id%TYPE,
    AVAIL_DATE AVAILABILITY_CALENDAR.AVAIL_DATE%TYPE ,
    TOTAL_COUNT number
    TYPE type_calendar_avail_resultset IS TABLE OF type_calendar_avail;
    tab_calendar_avail_resultset type_calendar_avail_resultset ; -- declare variable of type type_calendar_avail_resultset
    PROCEDURE sp_get_calendar_results (
    sallhotelswithavaildate VARCHAR2,
    ilengthofstay NUMBER,
    sorcowner VARCHAR2,
    all_unittypes VARCHAR2, --DBMS_SQL.VARCHAR2S
    calendar_resultset OUT calendar_cursor
         -- tab_calendar_avail_resultset out type_calendar_avail_resultset
    PROCEDURE sp_get_calendar_results (
    sallhotelswithavaildate VARCHAR2,
    ilengthofstay NUMBER,
    -- ivariant NUMBER,
    sorcowner VARCHAR2,
    all_unittypes VARCHAR2, --DBMS_SQL.VARCHAR2S
    calendar_resultset OUT calendar_cursor
    AS
    sbuf VARCHAR2 (200);
    sepr VARCHAR2 (1);
    shotelwithdate VARCHAR2 (200);
    shotelid VARCHAR2 (10);
    savaildate VARCHAR2 (8);
    sactualavaildate VARCHAR2 (8);
    pos NUMBER;
    istart NUMBER;
    sstartdate VARCHAR2 (8);
    senddate VARCHAR2 (8);
    squery VARCHAR2 (32767) := '';
    sunittypecond VARCHAR2 (500) := '';
    sunitdesccond VARCHAR2 (500) := '';
    v_unit_cond a_unit_cond;
    tempunitcond VARCHAR2 (50) := '';
    BEGIN
    istart := 1;
    LOOP
    tempunitcond := hotel.stringtokenizer (all_unittypes, istart, '|');
    IF tempunitcond IS NOT NULL
    THEN
    v_unit_cond (istart) := tempunitcond;
    istart := istart + 1;
    END IF;
    EXIT WHEN tempunitcond IS NULL;
    END LOOP;
    sunitdesccond := hotel.get_unit_description_cond (v_unit_cond);
    DBMS_OUTPUT.put_line ('unit description : ' || sunitdesccond);
    sbuf := sallhotelswithavaildate;
    sepr := '|';
    istart := 1;
    LOOP
    shotelwithdate := hotel.stringtokenizer (sbuf, istart, sepr);
    EXIT WHEN shotelwithdate IS NULL;
    shotelid :=
    SUBSTR (shotelwithdate, 1, INSTR (shotelwithdate, ',') - 1);
    savaildate :=
    SUBSTR (shotelwithdate, INSTR (shotelwithdate, ',') + 1);
    squery :=
    ' SELECT MIN (ad.avail_date) '
    || ' FROM wvo_fonres.fpavail_daily ad'
    || ' WHERE ad.hotel_id = '
    || shotelid
    || ' AND ad.days_left >= '
    || ilengthofstay
    || ' AND ad.avail_date >= '
    || savaildate;
    IF UPPER (sorcowner) = 'N'
    THEN
    squery :=
    squery
    || ' AND ad.ORC_TYPE != ''R'' and ad.ORC_TYPE != ''P'' and ad.ORC_TYPE != ''E'' ';
    END IF;
    squery := squery || ' AND ( ' || sunitdesccond || ') ';
    EXECUTE IMMEDIATE squery
    INTO sactualavaildate;
    DBMS_OUTPUT.put_line ('Actual available Date: ' || sactualavaildate);
    hotel.sp_get_startdate_enddate (sactualavaildate,
    --ivariant,
    sstartdate,
    senddate
    sunittypecond := hotel.get_unittype_cond (v_unit_cond, sorcowner);
    -- execute immediate
    squery :=
    'select HOTEL_ID, AVAIL_DATE, ' || sunittypecond || ' AS TOTAL_COUNT '
    || ' FROM AVAILABILITY_CALENDAR A '
    || 'WHERE '
    || 'AVAIL_DATE >= '''
    || sstartdate
    || ''' '
    || 'AND '
    || 'AVAIL_DATE <= '''
    || senddate
    || ''' '
    ||'AND '
    || 'A.HOTEL_ID IN ('
    || shotelid
    || ') '
    || 'AND ('
    || sunittypecond
    || '> 0) '
    || -- where total available count of unit type is greater than 0
    ' ORDER BY AVAIL_DATE'; --order clause
         open calendar_resultset for squery;
         fetch calendar_resultset BULK COLLECT INTO tab_calendar_avail_resultset;
    istart := istart + 1;
    END LOOP;
    COMMIT;
    EXCEPTION
    WHEN NO_DATA_FOUND
    THEN
    NULL;
    WHEN OTHERS
    THEN
    DBMS_OUTPUT.put_line
    (SQLERRM (SQLCODE));
    RAISE;
    END sp_get_calendar_results;
    END hotel;
    /

    1. put tags [co[/b][b]de] and [co[/b][b]de] around your code, so it's readable
    B. what does "hotel.get_unittype_cond (v_unit_cond, sorcowner)" actually retun?
    and third, try this for the array declaration:
    tab_calendar_avail_resultset type_calendar_avail_resultset := type_calendar_avail_resultset ; () ;

  • Managing statistics for object collections used as table types in SQL

    Hi All,
    Is there a way to manage statistics for collections used as table types in SQL.
    Below is my test case
    Oracle Version :
    SQL> select * from v$version;
    BANNER
    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 IBM/AIX RISC System/6000: Version 11.2.0.3.0 - Production
    NLSRTL Version 11.2.0.3.0 - Production
    SQL> Original Query :
    SELECT
         9999,
         tbl_typ.FILE_ID,
         tf.FILE_NM ,
         tf.MIME_TYPE ,
         dbms_lob.getlength(tfd.FILE_DATA)
    FROM
         TG_FILE tf,
         TG_FILE_DATA tfd,
              SELECT
              FROM
                   TABLE
                        SELECT
                             CAST(TABLE_ESC_ATTACH(OBJ_ESC_ATTACH( 9999, 99991, 'file1.png', NULL, NULL, NULL),
                             OBJ_ESC_ATTACH( 9999, 99992, 'file2.png', NULL, NULL, NULL)) AS TABLE_ESC_ATTACH)
                        FROM
                             dual
         )     tbl_typ
    WHERE
         tf.FILE_ID     = tfd.FILE_ID
    AND tf.FILE_ID  = tbl_typ.FILE_ID
    AND tfd.FILE_ID = tbl_typ.FILE_ID;
    Elapsed: 00:00:02.90
    Execution Plan
    Plan hash value: 3970072279
    | Id  | Operation                                | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT                         |              |     1 |   194 |  4567   (2)| 00:00:55 |
    |*  1 |  HASH JOIN                               |              |     1 |   194 |  4567   (2)| 00:00:55 |
    |*  2 |   HASH JOIN                              |              |  8168 |   287K|   695   (3)| 00:00:09 |
    |   3 |    VIEW                                  |              |  8168 |   103K|    29   (0)| 00:00:01 |
    |   4 |     COLLECTION ITERATOR CONSTRUCTOR FETCH|              |  8168 | 16336 |    29   (0)| 00:00:01 |
    |   5 |      FAST DUAL                           |              |     1 |       |     2   (0)| 00:00:01 |
    |   6 |    TABLE ACCESS FULL                     | TG_FILE      |   565K|    12M|   659   (2)| 00:00:08 |
    |   7 |   TABLE ACCESS FULL                      | TG_FILE_DATA |   852K|   128M|  3863   (1)| 00:00:47 |
    Predicate Information (identified by operation id):
       1 - access("TF"."FILE_ID"="TFD"."FILE_ID" AND "TFD"."FILE_ID"="TBL_TYP"."FILE_ID")
       2 - access("TF"."FILE_ID"="TBL_TYP"."FILE_ID")
    Statistics
              7  recursive calls
              0  db block gets
          16783  consistent gets
          16779  physical reads
              0  redo size
            916  bytes sent via SQL*Net to client
            524  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              2  rows processed Indexes are present in both the tables ( TG_FILE, TG_FILE_DATA ) on column FILE_ID.
    select
         index_name,blevel,leaf_blocks,DISTINCT_KEYS,clustering_factor,num_rows,sample_size
    from
         all_indexes
    where table_name in ('TG_FILE','TG_FILE_DATA');
    INDEX_NAME                     BLEVEL LEAF_BLOCKS DISTINCT_KEYS CLUSTERING_FACTOR     NUM_ROWS SAMPLE_SIZE
    TG_FILE_PK                          2        2160        552842             21401       552842      285428
    TG_FILE_DATA_PK                     2        3544        852297             61437       852297      852297 Ideally the view should have used NESTED LOOP, to use the indexes since the no. of rows coming from object collection is only 2.
    But it is taking default as 8168, leading to HASH join between the tables..leading to FULL TABLE access.
    So my question is, is there any way by which I can change the statistics while using collections in SQL ?
    I can use hints to use indexes but planning to avoid it as of now. Currently the time shown in explain plan is not accurate
    Modified query with hints :
    SELECT    
        /*+ index(tf TG_FILE_PK ) index(tfd TG_FILE_DATA_PK) */
        9999,
        tbl_typ.FILE_ID,
        tf.FILE_NM ,
        tf.MIME_TYPE ,
        dbms_lob.getlength(tfd.FILE_DATA)
    FROM
        TG_FILE tf,
        TG_FILE_DATA tfd,
            SELECT
            FROM
                TABLE
                        SELECT
                             CAST(TABLE_ESC_ATTACH(OBJ_ESC_ATTACH( 9999, 99991, 'file1.png', NULL, NULL, NULL),
                             OBJ_ESC_ATTACH( 9999, 99992, 'file2.png', NULL, NULL, NULL)) AS TABLE_ESC_ATTACH)
                        FROM
                             dual
        tbl_typ
    WHERE
        tf.FILE_ID     = tfd.FILE_ID
    AND tf.FILE_ID  = tbl_typ.FILE_ID
    AND tfd.FILE_ID = tbl_typ.FILE_ID;
    Elapsed: 00:00:00.01
    Execution Plan
    Plan hash value: 1670128954
    | Id  | Operation                                 | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT                          |                 |     1 |   194 | 29978   (1)| 00:06:00 |
    |   1 |  NESTED LOOPS                             |                 |       |       |            |          |
    |   2 |   NESTED LOOPS                            |                 |     1 |   194 | 29978   (1)| 00:06:00 |
    |   3 |    NESTED LOOPS                           |                 |  8168 |  1363K| 16379   (1)| 00:03:17 |
    |   4 |     VIEW                                  |                 |  8168 |   103K|    29   (0)| 00:00:01 |
    |   5 |      COLLECTION ITERATOR CONSTRUCTOR FETCH|                 |  8168 | 16336 |    29   (0)| 00:00:01 |
    |   6 |       FAST DUAL                           |                 |     1 |       |     2   (0)| 00:00:01 |
    |   7 |     TABLE ACCESS BY INDEX ROWID           | TG_FILE_DATA    |     1 |   158 |     2   (0)| 00:00:01 |
    |*  8 |      INDEX UNIQUE SCAN                    | TG_FILE_DATA_PK |     1 |       |     1   (0)| 00:00:01 |
    |*  9 |    INDEX UNIQUE SCAN                      | TG_FILE_PK      |     1 |       |     1   (0)| 00:00:01 |
    |  10 |   TABLE ACCESS BY INDEX ROWID             | TG_FILE         |     1 |    23 |     2   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       8 - access("TFD"."FILE_ID"="TBL_TYP"."FILE_ID")
       9 - access("TF"."FILE_ID"="TBL_TYP"."FILE_ID")
           filter("TF"."FILE_ID"="TFD"."FILE_ID")
    Statistics
              0  recursive calls
              0  db block gets
             16  consistent gets
              8  physical reads
              0  redo size
            916  bytes sent via SQL*Net to client
            524  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              2  rows processed
    Thanks,
    B

    Thanks Tubby,
    While searching I had found out that we can use CARDINALITY hint to set statistics for TABLE funtion.
    But I preferred not to say, as it is currently undocumented hint. I now think I should have mentioned it while posting for the first time
    http://www.oracle-developer.net/display.php?id=427
    If we go across the document, it has mentioned in total 3 hints to set statistics :
    1) CARDINALITY (Undocumented)
    2) OPT_ESTIMATE ( Undocumented )
    3) DYNAMIC_SAMPLING ( Documented )
    4) Extensible Optimiser
    Tried it out with different hints and it is working as expected.
    i.e. cardinality and opt_estimate are taking the default set value
    But using dynamic_sampling hint provides the most correct estimate of the rows ( which is 2 in this particular case )
    With CARDINALITY hint
    SELECT
        /*+ cardinality( e, 5) */*
    FROM
         TABLE
              SELECT
                   CAST(TABLE_ESC_ATTACH(OBJ_ESC_ATTACH( 9999, 99991, 'file1.png', NULL, NULL, NULL),
                   OBJ_ESC_ATTACH( 9999, 99992, 'file2.png', NULL, NULL, NULL)) AS TABLE_ESC_ATTACH)
              FROM
                   dual
         ) e ;
    Elapsed: 00:00:00.00
    Execution Plan
    Plan hash value: 1467416936
    | Id  | Operation                             | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT                      |      |     5 |    10 |    29   (0)| 00:00:01 |
    |   1 |  COLLECTION ITERATOR CONSTRUCTOR FETCH|      |     5 |    10 |    29   (0)| 00:00:01 |
    |   2 |   FAST DUAL                           |      |     1 |       |     2   (0)| 00:00:01 |
    With OPT_ESTIMATE hint
    SELECT
         /*+ opt_estimate(table, e, scale_rows=0.0006) */*
    FROM
         TABLE
              SELECT
                   CAST(TABLE_ESC_ATTACH(OBJ_ESC_ATTACH( 9999, 99991, 'file1.png', NULL, NULL, NULL),
                   OBJ_ESC_ATTACH( 9999, 99992, 'file2.png', NULL, NULL, NULL)) AS TABLE_ESC_ATTACH)
              FROM
                   dual
         ) e ;
    Execution Plan
    Plan hash value: 4043204977
    | Id  | Operation                              | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT                       |      |     5 |   485 |    29   (0)| 00:00:01 |
    |   1 |  VIEW                                  |      |     5 |   485 |    29   (0)| 00:00:01 |
    |   2 |   COLLECTION ITERATOR CONSTRUCTOR FETCH|      |     5 |    10 |    29   (0)| 00:00:01 |
    |   3 |    FAST DUAL                           |      |     1 |       |     2   (0)| 00:00:01 |
    With DYNAMIC_SAMPLING hint
    SELECT
        /*+ dynamic_sampling( e, 5) */*
    FROM
         TABLE
              SELECT
                   CAST(TABLE_ESC_ATTACH(OBJ_ESC_ATTACH( 9999, 99991, 'file1.png', NULL, NULL, NULL),
                   OBJ_ESC_ATTACH( 9999, 99992, 'file2.png', NULL, NULL, NULL)) AS TABLE_ESC_ATTACH)
              FROM
                   dual
         ) e ;
    Elapsed: 00:00:00.00
    Execution Plan
    Plan hash value: 1467416936
    | Id  | Operation                             | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT                      |      |     2 |     4 |    11   (0)| 00:00:01 |
    |   1 |  COLLECTION ITERATOR CONSTRUCTOR FETCH|      |     2 |     4 |    11   (0)| 00:00:01 |
    |   2 |   FAST DUAL                           |      |     1 |       |     2   (0)| 00:00:01 |
    Note
       - dynamic sampling used for this statement (level=2)I will be testing the last option "Extensible Optimizer" and put my findings here .
    I hope oracle in future releases, improve the statistics gathering for collections which can be used in DML and not just use the default block size.
    By the way, are you aware why it uses the default block size ? Is it because it is the smallest granular unit which oracle provides ?
    Regards,
    B

  • Is there a table type ATTRIBUTE that can be defined in an ABAP object?

    Hi. Within SE24 on the Attributes tab, is there a way to define an attribute of type TABLE? If you put in STANDARD TABLE as the reference type, it does not allow a generic table type.
    What I want to do is pass in a standard table type to my constructor, and then assign it to a private table attribute in the object.
    I do not want to assign the table to a local variable of the constructor. I want to store the table in a private object attribute. I don't mind if the attribute type is a specific table type (such as KNA1), I just want to be able to assign the constructor's table parameter to some type of private object attribute.
    Thanks.
    Brendan

    Hi Brendan,
      No they are not same. A modelled class or method or an attribute will not have any realtime appliaction. Say for example you want to provide a method or Attribute which may be used in future or expected to be used in future, then you declare that method as Modelled. YOu can execute such a method or access such an attribute.
    Abstract Class is an executable class...but it will have some methods with no implementation. The implementation of such methods will upto the user who is accessing that class.A class defined as ABSTRACT cannot be instantiated, that is, you cannot use CREATE OBJECT with reference to the class. Instead, you can only address the class using its static components or its subclasses. The major purpose of an abstract class is to serve as a template for subclasses.
    If a class contains abstract methods, that is, method declarations with the ABSTRACT addition, the whole class must also be abstract (that is, have the ABSTRACT addition), since a class may not be instantiated if it has unimplemented methods. Equally, if a subclass does not implement all of the abstract methods of its superclasses, it must itself declare them abstract.
    Regards,
    Vara

  • Oracle Object Table Type

    I have an application that I would like to map bc4j to a object type hierarchy in the database. From reading previous otn threads I'm under the impression that Domains are not used for Oracle Table Types, just for columns based on oracle types. The thread later goes on to say that for the base type (person_typ) I would map a entity object to the table(person_table) mapped to the base type. To map all the sub-types I would create new entity objects and have PersonEO subclassed into StudentEO and EmployeeEO.
    I have done this and it's unclear to me when I subclass PersonEO as StudentEO how do I declare that StudentEO is of oracle object type student_typ?
    I'm also having problems with inserting data into the base entity obect. Here's code:
    PersonVOImpl personVo = am.getPersonVO();
    PersonVORowImpl row = (PersonVORowImpl)personVo.createRow();
    personVo.insertRow(row);
    row.setName("Mark");
    row.setPhone("911");
    am.getTransaction().commit();
    personVo.executeQuery();
    while (personVo.hasNext()){
    PersonVORowImpl personRow = (PersonVORowImpl)personVo.next();
    The data gets comitted to the db correctly but when the code hits personVo.executeQuery() I get the following error:
    oracle.jbo.domain.DataCreationException: JBO-25009: Cannot create an object of type:oracle.sql.STRUCT with value:Mark
         at oracle.jbo.domain.TypeFactory.get(TypeFactory.java:687)
         at oracle.jbo.domain.TypeFactory.getInstance(TypeFactory.java:80)
         at oracle.jbo.server.OracleSQLBuilderImpl.doLoadBulkFromResultSet(OracleSQLBuilderImpl.java:1113)
         at oracle.jbo.server.ViewRowImpl.populate(ViewRowImpl.java:2017)
         at oracle.jbo.server.ViewDefImpl.createInstanceFromResultSet(ViewDefImpl.java:1013)
         at oracle.jbo.server.ViewObjectImpl.createRowFromResultSet(ViewObjectImpl.java:2309)
         at oracle.jbo.server.ViewObjectImpl.createInstanceFromResultSet(ViewObjectImpl.java:2240)
         at oracle.jbo.server.QueryCollection.populateRow(QueryCollection.java:1698)
         at oracle.jbo.server.QueryCollection.fetch(QueryCollection.java:1552)
         at oracle.jbo.server.QueryCollection.get(QueryCollection.java:1008)
         at oracle.jbo.server.ViewRowSetImpl.getRow(ViewRowSetImpl.java:2791)
         at oracle.jbo.server.ViewRowSetIteratorImpl.doFetch(ViewRowSetIteratorImpl.java:2504)
         at oracle.jbo.server.ViewRowSetIteratorImpl.ensureRefreshed(ViewRowSetIteratorImpl.java:2368)
         at oracle.jbo.server.ViewRowSetIteratorImpl.refresh(ViewRowSetIteratorImpl.java:2569)
         at oracle.jbo.server.ViewRowSetImpl.notifyRefresh(ViewRowSetImpl.java:1641)
         at oracle.jbo.server.ViewRowSetImpl.execute(ViewRowSetImpl.java:577)
         at oracle.jbo.server.ViewRowSetImpl.executeQueryForMasters(ViewRowSetImpl.java:611)
         at oracle.jbo.server.ViewRowSetImpl.executeQuery(ViewRowSetImpl.java:593)
         at oracle.jbo.server.ViewObjectImpl.executeQuery(ViewObjectImpl.java:2886)
         at model.testing.main(testing.java:33)
    Am I coding this correctly? I'm using jdev9032 for this. Are there any examples out there on how to correctly use bc4j with oracle object type tables?
    Thanks in advance!
    -Mark

    Here is my ddl:
    CREATE TYPE Person_typ AS OBJECT
    ( name VARCHAR2(30),
    address VARCHAR2(100)) NOT FINAL
    CREATE TABLE PERSON_TABLE OF PERSON_TYP
    I map a entity object to person_table one for one and I edit the SYS_NC_OID$ property of updateable to never.
    I then map a view object one for one to the entity object. The jbo trace I get when -Djbo.debugoutput=console is declared is the following (omitted everything before the db connected).[156] Successfully logged in
    [157] JDBCDriverVersion: 9.0.1.4.0
    [158] DatabaseProductName: Oracle
    [159] DatabaseProductVersion: Personal Oracle9i Release 9.2.0.1.0 - Production With the Partitioning, OLAP and Oracle Data Mining options JServer Release 9.2.0.1.0 - Production
    [160] ViewRowSetImpl's jbo.viewlink.consistent = false (0)
    [161] Column count: 3
    [162] Executing SQL in generateRefAndOID...
    [163] select a.oid, make_ref(PERSON_TABLE, a.oid) from (select /*+ NO_MERGE +*/ sys_op_guid() as oid from dual) a
    [164] OracleSQLBuilder Executing DML on: PERSON_TABLE (Insert)
    [165] INSERT INTO PERSON_TABLE(NAME,ADDRESS) VALUES (:1,:2)
    [166] BaseSQLBuilder: releaseSavepoint 'BO_SP' ignored
    [167] PersonVO notify COMMIT ...
    [168] Column count: 3
    [169] ViewObject : Created new QUERY statement
    [170] SELECT REF(PersonTable), PersonTable.NAME, PersonTable.ADDRESS FROM PERSON_TABLE PersonTable
    [171] LoadBulkFromResultSet failed (2)
    oracle.jbo.domain.DataCreationException: JBO-25009: Cannot create an object of type:oracle.sql.STRUCT with value:Mark
         java.lang.Object oracle.jbo.domain.TypeFactory.get(java.lang.Class, java.lang.Class, java.lang.Object)
              TypeFactory.java:687
         java.lang.Object oracle.jbo.domain.TypeFactory.getInstance(java.lang.Class, java.lang.Object)
              TypeFactory.java:80
         java.lang.Object[] oracle.jbo.server.OracleSQLBuilderImpl.doLoadBulkFromResultSet(oracle.jbo.server.AttributeDefImpl[], int, java.sql.ResultSet, int, oracle.jbo.server.DBTransactionImpl)
              OracleSQLBuilderImpl.java:1059
         void oracle.jbo.server.ViewRowImpl.populate(java.sql.ResultSet)
              ViewRowImpl.java:1964
         oracle.jbo.server.ViewRowImpl oracle.jbo.server.ViewDefImpl.createInstanceFromResultSet(oracle.jbo.server.ViewObjectImpl, oracle.jbo.server.QueryCollection, java.sql.ResultSet)
              ViewDefImpl.java:1019
         oracle.jbo.server.ViewRowImpl oracle.jbo.server.ViewObjectImpl.createRowFromResultSet(java.lang.Object, java.sql.ResultSet)
              ViewObjectImpl.java:2035
         oracle.jbo.server.ViewRowImpl oracle.jbo.server.ViewObjectImpl.createInstanceFromResultSet(oracle.jbo.server.QueryCollection, java.sql.ResultSet)
              ViewObjectImpl.java:1966
         oracle.jbo.server.ViewRowImpl oracle.jbo.server.QueryCollection.populateRow()
              QueryCollection.java:1395
         boolean oracle.jbo.server.QueryCollection.fetch(int)
              QueryCollection.java:1237
         java.lang.Object oracle.jbo.server.QueryCollection.get(int)
              QueryCollection.java:832
         oracle.jbo.Row oracle.jbo.server.ViewRowSetImpl.getRow(int)
              ViewRowSetImpl.java:2621
         void oracle.jbo.server.ViewRowSetIteratorImpl.doFetch(int)
              ViewRowSetIteratorImpl.java:2347
         void oracle.jbo.server.ViewRowSetIteratorImpl.ensureRefreshed()
              ViewRowSetIteratorImpl.java:2211
         void oracle.jbo.server.ViewRowSetIteratorImpl.refresh(boolean, boolean)
              ViewRowSetIteratorImpl.java:2412
         void oracle.jbo.server.ViewRowSetImpl.notifyRefresh(boolean, boolean)
              ViewRowSetImpl.java:1556
         void oracle.jbo.server.ViewRowSetImpl.execute(boolean, boolean)
              ViewRowSetImpl.java:548
         void oracle.jbo.server.ViewRowSetImpl.executeQuery()
              ViewRowSetImpl.java:564
         void oracle.jbo.server.ViewObjectImpl.executeQuery()
              ViewObjectImpl.java:2616
         void mypackage1.testing.main(java.lang.String[])
              testing.java:25
    Exception in thread main
    Process exited with exit code 1.
    Please let me know if you need more information.
    -Mark

  • SQL table type - How to retrieve in Java?

    Hello,
    I need to return a SQL object to Java from a PL/SQL function.
    In PL/SQL, sample code to create the scalar types, function and calling script would be:
    CREATE OR REPLACE TYPE tMessage AS OBJECT (tType CHAR(20), tText VARCHAR2 (400));
    CREATE OR REPLACE TYPE tMessage_Table AS TABLE OF tMessage;
    CREATE OR REPLACE FUNCTION Return_Message RETURN tMessage_Table AS
    vTable tMessage_Table;
    BEGIN
    vTable := tMessage_Table(NULL);
    vTable.Extend(1);
    vTable(1) := tMessage ('Header', 'Business Rule');
    vTable.Extend(1);
    vTable(2) := tMessage ('Phn', '9053098461');
    -- Output the data to reporting caller
    RETURN vTable;
    END Return_Message;
    DECLARE
    vTmp_Track tMessage_Table;
    BEGIN
    vTmp_Track := Return_Message;
    FOR i IN 1..vTmp_Track.Count LOOP
    DBMS_OUTPUT.PUT_LINE (vTmp_Track(i).tType);
    DBMS_OUTPUT.PUT_LINE (vTmp_Track(i).tText);
    DBMS_OUTPUT.PUT_LINE (' ');
    END LOOP;
    END;
    Is there a way in Java to declare and retrieve an object of type tMessage_Table?
    The only other way I can think of doing this would be to create a table and a ref cursor to browse over it, which I can read back from Java.
    Thank you.

    25266,
    Following code was executed using JDK 1.4.2_07, Oracle 9i (9.2.0.4) database, and "ojdbc14.jar" JDBC (thin) driver:
    [Note that I used your "type" definitions and PL/SQL function.]
    import java.sql.Array;
    import java.sql.CallableStatement;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.Struct;
    import java.sql.Types;
    import java.util.Arrays;
    public class SqlStruc {
      public static void main(String[] args) {
        CallableStatement cs = null;
        Connection dbConn = null;
        String url = "jdbc:oracle:thin:scott/tiger@host:1526:orcl";
        try {
          Class.forName("oracle.jdbc.driver.OracleDriver");
          dbConn = DriverManager.getConnection(url);
          cs = dbConn.prepareCall("{? = call RETURN_MESSAGE()}");
          cs.registerOutParameter(1, Types.ARRAY, "T_MSG_TBL");
          cs.execute();
          Object obj = cs.getObject(1);
          System.out.println(obj);
          if (obj != null) {
            System.out.println("Class: " + obj.getClass().getName());
          Array arr = (Array) obj;
          Object[] objArr = (Object[]) arr.getArray();
          for (int i = 0; i < objArr.length; i++) {
            Struct struct = (Struct) objArr;
    Object[] attrs = struct.getAttributes();
    System.out.println(Arrays.asList(attrs));
    catch (Exception x) {
    System.err.println("SqlStruc: Exception caught.");
    x.printStackTrace();
    finally {
    if (cs != null) {
    try {
    cs.close();
    catch (Exception x) {
    System.err.println("Failed to close statement.");
    x.printStackTrace();
    if (dbConn != null) {
    try {
    dbConn.close();
    catch (Exception x) {
    System.err.println("Failed to close database connection.");
    x.printStackTrace();
    And results were:
    oracle.sql.ARRAY@166a22b
    Class: oracle.sql.ARRAY
    [Header              , Business Rule]
    [Phn                 , 9053098461]Good Luck,
    Avi.

  • Can plsql return table of object type

    Dear All,
    I am trying to return a set of data using object type.
    But i am able to return only a single row but I want to return multiple rows.
    I am trying to create the procedure which will return the table of object type but I am not able to assign value to table of object type.
    Any ideas will be appreciated.
    Regards
    Abhishek

    ArchitectView wrote:
    The intention is to create a tree structure of data.Is this structure stored in the database? If so, then what data model is used? Relational? Hierachical? Object?
    Each of these have pros and cons. The object model has many when persisted in a database as it nowhere near as flexible and robust as relational. Simple example, you can define an object class called Address. You can define a collection class called addressList. You can make that collection class a column in the Customers table. This allows you to store multiple addresses for a customer - as part of the same row for a customer.
    However, there is a data modeling issue here. How do you index the region code in the address to do region based sales and marketing queries? There is a performance issue here - every time a customer row is read, the Addresses column is also read and this column contains a collection of addresses... Expensive I/O wise.
    If relational data model was used, there would have been an Addresses table. It would have had a region index. And every time you read a customer row, all the addresses of that customer is not automatically read into memory too.
    This Pl/SQL is to be called by another program which will accept the tree structure.So PL/SQL is to deliver a tree structure class?
    You have mentioned about the design being not optimal, please elaborate.
    I am doing these steps to improve performance.
    i already have a java code which creates the data in the tree form {common data model -  XML} .
    I am thinking that if I create the structure in database , it will be better for performance.What makes sense to me (performance, usability and data modeling wise) is to use a relational design to store the tree data in Oracle. Each tree item will have a unique identifier and an optional parent identifier. The latter will be a foreign key constraint to the unique identifier.
    The PL/SQL procedure can use a hierachical SQL to select the relevant root nodes from the tree table (i.e. start with tree items that have null parent identifiers) and transform this into a XML and supply XML output.
    This allows Java to call this PL/SQL procedure, and get XML in response.
    An alternative would be to not use XML, but instead define the tree structure as Java expects it, using SQL advance data types (i.e. classes). But instead of using that for store of the tree's data, the PL/SQL proc uses it to transform the tree data (selected via a hierarchical query) into this class object structure.
    The Java client then needs to have wrapper classes for these SQL classes - and when it calls the PL/SQL proc, it gets a class structure returned that it can natively use on its side.
    This a tad more complex to do than the XML interface - but could be faster as the Java layer does not need to transform the XML into a local data structure... it gets an equivalent data structure directly from PL/SQL.
    The only issue ito performance I can see, is attempting to use such an object structure also as data storage (Oracle table) structure. This is usually less than optimal. Fair to say, that relational data modeling still reigns supreme ito usability, integrity and performance. (at least within RDBMS products, like Oracle)

  • Building an object of nested table types

    Hi,
    Looking for suggestions for the following.
    I have a procedure with 4 table types.
    They are in a hierarchical order so that 4 is the child of 3, 3 is the child of 2 and 2 is the child of 1.
    One of the columns of table 1 is a table type holding all the child records from table 2,
    One of the columns of table 2 is a table type holding all the child records from table 3,
    One of the columns of table 3 is a table type holding all the child records from table 4,
    I have 4 cursors that pull out all of the data to populate each of my 4 table types.
    I am trying to figure out how to nest my fetches to populate all of my table types to create a single object that hold all of my data.
    It’s a table of a table of a table of a table.
    Column 3 of table 1 holds table 2
    Column 3 of table 2 holds table 3
    Column 3 of table 3 holds table 4
    I’ve tried creating my procedure like this (pseudo code)
    declare
    tab_1 tab_1_type;
    tab_2 tab_2_type;
    tab_3 tab_3_type;
    tab_4 tab_4_type;
    cursor get_tab_1 is
    select col1, col2, tab_2 – added the table type for the child records
    from data_table_1
    cursor get_tab_2(tab_1_pk in number) is
    select col1, col2, tab_3 – added the table type for the child records
    from data_table_2
    where tab_2_fk = tab_1_pk
    cursor get_tab_3(tab_2_pk in number) is
    select col1, col2, tab_4 – added the table type for the child records
    from data_table_3
    where tab_3_fk = tab_2_pk
    cursor get_tab_4(tab_3_pk in number) is
    select col1, col2, col3
    from data_table_4
    where tab_4_fk = tab_3_pk
    begin
    open get_tab_1;
    loop
    open get_tab_2
    loop
    open get_tab_3
    loop
    open get_tab_4(tab_3_pk);
    bulk collect get_tab_4 into tab_4;
    close get_tab_4;
    fetch get_tab_3 into tab_3;
    tab_4:= null;
    exit when get_tab_3 %notfound;
    end loop;
    close get_tab_3;
    fetch get_tab_2 into tab_2;
    tab_3:= null;
    exit when get_tab_2 %notfound;
    end loop;
    close get_tab_2;
    fetch get_tab_1 into tab_1;
    tab_3:= null;
    exit when get_tab_1 %notfound;
    end loop;
    close get_tab_1;
    l_return := tab_1;
    end;
    The above won’t work because once the cursor is opened the child tables will be assigned values of null before they have had a chance to populate from the nested fetches.
    It’s almost as if I need to execute the fetch and update the extra columns afterwards somehow, something like:
    fetch get_tab_3 into tab_3;
    tab_3.col3 := tab_4;
    tab_4 := null;
    end loop;
    close get_tab_3;
    can I do that?
    Also the above seems very cumbersome. If there is a more elegant way of building up this object I’d like to hear it.
    Cheers
    Yog

    Interesting little exercise getting a 3 deep nested structure using a single SQL. Below is my attempt. You should be able to run it in any schema that has CREATE TYPE privs.
    SQL> -- Nested structure design:
    SQL> --
    SQL> -- USER LIST = (
    SQL> -- (USER1,OBJECT_LIST1).., (USERn,OBJECT_LISTn)
    SQL> -- )
    SQL> --
    SQL> -- LIST OF OBJECTS = (
    SQL> -- (TYPE1, NAME_LIST1).., (TYPEn, NAME_LISTn)
    SQL> -- )
    SQL> --
    SQL> -- LIST OF NAMES = ( NAME1..,NAMEn )
    SQL>
    SQL>
    SQL> create or replace type TObjectList is table of varchar2(50)
    2 /
    Type created.
    SQL>
    SQL> create or replace type TObjType is object(
    2 obj_type varchar2(50),
    3 obj_list TObjectList
    4 );
    5 /
    Type created.
    SQL>
    SQL> create or replace type TObjTypeList is table of TObjType;
    2 /
    Type created.
    SQL>
    SQL> create or replace type TUser is object(
    2 user_name varchar2(50),
    3 objects TObjTypeList
    4 );
    5 /
    Type created.
    SQL>
    SQL> create or replace type TUserList is table of TUser;
    2 /
    Type created.
    SQL>
    SQL> col NESTED_STRUCTURE format a100
    SQL>
    SQL> -- constructing the above user list (have made the start of the USER bold in the output below)
    SQL> select
    2 CAST( COLLECT(
    3 TUser(
    4 username,
    5 CAST( MULTISET(
    6 select
    7 TObjType(
    8 object_type,
    9 CAST( COLLECT(o.object_name) as TObjectList)
    10 )
    11 from all_objects o
    12 where o.owner = u.username
    13 group by
    14 o.object_type
    15 ) as TObjTypeList
    16 )
    17 )
    18 ) as TUserList
    19 ) as NESTED_STRUCTURE
    20 from all_users u
    21 where u.username in ('BILLY','DBSNMP')
    22 /
    NESTED_STRUCTURE(USER_NAME, OBJECTS(OBJ_TYPE, OBJ_LIST))
    TUSERLIST(TUSER('BILLY', TOBJTYPELIST(TOBJTYPE('FUNCTION', TOBJECTLIST('GETEMP', 'GETEMP2', 'TESTRET
    URN', 'WTF', 'ANOOP_REF')), TOBJTYPE('INDEX', TOBJECTLIST('PK_DEPT', 'PK_EMP')), TOBJTYPE('PROCEDURE
    ', TOBJECTLIST('USESEQ1', 'FOOPROC', 'W')), TOBJTYPE('TABLE', TOBJECTLIST('X', 'LOAD_TABLE', 'DEPT',
    'EMP', 'BONUS', 'SALGRADE')), TOBJTYPE('TYPE', TOBJECTLIST('TEMP', 'TEMPLOYEE', 'TX', 'TARRAY2D', '
    TARRAY1D', 'TARRAY3D', 'TOBJECT', 'TOBJTYPE', 'TOBJECTLIST', 'TOBJTYPELIST', 'TUSER', 'TUSERLIST', '
    SYSTPTkQoC5hBR+DgQPsKOl0PFQ==', 'SYSTPTkQoC5hyR+DgQPsKOl0PFQ==', 'SYSTPTkQoC5qzR+DgQPsKOl0PFQ==', 'S
    YSTPTkQoC5raR+DgQPsKOl0PFQ==')))), TUSER('DBSNMP', TOBJTYPELIST(TOBJTYPE('INDEX', TOBJECTLIST('MGMT_
    DB_FILE_GTT_PK', 'MGMT_DB_SIZE_GTT_PK')), TOBJTYPE('PACKAGE', TOBJECTLIST('MGMT_RESPONSE')), TOBJTYP
    E('PACKAGE BODY', TOBJECTLIST('MGMT_RESPONSE')), TOBJTYPE('SEQUENCE', TOBJECTLIST('MGMT_RESPONSE_CAP
    TURE_ID', 'MGMT_RESPONSE_SNAPSHOT_ID')), TOBJTYPE('TABLE', TOBJECTLIST('MGMT_SNAPSHOT', 'MGMT_SNAPSH
    OT_SQL', 'MGMT_BASELINE', 'MGMT_BASELINE_SQL', 'MGMT_CAPTURE', 'MGMT_CAPTURE_SQL', 'MGMT_RESPONSE_CO
    NFIG', 'MGMT_LATEST', 'MGMT_LATEST_SQL', 'MGMT_HISTORY', 'MGMT_HISTORY_SQL', 'MGMT_TEMPT_SQL', 'MGMT
    DBFILE_GTT', 'MGMT_DB_SIZE_GTT')), TOBJTYPE('VIEW', TOBJECTLIST('MGMT_RESPONSE_BASELINE')))))
    SQL>
    PS. To understand how the SQL works, run it from the inside out - i.e. run the innermost select on its own to see the output and then add to it until the full select is reached.

  • Passing parameters to PL/SQL table types

    Hi Everybody,
    I have one question about passing PL/SQL tables types and tabs as IN parameter in procedure.I am working in 11.2.0.2.0 environment. I am stuck on how to pass those values to procedure.Please find below more details:
    Table 1:
    CREATE TABLE ITEMS
    ITEM_ID VARCHAR2(40 BYTE) NOT NULL,
    ITEM_NAME VARCHAR2(40 BYTE),
    SERIAL NUMBER(2),
    ADDED_ON DATE);
    Table 2:
    CREATE TABLE ITEM_ACTIVITY_INFO
    ITEM_ID VARCHAR2(40 BYTE) NOT NULL,
    ACCOUNT_TYPE VARCHAR2(1 BYTE),
    ID_NUMBER NUMBER(3),
    ACTIVATION_DATE DATE);
    Table 3:
    CREATE TABLE ITEM_GROUP
    GROUP_ID NUMBER(2) NOT NULL,
    ITEM_ID VARCHAR2(40 BYTE),
    GROUP_TYPE VARCHAR2(20 BYTE),
    GROUP_DATE DATE);
    Table 4:
    CREATE TABLE ITEM_ADDRESS
    GROUP_ID NUMBER(2) NOT NULL,
    NAME VARCHAR2(60 BYTE),
    ADDRESS VARCHAR2(100));
    Following types are created:
    CREATE OR REPLACE TYPE ITEMS_TYPE AS OBJECT
    ITEM_ID VARCHAR2(40 BYTE),
    ITEM_NAME VARCHAR2(40 BYTE),
    SERIAL NUMBER(2),
    ADDED_ON DATE);
    CREATE OR REPLACE TYPE ITEM_ACTIVITY_TYPE AS OBJECT
    ITEM_ID VARCHAR2(40 BYTE),
    ACCOUNT_TYPE VARCHAR2(1 BYTE),
    ID_NUMBER NUMBER(3),
    ACTIVATION_DATE DATE);
    CREATE OR REPLACE TYPE ITEM_GROUP_COMP_TYPE AS OBJECT
    GROUP_ID NUMBER(2) NOT NULL,
    ITEM_ID VARCHAR2(40 BYTE),
    GROUP_TYPE VARCHAR2(20 BYTE),
    GROUP_DATE DATE
    ITEM_ADDRESS_IN ITEM_ADDRESS_TYPE);
    CREATE OR REPLACE TYPE ITEM_ADDRESS_TYPE AS OBJECT
    GROUP_ID NUMBER(2),
    NAME VARCHAR2(60 BYTE),
    ADDRESS VARCHAR2(100));
    CREATE OR REPLACE TYPE ITEM_GROUP_COMP_TAB AS TABLE OF ITEM_GROUP_COMP_TYPE;
    Create or replace procedure ITEM_ADD_CHANGE(
    ITEM_IN IN ITEMS_TYPE,
    ITEM_ACTIVITY_IN IN ITEM_ACTIVITY_TYPE,
    ITEM_GROUP_IN IN ITEM_GROUP_COMP_TAB,
    ITEM_OUT IN OUT ITEMS.ITEM_ID%TYPE);
    Above are the paramteres we are passing to procedure.
    I need help in how to pass parameters to above procedure. All comments and responses will be highly appreciated. Thanks everyone for going through the post. Please let me know if more more information is required on this problem.
    Regards
    Dev

    Billy  Verreynne  wrote:
    Types used in this fashion, only make sense if the table is based on the type. It makes very little sense to have a table structure and then to duplicate the structure using a type.
    The 2 structures may be defined the same. But they are NOT interchangeable and requires one to be converted to the other to use. This is not sensible in my view. It is far easier in that case to simply use the PL/SQL macro +%RowType+ to create a duplicate structure definition - one that can natively be used for touching that table, without conversions required.
    If you do want to use types, define the type, then define the table of that type, adding the required constraints (pk, fk, not null, check) to the table's definition.Billy:
    Just curious, why do you say it makes very little sense to have a type modeled on a table? I do that a lot. In my case, I am getting the values from an external program, not building them manually, but it makes a lot of sense to me.
    One application where I do this a lot has a java front-end that parses HL7 messages. Each message contains at least minimal information about a variable number of entities (and often several rows for an entity) in the database, and must be processed as a single atomic trasnaction. So, rather than have potentially hundreds of parameters to the "main" driver procedures for different message types I created a set of types more or less identical to the tables representing the entities. The java program parses the mesasge and populates the type, then calls the appropriate stored procedure for the message type passing in the populated types. My stored procedure then does inserts/updates or deletes as appropriate over potentially dozens of tables.
    John

  • PL/SQL table type in Forms 4.5

    Hi
    I am trying to use a pl/sql table type variable in Oracle forms 4.5 . I am able to compile this and run it on the database that the application connects to but in forms , it gives me a compilation error.
    Is there some restriction on using this datatype in forms 4.5
    Following is the syntax I am using:
    TYPE block_list_type IS TABLE of VARCHAR2(200) INDEX BY BINARY_INTEGER;
    block_list block_list_type;
    I get fatal syntax error even though the syntax is correct(checked it on the database).
    please let me know if I am doing something wrong.
    thanks a lot

    That explains it!!
    Thanks. My company is on oracle 10.7 and is too reluctant to move to higher versions. They finally bought I2 and are developing their own custom java applications and will phase out 10.7 but are not willing to move to the next version of Oracle !!
    Seems like they are done with Oracle .
    thanks for the input anyways.

  • Passing PL/SQL table type as IN Parameter to DB Adapter

    Hi,
    I have an requirement to pass multiple record values(array of values) to an API from BPEL process.
    For this,
    1) I have created a package procedure having PL/SQL table type variable as IN Parameter.
    2) In the BPEL process, created a DB adpater pointing to the above API.(Created wrapper API impicitly)
    When I intiated the BPEL process passing multiple values, the API is taking only the first value, ignoring rest of the values.
    Any reason, why only the first value is accepted by the API ?
    Thanks,
    Rapp.

    If I understand correctly, JPublisher generates a wrapper API for an underlying API that takes a PL/SQL table as an IN parameter. The wrapper will generate and use a SQL nested table as the type for the IN parameter of the wrapper procedure.
    The DB adapter DOES support nested tables, varrays, and objects as IN parameters of an API. The problem you are seeing is most likely due to the way you are modeling your BPEL process, specifically with respect to your Assign activities.
    When you Assign TO an IN parameter, make sure that you drill down all the way and choose the parameter name in the InputParameters root element. Similarly, when you Assign FROM the API value, you must drill down and choose the name of the OUT parameter in the OutputParameters root element.
    In a Transform activity, you would use the FOR construct on the target side to get the values of the nested table or varray from the source side.

  • Help!! Calling PL/SQL with table of objects params

    Hi JDBC experts,
    This is probably a familiar problem to many of you and I was hoping you can help me.
    I have a JDBC application that makes calls to a PL/SQL stored procedure that accepts and returns tables (arrays) of objects. I have an equivalent representation of these in Java (the object is a simple Java class and the array of objects is a subclass of ArrayList). The object has around 10 attributes (varchar and number) and the call typically accepts and returns between 50 and 100 objects.
    I noticed that converting from one representation to the other before and after the JDBC call is very time consuming. Before calling the procedure, I need to instantiate a new oracle.sql.ARRAY and fill it with oracle.sql.STRUCT equivalents for each object in my ArrayList. After the procedure call returns, I need to instantiate a new ArrayList and fill it with my Java object representation for each oracle.sql.STRUCT in the returned oracle.sql.ARRAY. Given the # of objects returned and the size of each object, this causes performance degradation.
    Is there any way I can avoid the above conversion overhead? I was reading somewhere about jpub and CustomDatum. I tried it out but the code that sqlj generated looked rather complex - but if this is the recommended approach, I can follow that.
    Also, are there any java code examples for dealing with table of (non-scalar) objects with CustomDatum? I saw some code for using CustomDatum with single objects but not with a table of objects.
    Your help is much appreciated!
    Thanks,
    Niranjan

    I would do it like this :
    - use existsNode function in the filter predicate to look for candidate rows regardless of the number of occurrences of target nodes in the document
    - use XPath predicates on attributes to restrict target nodes
    SQL> create table temp1 of xmltype;
    Table created
    SQL>
    SQL> insert into temp1 values(xmlparse(document
      2  '<soc id="2">
      3   <listsectii>
      4    <sectie cods="4">
      5     <prodv codp="2" cant=""></prodv>
      6    </sectie>
      7    <sectie cods="5">
      8     <prodv codp="8"></prodv>
      9    </sectie>
    10    <sectie cods="6">
    11     <prodv codp="2"></prodv>
    12    </sectie>
    13   </listsectii>
    14  </soc>'));
    1 row inserted
    SQL>
    SQL> update temp1
      2  set object_value =
      3      updateXML( object_value
      4               , '/soc/listsectii/sectie[@cods="4"]/prodv[@codp="2"]/@cant'
      5               , 'new_cant' )
      6  where existsNode( object_value
      7                  , '/soc/listsectii/sectie[@cods="4"]/prodv[@codp="2"]' ) = 1
      8  ;
    1 row updated
    SQL> select * from temp1;
    SYS_NC_ROWINFO$
    <soc id="2">
      <listsectii>
        <sectie cods="4">
          <prodv codp="2" cant="new_cant"/>
        </sectie>
        <sectie cods="5">
          <prodv codp="8"/>
        </sectie>
        <sectie cods="6">
          <prodv codp="2"/>
        </sectie>
      </listsectii>
    </soc>
    Of course, that implies there's already an existing "cant" attribute (not the case in your samples).
    If you actually need to create one, then you must use insertChildXML() instead.

  • Passing pl/sql type objects between two database

    Hi All!
    Is there any way out of passing of pl/sql type objects from one databse to another remote database? What are the options available?
    thanks...
    Sanjeeb Bose
    Kolkata India

    Sanjeeb,
    Same answer as your other questions. Since remote object types are not allowed, you need to use scalar types instead.
    Regards,
    Geoff
    Hi All!
    Is there any way out of passing of pl/sql type objects from one databse to another remote database? What are the options available?
    thanks...
    Sanjeeb Bose
    Kolkata India

  • Can you input records to a COLLECTION TYPE object and use it as a table??

    My PL/SQL stored procedure creates a list of employee number and phone number records. I don't want to store them in a table. I will be passing this list from one procedure to another in my package.
    I created the object type (record) and collection type (table) using this statements.
    CREATE TYPE obj_emp_phone_rec AS OBJECT
         emp_number   NUMBER,
         emp_phone    VARCHAR2(100)
    CREATE TYPE obj_emp_phone_recs_table AS TABLE OF obj_emp_phone_rec
    /Thing is, can I use the obj_emp_phone_recs_table "table type" as a table?
    I.e. can I insert records to this in the package procedure and pass reference to it in called sub-procedures.
    i.e. something like this
    PACKAGE BODY abc IS
      PROCEDURE kdkddk IS
      BEGIN
        -- Insert records to the  obj_emp_phone_recs_table
        obj_emp_phone_recs_table(1).emp_number := '1';
        obj_emp_phone_recs_table(1).emp_phone   := '0774949494';
        obj_emp_phone_recs_table(2).emp_number := '234';
        obj_emp_phone_recs_table(2).emp_phone   := '285494';
        -- Pass the table to the sub procedure
        xyx(obj_emp_phone_recs_table);
      END kdkddk;
    END abc;If so how to insert to the obj_emp_phone_recs_table ???
    Nothing on the net. In the Net I found only where u define a normal table's column as an object type and then inserting records to it.
    Any help would be greatly appreciated.
    Edited by: user12240205 on Oct 6, 2011 2:08 AM

    mhouri > drop type obj_emp_phone_recs_table;
    Type dropped.
    mhouri > drop type obj_emp_phone_rec ;
    Type dropped.
    mhouri > CREATE TYPE obj_emp_phone_rec AS OBJECT
      2    (
      3       emp_number   NUMBER,
      4       emp_phone    VARCHAR2(100)
      5    )
      6  /
    Type created.
    mhouri > CREATE TYPE obj_emp_phone_recs_table AS TABLE OF obj_emp_phone_rec
      2  /
    Type created.
    mhouri > create or replace procedure p1(pin_tab IN obj_emp_phone_recs_table)
      2  is
      3   begin
      4     for j in 1..pin_tab.count
      5     loop
      6      dbms_output.put_line('record number '||j ||'-- emp number --'||pin_tab(j).emp_number);
      7     end loop;
      8 
      9  end p1;
    10  /
    Procedure created.
    mhouri > create or replace procedure p2
      2  is
      3  lin_tab  obj_emp_phone_recs_table := obj_emp_phone_recs_table();
      4  begin
      5  FOR i IN 1 .. 5
      6     LOOP
      7        lin_tab.extend;
      8        lin_tab(i) := obj_emp_phone_rec(i, 'i-i-i');
      9     END LOOP;
    10 
    11    p1(lin_tab);
    12 
    13  end p2;
    14  /
    Procedure created.
    mhouri > set serveroutput on
    mhouri > exec p2
    record number 1-- emp number -- 1                                                                                                                                                                                                                         
    record number 2-- emp number --2                                                                                                                                                                                                                         
    record number 3-- emp number --3                                                                                                                                                                                                                         
    record number 4-- emp number --4                                                                                                                                                                                                                         
    record number 5-- emp number --5                                                                                                                                                                                                                         
    PL/SQL procedure successfully completed.Best Regards
    Mohamed Houri

Maybe you are looking for

  • Border selection in V3.2

    Hi hi, Previously, in numbers '09 it was possible to select individual border, then to copy/paste style. Cannot find that In new version. Is it dissabled in v3.2?

  • SQL Developer version 3.2.20.09 and Oracle Diff

        It is my understanding that from this version onwards this functionality would be available without licensing but it is not available for use actually, maybe I am doing something wrong or just "bad info" ? I downloaded jre version 32 bits. Thanks

  • Rounding ruels for cash discount

    Hi, Can any one help me Client want the discount should be rounded, i.e., if the discount value is 25.42 it should be 25 & if it is 25.51, value should be 26 Thanks & regards Kareem

  • License Validation Failed

    I get the following error when trying to use the SQL Server JDBC Driver with WL 6.0. The license we have a developer's license. We have that stored in license.bea in the bea home directory. I have that directory loaded up in the classpath as well. If

  • HT1229 Can I move photos to iphone 5 using from  iphoto11

    Can I move photos to an IPhone 5 FROM iMac 27 using Iphoto 11?