Clob datatype with pipelined table function.

hi
i made two functions one of them which use varchar2 data type with pipelined and
another with clob data type with pipelined.
i am giving parameters to both of them first varch2 with pipelined is working fine.
but another is not.
and i made diff type for both of them.
like clob object type for second.
and varchar2 type for first.
my first function is like
TYPE "CSVOBJECTFORMAT"  AS OBJECT ( "S"   VARCHAR2(500));
TYPE "CSVTABLETYPE" AS TABLE OF CSVOBJECTFORMAT;
CREATE OR REPLACE FUNCTION "FN_PARSECSVSTRING" (p_list
    VARCHAR2, p_delim VARCHAR2:=' ') RETURN CsvTableType PIPELINED
    IS
l_idx PLS_INTEGER;
l_list VARCHAR2(32767) := p_list;
l_value VARCHAR2(32767);
BEGIN
LOOP
l_idx := INSTR(l_list, p_delim);
IF l_idx > 0 THEN
PIPE ROW(CsvObjectFormat(SUBSTR(l_list, 1, l_idx-1)));
l_list := SUBSTR(l_list, l_idx+LENGTH(p_delim));
ELSE
PIPE ROW(CsvObjectFormat(l_list));
EXIT;
END IF;
END LOOP;
RETURN;
END fn_ParseCSVString;
and out put for this function is like
which is correct.
SQL>   SELECT s  FROM  TABLE( CAST( fn_ParseCSVString('+588675,1~#588675^1^99^~2~16~115~99~SP5601~~~~~0~~', '~') as CsvTableType)) ;
S
+588675,1
#588675^1^99^
2
16
115
99
SP5601
S
0
14 rows selected.
SQL>
my second function is like
TYPE "CSVOBJECTFORMAT1"  AS OBJECT ( "S"   clob);
TYPE "CSVTABLETYPE1" AS TABLE OF CSVOBJECTFORMAT1;
CREATE OR REPLACE FUNCTION "FN_PARSECSVSTRING1" (p_list
    clob, p_delim VARCHAR2:=' ') RETURN CsvTableType1 PIPELINED
    IS
l_idx PLS_INTEGER;
l_list  clob := p_list;
l_value VARCHAR2(32767);
BEGIN
dbms_output.put_line('hello');
  LOOP
  l_idx := INSTR(l_list, p_delim);
  IF l_idx > 0 THEN
PIPE ROW(CsvObjectFormat1(substr(l_list, 1, l_idx-1)));
l_list :=  dbms_lob.substr(l_list, l_idx+LENGTH(p_delim));
ELSE
PIPE ROW(CsvObjectFormat1(l_list));
exit;
END IF;
  END LOOP;
RETURN;
END fn_ParseCSVString1;
SQL>   SELECT s  FROM  TABLE( CAST( fn_ParseCSVString1('+588675,1~#588675^1^99^~2~16~115~99~SP5601~~~~~0~~', '~') as CsvTableType1)) ;
S
+588675,1
+588675,1
+588675,1
+588675,1
+588675,1
+588675,1
+588675,1
+588675,1
+588675,1
+588675,1
+588675,1
and it goes on until i use ctrl+C to break it.
actually i want to make a function which can accept large values  so i am trying to change first function.thanks

RTFM DBMS_LOB.SUBSTR. Unlike built-in function SUBSTR, second parameter in DBMS_LOB.SUBSTR is length, not position. Also, PL/SQL fully supports CLOBs, so there is no need to use DBMS_LOB:
SQL> CREATE OR REPLACE
  2  FUNCTION FN_PARSECSVSTRING1(p_list clob,
  3                              p_delim VARCHAR2:=' '
  4                             )
  5    RETURN CsvTableType1
  6    PIPELINED
  7    IS
  8        l_pos   PLS_INTEGER := 1;
  9        l_idx   PLS_INTEGER;
10        l_value clob;
11    BEGIN
12        LOOP
13          l_idx := INSTR(p_list, p_delim,l_pos);
14          IF l_idx > 0
15            THEN
16              PIPE ROW(CsvObjectFormat1(substr(p_list,l_pos,l_idx-l_pos)));
17              l_pos := l_idx+LENGTH(p_delim);
18            ELSE
19              PIPE ROW(CsvObjectFormat1(substr(p_list,l_pos)));
20              RETURN;
21          END IF;
22        END LOOP;
23        RETURN;
24  END fn_ParseCSVString1;
25  /
Function created.
SQL> SELECT rownum,s  FROM  TABLE( CAST( fn_ParseCSVString1('+588675,1~#588675^1^99^~2~16~115~99~SP5
601~~~~~0~~', '~') as CsvTableType1)) ;
    ROWNUM S
         1 +588675,1
         2 #588675^1^99^
         3 2
         4 16
         5 115
         6 99
         7 SP5601
         8
         9
        10
        11
    ROWNUM S
        12 0
        13
        14
14 rows selected.
SQL> SY.

Similar Messages

  • Performance issues with pipelined table functions

    I am testing pipelined table functions to be able to re-use the <font face="courier">base_query</font> function. Contrary to my understanding, the <font face="courier">with_pipeline</font> procedure runs 6 time slower than the legacy <font face="courier">no_pipeline</font> procedure. Am I missing something? The <font face="courier">processor</font> function is from [url http://www.oracle-developer.net/display.php?id=429]improving performance with pipelined table functions .
    Edit: The underlying query returns 500,000 rows in about 3 minutes. So there are are no performance issues with the query itself.
    Many thanks in advance.
    CREATE OR REPLACE PACKAGE pipeline_example
    IS
       TYPE resultset_typ IS REF CURSOR;
       TYPE row_typ IS RECORD (colC VARCHAR2(200), colD VARCHAR2(200), colE VARCHAR2(200));
       TYPE table_typ IS TABLE OF row_typ;
       FUNCTION base_query (argA IN VARCHAR2, argB IN VARCHAR2)
          RETURN resultset_typ;
       c_default_limit   CONSTANT PLS_INTEGER := 100;  
       FUNCTION processor (
          p_source_data   IN resultset_typ,
          p_limit_size    IN PLS_INTEGER DEFAULT c_default_limit)
          RETURN table_typ
          PIPELINED
          PARALLEL_ENABLE(PARTITION p_source_data BY ANY);
       PROCEDURE with_pipeline (argA          IN     VARCHAR2,
                                argB          IN     VARCHAR2,
                                o_resultset      OUT resultset_typ);
       PROCEDURE no_pipeline (argA          IN     VARCHAR2,
                              argB          IN     VARCHAR2,
                              o_resultset      OUT resultset_typ);
    END pipeline_example;
    CREATE OR REPLACE PACKAGE BODY pipeline_example
    IS
       FUNCTION base_query (argA IN VARCHAR2, argB IN VARCHAR2)
          RETURN resultset_typ
       IS
          o_resultset   resultset_typ;
       BEGIN
          OPEN o_resultset FOR
             SELECT colC, colD, colE
               FROM some_table
              WHERE colA = ArgA AND colB = argB;
          RETURN o_resultset;
       END base_query;
       FUNCTION processor (
          p_source_data   IN resultset_typ,
          p_limit_size    IN PLS_INTEGER DEFAULT c_default_limit)
          RETURN table_typ
          PIPELINED
          PARALLEL_ENABLE(PARTITION p_source_data BY ANY)
       IS
          aa_source_data   table_typ;-- := table_typ ();
       BEGIN
          LOOP
             FETCH p_source_data
             BULK COLLECT INTO aa_source_data
             LIMIT p_limit_size;
             EXIT WHEN aa_source_data.COUNT = 0;
             /* Process the batch of (p_limit_size) records... */
             FOR i IN 1 .. aa_source_data.COUNT
             LOOP
                PIPE ROW (aa_source_data (i));
             END LOOP;
          END LOOP;
          CLOSE p_source_data;
          RETURN;
       END processor;
       PROCEDURE with_pipeline (argA          IN     VARCHAR2,
                                argB          IN     VARCHAR2,
                                o_resultset      OUT resultset_typ)
       IS
       BEGIN
          OPEN o_resultset FOR
               SELECT /*+ PARALLEL(t, 5) */ colC,
                      SUM (CASE WHEN colD > colE AND colE != '0' THEN colD / ColE END)de,
                      SUM (CASE WHEN colE > colD AND colD != '0' THEN colE / ColD END)ed,
                      SUM (CASE WHEN colD = colE AND colD != '0' THEN '1' END) de_one,
                      SUM (CASE WHEN colD = '0' OR colE = '0' THEN '0' END) de_zero
                 FROM TABLE (processor (base_query (argA, argB),100)) t
             GROUP BY colC
             ORDER BY colC
       END with_pipeline;
       PROCEDURE no_pipeline (argA          IN     VARCHAR2,
                              argB          IN     VARCHAR2,
                              o_resultset      OUT resultset_typ)
       IS
       BEGIN
          OPEN o_resultset FOR
               SELECT colC,
                      SUM (CASE WHEN colD > colE AND colE  != '0' THEN colD / ColE END)de,
                      SUM (CASE WHEN colE > colD AND colD  != '0' THEN colE / ColD END)ed,
                      SUM (CASE WHEN colD = colE AND colD  != '0' THEN 1 END) de_one,
                      SUM (CASE WHEN colD = '0' OR colE = '0' THEN '0' END) de_zero
                 FROM (SELECT colC, colD, colE
                         FROM some_table
                        WHERE colA = ArgA AND colB = argB)
             GROUP BY colC
             ORDER BY colC;
       END no_pipeline;
    END pipeline_example;
    ALTER PACKAGE pipeline_example COMPILE;Edited by: Earthlink on Nov 14, 2010 9:47 AM
    Edited by: Earthlink on Nov 14, 2010 11:31 AM
    Edited by: Earthlink on Nov 14, 2010 11:32 AM
    Edited by: Earthlink on Nov 20, 2010 12:04 PM
    Edited by: Earthlink on Nov 20, 2010 12:54 PM

    Earthlink wrote:
    Contrary to my understanding, the <font face="courier">with_pipeline</font> procedure runs 6 time slower than the legacy <font face="courier">no_pipeline</font> procedure. Am I missing something? Well, we're missing a lot here.
    Like:
    - a database version
    - how did you test
    - what data do you have, how is it distributed, indexed
    and so on.
    If you want to find out what's going on then use a TRACE with wait events.
    All nessecary steps are explained in these threads:
    HOW TO: Post a SQL statement tuning request - template posting
    http://oracle-randolf.blogspot.com/2009/02/basic-sql-statement-performance.html
    Another nice one is RUNSTATS:
    http://asktom.oracle.com/pls/asktom/ASKTOM.download_file?p_file=6551378329289980701

  • Using Pipeline Table functions with other tables

    I am on DB 11.2.0.2 and have sparingly used pipelined table functions but am considering it for a project that has some fairly big (lots of rows) sized tables. In my tests, selecting from just the pipelined table perform pretty well (whether it is directly from the pipleined table or the view I created on top of it). Where I start to see some degregation when I try to join the pipelined tabe view to other tables and add where conditions.
    ie:
    SELECT A.empno, A.empname, A.job, B.sal
    FROM EMP_VIEW A, EMP B
    WHERE A.empno = B.empno AND
          B.mgr = '7839'
    I have seen some articles and blogs that mention this as a cardinality issue, and offer some undocumented methods to try and combat.
    Can someone please give me some advice or tips on this. Thanks!
    I have created a simple example using the emp table below to help illustrate what I am doing.
    DROP TYPE EMP_TYPE;
    DROP TYPE EMP_SEQ;
    CREATE OR REPLACE TYPE EMP_SEQ AS OBJECT
           ( EMPNO                                         NUMBER(10),
             ENAME                                         VARCHAR2(100),
             JOB                                           VARCHAR2(100));
    CREATE OR REPLACE TYPE EMP_TYPE AS TABLE OF EMP_SEQ;
    CREATE OR REPLACE FUNCTION get_emp return EMP_TYPE PIPELINED AS
    BEGIN
      FOR cur IN (SELECT
                    empno,
                    ename,
                    job
                  FROM emp
             LOOP
               PIPE ROW(EMP_SEQ(cur.empno,
                                cur.ename,
                                cur.job));
             END LOOP;
             RETURN;
    END get_emp;
    create OR REPLACE view EMP_VIEW as select * from table(get_emp());
    SELECT A.empno, A.empname, A.job, B.sal
    FROM EMP_VIEW A, EMP B
    WHERE A.empno = B.empno AND
          B.mgr = '7839'

    I am on DB 11.2.0.2 and have sparingly used pipelined table functions but am considering it for a project that has some fairly big (lots of rows) sized tables
    Which begs the question: WHY? What PROBLEM are you trying to solve and what makes you think using pipelined table functions is the best way to solve that problem?
    The lack of information about cardinality is the likely root of the degradation you noticed as already mentioned.
    But that should be a red flag about pipelined functions in general. PIPELINED functions hide virtually ALL KNOWLEDGE about the result set that is produced; cardinality is just the tip of the iceberg. Those functions pretty much say 'here is a result set' without ANY information about the number of rows (cardinality), distinct values for any columns, nullability of any columns, constraints that might apply to any columns (foreign key, primary key) and so on.
    If you are going to hide all of that information from Oracle that would normally be used to help optimize queries and select the appropriate execution plan you need to have a VERY good reason.
    The use of PIPELINED functions should be reserved for those use cases where ordinary SQL and PL/SQL cannot get the job done. That is they are a 'special case' solution.
    The classic use case for those functions is for the transform stage of ETL where multiple pipelined functions are chained together: one function feeds its rows to the next function which feeds its rows to another and so on. Each of those 'chained' functions is roughly analogous to a full table scan of the data that often does not need to be joined to other data except perhaps low volumn lookup tables where the data may even be cached.
    I suggest that any exploratory or prototyping work you do use standard relational tables until such point as you run into a problem whose solution might require PIPELINED functions to solve.

  • Interactive report on view based on pipelined table function.

    Hi,
    I want to build an Interactive Report on a view.
    The view definition contains a select on a pipelined table function. I use context functionality to pass paramaters to the pipelined table function.
    A plain select * from #my_view# in SqlPlus results in 121 different rows.
    However, If I base my Interactive report on this view, I get 15 repeated rows (all the same).
    Is it possible to use pipelined table functionality on an Interactive report? I can't seem to get it working.
    If I use the following approach (http://rakeshjsr.blogspot.nl/2010/10/oracle-apex-interactive-report-based-on.html) I do get results, but I can't use this solution for a reason that's not relevant.

    Hello,
    Is it possible to use pipelined table functionality on an Interactive report? I can't seem to get it working. I have used it in one instance and it works fine. However I was passing the values to pipe-lined function directly.
    IR Query..
    SELECT * FROM TABLE(fn_pipeline(:P1_ITEM_NAME))Call pipe-lined function from IR query directly (instead of using view)
    Try sending values to Pipe-lined function directly. In-case if the problem is with setting and getting values from the context?
    Regards,
    Hari

  • Pipeline Table Function returning a fraction of data

    My current project involves migrating an Oracle database to a new structure based on the new client application requirements. I would like to use pipelined table functions as it seems as though that would provide the best performance.
    The first table has about 65 fields, about 75% of which require some type of recoding for the new app. I have written a function for each transformation and have all of these functions stored in a package. If I do:
    create new_table as select (
    pkg_name.function1(old_field1),
    pkg_name.function2(old_field2),
    pkg_name.function3(old_field3),
    it runs with out any errors but takes about 3 1/2 hours. There are a little more than 10 million rows in the table.
    I wrote a function that is passed the old table as a cursor, runs all the functions for the transformations and then pipes the new row back to the insert statement that called the function. It is incredibly fast but only returns .025% of the data (about 50 rows out of my sample table of 200,000). It does not throw any errors.
    So I am trying to determine what is going on. Perhaps one of my functions has a bug. If there was would cause the row to be kicked out? There are 40 or so functions so tracking this down has been a bit of a bear.
    Any advice as to how I might resolve this would be much appreciated.
    Thanks
    Dan

    . I would like to use pipelined table functions as it seems as though that would provide the best performanceUh huh...
    it runs with out any errors but takes about 3 1/2 hours. There are a little more than 10 million rows in the table.Not the first time a lovely theory has been killed by an ugly fact. Did you do any bench marks to see whether the pipelined functions did offer performance benefits over doing it some other way?
    From the context of your comments I think you are trying to a populate a new table from a single old table. Is this the case? If so I would have thought a straightforward CTAS with normal functions would be more appropriate: pipelined functions are really meant for situations in which one input produced more than one output. Anyway, ifr we are to help you I think you need to give us more details about how this process works and post a sample transformation function.
    There are 40 or so functions so tracking this down has been a bit of a bear.The teaching is: we should code one function and get that working before moving on to the next one. Which might not seem like a helpful thing to say, but the best lesson is often "I'll do it differently next time".
    Cheers, APC

  • 10g: delay for collecting results from parallel pipelined table functions

    When parallel pipelined table functions are properly started and generate output record, there is a delay for the consuming main thread to gather these records.
    This delay is huge compared with the run-time of the worker threads.
    For my application it goes like this:
    main thread timing efforts to start worker and collect their results:
    [10:50:33-*10:50:49*]:JOMA: create (master): 015.93 sec (#66356 records, #4165/sec)
    worker threads:
    [10:50:34-*10:50:39*]:JOMA: create (slave) : 005.24 sec (#2449 EDRs, #467/sec, #0 errored / #6430 EBTMs, #1227/sec, #0 errored) - bulk #1 / sid #816
    [10:50:34-*10:50:39*]:JOMA: create (slave) : 005.56 sec (#2543 EDRs, #457/sec, #0 errored / #6792 EBTMs, #1221/sec, #0 errored) - bulk #1 / sid #718
    [10:50:34-*10:50:39*]:JOMA: create (slave) : 005.69 sec (#2610 EDRs, #459/sec, #0 errored / #6950 EBTMs, #1221/sec, #0 errored) - bulk #1 / sid #614
    [10:50:34-*10:50:39*]:JOMA: create (slave) : 005.55 sec (#2548 EDRs, #459/sec, #0 errored / #6744 EBTMs, #1216/sec, #0 errored) - bulk #1 / sid #590
    [10:50:34-*10:50:39*]:JOMA: create (slave) : 005.33 sec (#2461 EDRs, #462/sec, #0 errored / #6504 EBTMs, #1220/sec, #0 errored) - bulk #1 / sid #508
    You can see, the worker threads are all started at the same time and terminating at the same time: 10:50:34-10:50:*39*.
    But the main thread just invoking them and saving their results into a collection has finished at 10:50:*49*.
    Why does it need #10 sec more just to save the data?
    Here's a sample sqlplus script to demonstrate this:
    --------------------------- snip -------------------------------------------------------
    set serveroutput on;
    drop table perf_data;
    drop table test_table;
    drop table tmp_test_table;
    drop type ton_t;
    drop type test_list;
    drop type test_obj;
    create table perf_data
         sid number,
         t1 timestamp with time zone,
         t2 timestamp with time zone,
         client varchar2(256)
    create table test_table
         a number(19,0),
         b timestamp with time zone,
         c varchar2(256)
    create global temporary table tmp_test_table
         a number(19,0),
         b timestamp with time zone,
         c varchar2(256)
    create or replace type test_obj as object(
         a number(19,0),
         b timestamp with time zone,
         c varchar2(256)
    create or replace type test_list as table of test_obj;
    create or replace type ton_t as table of number;
    create or replace package test_pkg
    as
         type test_rec is record (
              a number(19,0),
              b timestamp with time zone,
              c varchar2(256)
         type test_tab is table of test_rec;
         type test_cur is ref cursor return test_rec;
         function TZDeltaToMilliseconds(
              t1 in timestamp with time zone,
              t2 in timestamp with time zone)
         return pls_integer;
         function TF(mycur test_cur)
    return test_list pipelined
    parallel_enable(partition mycur by hash(a));
    end;
    create or replace package body test_pkg
    as
         * Calculate timestamp with timezone difference
         * in milliseconds
         function TZDeltaToMilliseconds(
              t1 in timestamp with time zone,
              t2 in timestamp with time zone)
         return pls_integer
         is
         begin
              return     (extract(hour from t2) - extract(hour from t1)) * 3600 * 1000
              +     (extract(minute from t2) - extract(minute from t1)) * 60 * 1000
              +     (extract(second from t2) - extract(second from t1)) * 1000;
         end TZDeltaToMilliseconds;
         function TF(mycur test_cur)
    return test_list pipelined
    parallel_enable(partition mycur by hash(a))
    is
              pragma autonomous_transaction;
              sid number;
              counter number(19,0) := 0;
              myrec test_rec;
              mytab test_tab;
              mytab2 test_list := test_list();
              t1 timestamp with time zone;
              t2 timestamp with time zone;
         begin
              t1 := systimestamp;
              select userenv('SID') into sid from dual;
              dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): enter');
              loop
                   fetch mycur into myRec;
                   exit when mycur%NOTFOUND;
                   mytab2.extend;
                   mytab2(mytab2.last) := test_obj(myRec.a, myRec.b, myRec.c);
              end loop;
              for i in mytab2.first..mytab2.last loop
                   -- attention: saves own SID in test_obj.a for indication to caller
                   --     how many sids have been involved
                   pipe row(test_obj(sid, mytab2(i).b, mytab2(i).c));
                   pipe row(test_obj(sid, mytab2(i).b, mytab2(i).c)); -- duplicate
                   pipe row(test_obj(sid, mytab2(i).b, mytab2(i).c)); -- duplicate once again
                   counter := counter + 1;
              end loop;
              t2 := systimestamp;
              insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'slave');
              commit;
              dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): exit, piped #' || counter || ' records');
         end;
    end;
    declare
         myList test_list := test_list();
         myList2 test_list := test_list();
         sids ton_t := ton_t();
         sid number;
         t1 timestamp with time zone;
         t2 timestamp with time zone;
    procedure LogPerfTable
    is
    type ton is table of number;
    type tot is table of timestamp with time zone;
              type clients_t is table of varchar2(256);
    sids ton;
    t1s tot;
    t2s tot;
              clients clients_t;
    deltaTime integer;
    btsPerSecond number(19,0);
    edrsPerSecond number(19,0);
    begin
    select sid, t1, t2, client bulk collect into sids, t1s, t2s, clients from perf_data order by client;
    if clients.count > 0 then
    for i in clients.FIRST .. clients.LAST loop
    deltaTime := test_pkg.TZDeltaToMilliseconds(t1s(i), t2s(i));
    if deltaTime = 0 then deltaTime := 1; end if;
    dbms_output.put_line(
    '[' || to_char(t1s(i), 'hh:mi:ss') ||
    '-' || to_char(t2s(i), 'hh:mi:ss') ||
    ']:' ||
    ' client ' || clients(i) || ' / sid #' || sids(i)
    end loop;
    end if;
    end LogPerfTable;
    begin
         select userenv('SID') into sid from dual;
         for i in 1..200000 loop
              myList.extend; myList(myList.last) := test_obj(i, sysdate, to_char(i+2));
         end loop;
         -- save into the real table
         insert into test_table select * from table(cast (myList as test_list));
         -- save into the tmp table
         insert into tmp_test_table select * from table(cast (myList as test_list));
         dbms_output.put_line(chr(10) || '(1) copy ''mylist'' to ''mylist2'' by streaming via table function...');
         delete from perf_data;
         t1 := systimestamp;
         select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
         from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from table(cast (myList as test_list)) tab)));
         t2 := systimestamp;
         insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
         LogPerfTable;
         dbms_output.put_line('... saved #' || myList2.count || ' records');
         select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
         dbms_output.put_line(chr(10) || '(2) copy temporary ''tmp_test_table'' to ''mylist2'' by streaming via table function:');
         delete from perf_data;
         t1 := systimestamp;
         select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
         from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from tmp_test_table tab)));
         t2 := systimestamp;
         insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
         LogPerfTable;
         dbms_output.put_line('... saved #' || myList2.count || ' records');
         select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
         dbms_output.put_line(chr(10) || '(3) copy physical ''test_table'' to ''mylist2'' by streaming via table function:');
         delete from perf_data;
         t1 := systimestamp;
         select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
         from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
         t2 := systimestamp;
         insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
         LogPerfTable;
         dbms_output.put_line('... saved #' || myList2.count || ' records');
         select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
    end;
    --------------------------- snap -------------------------------------------------------
    best regards,
    Frank

    Hello
    I think the delay you are seeing is down to choosing the partitioning method as HASH. When you specify anything other than ANY, an additional buffer sort is included in the execution plan...
    create or replace package test_pkg
    as
    type test_rec is record (
    a number(19,0),
    b timestamp with time zone,
    c varchar2(256)
    type test_tab is table of test_rec;
    type test_cur is ref cursor return test_rec;
    function TZDeltaToMilliseconds(
    t1 in timestamp with time zone,
    t2 in timestamp with time zone)
    return pls_integer;
    function TF(mycur test_cur)
    return test_list pipelined
    parallel_enable(partition mycur by hash(a));
    function TF_Any(mycur test_cur)
    return test_list pipelined
    parallel_enable(partition mycur by ANY);
    end;
    create or replace package body test_pkg
    as
    * Calculate timestamp with timezone difference
    * in milliseconds
    function TZDeltaToMilliseconds(
    t1 in timestamp with time zone,
    t2 in timestamp with time zone)
    return pls_integer
    is
    begin
    return (extract(hour from t2) - extract(hour from t1)) * 3600 * 1000
    + (extract(minute from t2) - extract(minute from t1)) * 60 * 1000
    + (extract(second from t2) - extract(second from t1)) * 1000;
    end TZDeltaToMilliseconds;
      function TF(mycur test_cur)
      return test_list pipelined
      parallel_enable(partition mycur by hash(a))
      is
      pragma autonomous_transaction;
        sid number;
        counter number(19,0) := 0;
        myrec test_rec;
        t1 timestamp with time zone;
        t2 timestamp with time zone;
      begin
        t1 := systimestamp;
        select userenv('SID') into sid from dual;
        dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): enter');
      loop
        fetch mycur into myRec;
        exit when mycur%NOTFOUND;
        -- attention: saves own SID in test_obj.a for indication to caller
        -- how many sids have been involved
        pipe row(test_obj(sid, myRec.b, myRec.c));
        pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate
        pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate once again
        counter := counter + 1;
      end loop;
      t2 := systimestamp;
      insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'slave');
      commit;
      dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): exit, piped #' || counter || ' records');
      end;
      function TF_any(mycur test_cur)
      return test_list pipelined
      parallel_enable(partition mycur by ANY)
      is
      pragma autonomous_transaction;
        sid number;
        counter number(19,0) := 0;
        myrec test_rec;
        t1 timestamp with time zone;
        t2 timestamp with time zone;
      begin
        t1 := systimestamp;
        select userenv('SID') into sid from dual;
        dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): enter');
        loop
          fetch mycur into myRec;
          exit when mycur%NOTFOUND;
          -- attention: saves own SID in test_obj.a for indication to caller
          -- how many sids have been involved
          pipe row(test_obj(sid, myRec.b, myRec.c));
          pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate
          pipe row(test_obj(sid, myRec.b, myRec.c)); -- duplicate once again
          counter := counter + 1;
        end loop;
        t2 := systimestamp;
        insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'slave');
        commit;
        dbms_output.put_line('test_pkg.TF( sid => '''|| sid || ''' ): exit, piped #' || counter || ' records');
      end;
    end;
    explain plan for
    select /*+ first_rows */ test_obj(a, b, c)
    from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
    select * from table(dbms_xplan.display);
    Plan hash value: 1037943675
    | Id  | Operation                             | Name       | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
    |   0 | SELECT STATEMENT                      |            |  8168 |  3972K|    20   (0)| 00:00:01 |        |      |            |
    |   1 |  PX COORDINATOR                       |            |       |       |            |          |        |      |            |
    |   2 |   PX SEND QC (RANDOM)                 | :TQ10001   |  8168 |  3972K|    20   (0)| 00:00:01 |  Q1,01 | P->S | QC (RAND)  |
    |   3 |    BUFFER SORT                        |            |  8168 |  3972K|            |          |  Q1,01 | PCWP |            |
    |   4 |     VIEW                              |            |  8168 |  3972K|    20   (0)| 00:00:01 |  Q1,01 | PCWP |            |
    |   5 |      COLLECTION ITERATOR PICKLER FETCH| TF         |       |       |            |          |  Q1,01 | PCWP |            |
    |   6 |       PX RECEIVE                      |            |   931K|   140M|   136   (2)| 00:00:02 |  Q1,01 | PCWP |            |
    |   7 |        PX SEND HASH                   | :TQ10000   |   931K|   140M|   136   (2)| 00:00:02 |  Q1,00 | P->P | HASH       |
    |   8 |         PX BLOCK ITERATOR             |            |   931K|   140M|   136   (2)| 00:00:02 |  Q1,00 | PCWC |            |
    |   9 |          TABLE ACCESS FULL            | TEST_TABLE |   931K|   140M|   136   (2)| 00:00:02 |  Q1,00 | PCWP |            |
    Note
       - dynamic sampling used for this statement
    explain plan for
    select /*+ first_rows */ test_obj(a, b, c)
    from table(test_pkg.TF_Any(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
    select * from table(dbms_xplan.display);
    Plan hash value: 4097140875
    | Id  | Operation                            | Name       | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
    |   0 | SELECT STATEMENT                     |            |  8168 |  3972K|    20   (0)| 00:00:01 |        |      |            |
    |   1 |  PX COORDINATOR                      |            |       |       |            |          |        |      |            |
    |   2 |   PX SEND QC (RANDOM)                | :TQ10000   |  8168 |  3972K|    20   (0)| 00:00:01 |  Q1,00 | P->S | QC (RAND)  |
    |   3 |    VIEW                              |            |  8168 |  3972K|    20   (0)| 00:00:01 |  Q1,00 | PCWP |            |
    |   4 |     COLLECTION ITERATOR PICKLER FETCH| TF_ANY     |       |       |            |          |  Q1,00 | PCWP |            |
    |   5 |      PX BLOCK ITERATOR               |            |   931K|   140M|   136   (2)| 00:00:02 |  Q1,00 | PCWC |            |
    |   6 |       TABLE ACCESS FULL              | TEST_TABLE |   931K|   140M|   136   (2)| 00:00:02 |  Q1,00 | PCWP |            |
    Note
       - dynamic sampling used for this statementI posted about it here a few years ago and I more recently posted a question on Asktom. Unfortunately Tom was not able to find a technical reason for it to be there so I'm still a little in the dark as to why it is needed. The original question I posted is here:
    Pipelined function partition by hash has extra sort#
    I ran your tests with HASH vs ANY and the results are in line with the observations above....
    declare
    myList test_list := test_list();
    myList2 test_list := test_list();
    sids ton_t := ton_t();
    sid number;
    t1 timestamp with time zone;
    t2 timestamp with time zone;
    procedure LogPerfTable
    is
    type ton is table of number;
    type tot is table of timestamp with time zone;
    type clients_t is table of varchar2(256);
    sids ton;
    t1s tot;
    t2s tot;
    clients clients_t;
    deltaTime integer;
    btsPerSecond number(19,0);
    edrsPerSecond number(19,0);
    begin
    select sid, t1, t2, client bulk collect into sids, t1s, t2s, clients from perf_data order by client;
    if clients.count > 0 then
    for i in clients.FIRST .. clients.LAST loop
    deltaTime := test_pkg.TZDeltaToMilliseconds(t1s(i), t2s(i));
    if deltaTime = 0 then deltaTime := 1; end if;
    dbms_output.put_line(
    '[' || to_char(t1s(i), 'hh:mi:ss') ||
    '-' || to_char(t2s(i), 'hh:mi:ss') ||
    ']:' ||
    ' client ' || clients(i) || ' / sid #' || sids(i)
    end loop;
    end if;
    end LogPerfTable;
    begin
    select userenv('SID') into sid from dual;
    for i in 1..200000 loop
    myList.extend; myList(myList.last) := test_obj(i, sysdate, to_char(i+2));
    end loop;
    -- save into the real table
    insert into test_table select * from table(cast (myList as test_list));
    -- save into the tmp table
    insert into tmp_test_table select * from table(cast (myList as test_list));
    dbms_output.put_line(chr(10) || '(1) copy ''mylist'' to ''mylist2'' by streaming via table function...');
    delete from perf_data;
    t1 := systimestamp;
    select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
    from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from table(cast (myList as test_list)) tab)));
    t2 := systimestamp;
    insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
    LogPerfTable;
    dbms_output.put_line('... saved #' || myList2.count || ' records');
    select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
    dbms_output.put_line(chr(10) || '(2) copy temporary ''tmp_test_table'' to ''mylist2'' by streaming via table function:');
    delete from perf_data;
    t1 := systimestamp;
    select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
    from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from tmp_test_table tab)));
    t2 := systimestamp;
    insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
    LogPerfTable;
    dbms_output.put_line('... saved #' || myList2.count || ' records');
    select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
    dbms_output.put_line(chr(10) || '(3) copy physical ''test_table'' to ''mylist2'' by streaming via table function:');
    delete from perf_data;
    t1 := systimestamp;
    select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
    from table(test_pkg.TF(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
    t2 := systimestamp;
    insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
    LogPerfTable;
    dbms_output.put_line('... saved #' || myList2.count || ' records');
    select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
    dbms_output.put_line(chr(10) || '(4) copy temporary ''tmp_test_table'' to ''mylist2'' by streaming via table function ANY:');
    delete from perf_data;
    t1 := systimestamp;
    select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
    from table(test_pkg.TF_any(CURSOR(select /*+ parallel(tab,5) */ * from tmp_test_table tab)));
    t2 := systimestamp;
    insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
    LogPerfTable;
    dbms_output.put_line('... saved #' || myList2.count || ' records');
    select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
    dbms_output.put_line(chr(10) || '(5) copy physical ''test_table'' to ''mylist2'' by streaming via table function using ANY:');
    delete from perf_data;
    t1 := systimestamp;
    select /*+ first_rows */ test_obj(a, b, c) bulk collect into myList2
    from table(test_pkg.TF_any(CURSOR(select /*+ parallel(tab,5) */ * from test_table tab)));
    t2 := systimestamp;
    insert into perf_data (sid, t1, t2, client) values(sid, t1, t2, 'master');
    LogPerfTable;
    dbms_output.put_line('... saved #' || myList2.count || ' records');
    select distinct(tab.a) bulk collect into sids from table(cast (myList2 as test_list)) tab;
    end;
    (1) copy 'mylist' to 'mylist2' by streaming via table function...
    test_pkg.TF( sid => '918' ): enter
    test_pkg.TF( sid => '918' ): exit, piped #200000 records
    [01:40:19-01:40:29]: client master / sid #918
    [01:40:19-01:40:29]: client slave / sid #918
    ... saved #600000 records
    (2) copy temporary 'tmp_test_table' to 'mylist2' by streaming via table function:
    [01:40:31-01:40:36]: client master / sid #918
    [01:40:31-01:40:32]: client slave / sid #659
    [01:40:31-01:40:32]: client slave / sid #880
    [01:40:31-01:40:32]: client slave / sid #1045
    [01:40:31-01:40:32]: client slave / sid #963
    [01:40:31-01:40:32]: client slave / sid #712
    ... saved #600000 records
    (3) copy physical 'test_table' to 'mylist2' by streaming via table function:
    [01:40:37-01:41:05]: client master / sid #918
    [01:40:37-01:40:42]: client slave / sid #738
    [01:40:37-01:40:42]: client slave / sid #568
    [01:40:37-01:40:42]: client slave / sid #618
    [01:40:37-01:40:42]: client slave / sid #659
    [01:40:37-01:40:42]: client slave / sid #963
    ... saved #3000000 records
    (4) copy temporary 'tmp_test_table' to 'mylist2' by streaming via table function ANY:
    [01:41:12-01:41:16]: client master / sid #918
    [01:41:12-01:41:16]: client slave / sid #712
    [01:41:12-01:41:16]: client slave / sid #1045
    [01:41:12-01:41:16]: client slave / sid #681
    [01:41:12-01:41:16]: client slave / sid #754
    [01:41:12-01:41:16]: client slave / sid #880
    ... saved #600000 records
    (5) copy physical 'test_table' to 'mylist2' by streaming via table function using ANY:
    [01:41:18-01:41:38]: client master / sid #918
    [01:41:18-01:41:38]: client slave / sid #681
    [01:41:18-01:41:38]: client slave / sid #712
    [01:41:18-01:41:38]: client slave / sid #754
    [01:41:18-01:41:37]: client slave / sid #880
    [01:41:18-01:41:38]: client slave / sid #1045
    ... saved #3000000 recordsHTH
    David

  • Importing and Exporting Data with a Clob datatype with HTML DB

    I would like to know what to do and what to be aware of when Importing and Exporting data with a Clob Datatype with HTML DB?

    Colin - what kind of import/export operation would that be, which pages are you referring to?
    Scott

  • Need some help with the Table Function Operator

    I'm on OWB 10gR2 for Sun/Solaris 10 going against some 10gR2 DB's...
    I've been searching up and down trying to figure out how to make OWB use a Table Function (TF) which will JOIN with another table; allowing a column of the joined table to be a parameter in to the TF. I can't seem to get it to work. I'm able to get this to work in regular SQL, though. Here's the setup:
    -- Source Table:
    DROP TABLE "ZZZ_ROOM_MASTER_EX";
    CREATE TABLE "ZZZ_ROOM_MASTER_EX"
    ( "ID" NUMBER(8,0),
    "ROOM_NUMBER" VARCHAR2(200),
    "FEATURES" VARCHAR2(4000)
    -- Example Data:
    Insert into ZZZ_ROOM_MASTER_EX (ID,ROOM_NUMBER,FEATURES) values (1,'Room 1',null);
    Insert into ZZZ_ROOM_MASTER_EX (ID,ROOM_NUMBER,FEATURES) values (2,'Room 2',null);
    Insert into ZZZ_ROOM_MASTER_EX (ID,ROOM_NUMBER,FEATURES) values (3,'Room 3','1,1;2,3;');
    Insert into ZZZ_ROOM_MASTER_EX (ID,ROOM_NUMBER,FEATURES) values (4,'Room 4','5,2;5,4;');
    Insert into ZZZ_ROOM_MASTER_EX (ID,ROOM_NUMBER,FEATURES) values (5,'Room 5',' ');
    -- Destination Table:
    DROP TABLE "ZZZ_ROOM_FEATURES_EX";
    CREATE TABLE "ZZZ_ROOM_FEATURES_EX"
    ( "ROOM_NUMBER" VARCHAR2(200),
    "FEATUREID" NUMBER(8,0),
    "QUANTITY" NUMBER(8,0)
    -- Types for output table:
    CREATE OR REPLACE TYPE FK_Row_EX AS OBJECT
    ID NUMBER(8,0),
    QUANTITY NUMBER(8,0)
    CREATE OR REPLACE TYPE FK_Table_EX AS TABLE OF FK_Row_EX;
    -- Package Dec:
    CREATE OR REPLACE
    PACKAGE ZZZ_SANDBOX_EX IS
    FUNCTION UNFK(inputString VARCHAR2) RETURN FK_Table_EX;
    END ZZZ_SANDBOX_EX;
    -- Package Body:
    CREATE OR REPLACE
    PACKAGE BODY ZZZ_SANDBOX_EX IS
    FUNCTION UNFK(inputString VARCHAR2) RETURN FK_Table_EX
    AS
    RETURN_VALUE FK_Table_EX := FK_Table_EX();
    i NUMBER(8,0) := 0;
    BEGIN
    -- TODO: Put some real code in here that will actually read the
    -- input string, parse it out, and put data in to RETURN_VALUE
    WHILE(i < 3) LOOP
    RETURN_VALUE.EXTEND;
    RETURN_VALUE(RETURN_VALUE.LAST) := FK_Row_EX(4, 5);
    i := i + 1;
    END LOOP;
    RETURN RETURN_VALUE;
    END UNFK;
    END ZZZ_SANDBOX_EX;
    I've got a source system built by lazy DBA's and app developers who decided to store foreign keys for many-to-many relationships as delimited structures in driving tables. I need to build a generic table function to parse this data and return it as an actual table. In my example code, I don't actually have the parsing part written yet (I need to see how many different formats the source system uses first) so I just threw in some stub code to generate a few rows of 4's and 5's to return.
    I can get the data from my source table to my destination table using the following SQL statement:
    -- from source table joined with table function
    INSERT INTO ZZZ_ROOM_FEATURES_EX(
    ROOM_NUMBER,
    FEATUREID,
    QUANTITY)
    SELECT
    ZZZ_ROOM_MASTER_EX.ROOM_NUMBER,
    UNFK.ID,
    UNFK.QUANTITY
    FROM
    ZZZ_ROOM_MASTER_EX,
    TABLE(ZZZ_SANDBOX_EX.UNFK(ZZZ_ROOM_MASTER_EX.FEATURES)) UNFK
    Now, the big question is--how do I do this from OWB? I've tried several different variations of my function and settings in OWB to see if I can build a single SELECT statement which joins a regular table with a table function--but none of them seem to work, I end up getting SQL generated that won't compile because it doesn't see the source table right:
    INSERT
    /*+ APPEND PARALLEL("ZZZ_ROOM_FEATURES_EX") */
    INTO
    "ZZZ_ROOM_FEATURES_EX"
    ("ROOM_NUMBER",
    "FEATUREID",
    "QUANTITY")
    (SELECT
    "ZZZ_ROOM_MASTER_EX"."ROOM_NUMBER" "ROOM_NUMBER",
    "INGRP2"."ID" "ID_1",
    "INGRP2"."QUANTITY" "QUANTITY"
    FROM
    (SELECT
    "UNFK"."ID" "ID",
    "UNFK"."QUANTITY" "QUANTITY"
    FROM
    TABLE ( "ZZZ_SANDBOX_EX"."UNFK2" ("ZZZ_ROOM_MASTER_EX"."FEATURES")) "UNFK") "INGRP2",
    "ZZZ_ROOM_MASTER_EX" "ZZZ_ROOM_MASTER_EX"
    As you can see, it's trying to create a sub-query in the FROM clause--causing it to just ask for "ZZZ_ROOM_MASTER_EX"."FEATURES" as an input--which isn't available because it's outside of the sub-query!
    Is this some kind of bug with the code generator or am I doing something seriously wrong here? Any help will be greatly appreciated!

    Hello Everybody!
    Thank you for all your response!
    I had changes this work area into Internal table and changed the select query. PLease let me know if this causes any performance issues?
    I had created a Z table with the following fields :
    ZADS :
    MANDT
    VKORG
    ABGRU.
    I had written a select query as below :
    I had removed the select single and insted of using the Structure it_rej, I had changed it into Internal table 
    select vkorg abgru from ZADS into it_rej.
    Earlier :
    IT_REJ is a Work area:
    DATA : BEGIN OF IT_REJ,
    VKORG TYPE VBAK-VKORG,
    ABGRU TYPE VBAP-ABGRU,
    END OF IT_REJ.
    Now :
    DATA : BEGIN OF IT_REJ occurs 0,
    VKORG TYPE VBAK-VKORG,
    ABGRU TYPE VBAP-ABGRU,
    END OF IT_REJ.
    I guess this will fix the issue correct?
    PLease suggest!
    Regards,
    Developer.

  • Query performance improvement using pipelined table function

    Hi,
    I have got two select queries one is like...
    select * from table
    another is using pielined table function
    select *
    from table(pipelined_function(cursor(select * from table)))
    which query will return result set more faster????????
    suggest methods for retrieving dataset more faster (using pipelined table function) than a normal select query.
    rgds
    somy

    Compare the performance between these solutions:
    create table big as select * from all_objects;
    First test the performance of a normal select statement:
    begin
      for r in (select * from big) loop
       null;
      end loop;
    end;
    /Second a pipelined function:
    create type rc_vars as object 
    (OWNER  VARCHAR2(30)
    ,OBJECT_NAME     VARCHAR2(30));
    create or replace type rc_vars_table as table of  rc_vars ;
    create or replace
    function rc_get_vars
    return rc_vars_table
    pipelined
    as
      cursor c_aobj
             is
             select owner, object_name
             from   big;
      l_aobj c_aobj%rowtype;
    begin
      for r_aobj in c_aobj loop
        pipe row(rc_vars(r_aobj.owner,r_aobj.object_name));
      end loop;
      return;
    end;
    /Test the performance of the pipelined function:
    begin
      for r in (select * from table(rc_get_vars)) loop
       null;
      end loop;
    end;
    /On my system the simple select-statement is 20 times faster.
    Correction: It is 10 times faster, not 20.
    Message was edited by:
    wateenmooiedag

  • Parallel pipelined table function, autonomous_transaction to global tmp tab

    Hi,
    i try to speed up my parallel pipelined table function and switch from pl/sql collection to global temporary table inside.
    This requires to use PRAGMA AUTONOMOUS_TRANSACTION (and commit), because inserting into global temporary table (DML)
    within select - for invoking the table function - is not allowed without.
    As a consequence of commit it next requires to have on commit preserve rows for the global temporary table.
    Now:
    Inserts into the global temporary table are done - indicated by sql%rowcount.
    But a select afterwards doesn't show any record anymore.
    Here is a program to demonstrate it:
    set serveroutput on;
    drop type TestTableOfNumber_t;
    create or replace type TestTableOfNumber_t is table of number;
    drop type TestStatusList;
    drop type TestStatusObj;
    create or replace type TestStatusObj as object(
         sid number,
         ctr1 number,
         ctr2 number,
         ctr3 number
    create or replace type TestStatusList is table of TestStatusObj;
    drop table TestTmpTable;
    create global temporary table TestTmpTable (
         value     number
    ) on commit preserve rows;
    create or replace package test_pkg
    as
         type TestStatusRec is record (
              sid number,
              ctr1 number,
              ctr2 number,
              ctr3 number
         type TestStatusTab is table of TestStatusRec;
         function FillTmpTable(id in varchar2)
         return TestStatusRec;
         FUNCTION ptf (p_cursor  IN  sys_refcursor)
         RETURN TestStatusList PIPELINED
         PARALLEL_ENABLE(PARTITION p_cursor BY any);
    end;
    create or replace package body test_pkg
    as
         function FillTmpTable(id in varchar2)
         return TestStatusRec
         is
              PRAGMA AUTONOMOUS_TRANSACTION;
              result TestStatusRec;
              sid number;
              type ton is table of number;
              tids TestTableOfNumber_t := TestTableOfNumber_t();
              records number := 0;
         begin
              select userenv('SID') into sid from dual;
              result.sid := sid;
              delete from TestTmpTable;
              for i in 1..100 loop
                   tids.extend;
                   tids(tids.last) := i;
              end loop;
              forall i in 1..tids.count
                   insert into TestTmpTable (value) values (tids(i));
              -- get number of records inserted
              records := sql%rowcount;
              result.ctr1 := records;
              -- retrieve again before commit
              select count(*) into records from TestTmpTable;
              result.ctr2 := records;
              commit;
              -- retrieve again after commit
              select count(*) into records from TestTmpTable;
              result.ctr3 := records;
              return result;
         end;
           FUNCTION ptf (p_cursor  IN  sys_refcursor)
         RETURN TestStatusList PIPELINED
         PARALLEL_ENABLE(PARTITION p_cursor BY any)
         IS
              rec test_pkg.TestStatusRec;
              value number;
              sid number;
              ctr integer := 0;
         BEGIN
              select userenv('SID') into sid from dual;
              rec := FillTmpTable('IN PTF');
              LOOP
                   FETCH p_cursor into value;
                   EXIT WHEN p_cursor%NOTFOUND;
                   ctr := ctr + 1;     
              END LOOP;
              -- as a result i am only interested in the results of FillTmpTable():
              PIPE ROW (TestStatusObj(rec.sid, rec.ctr1, rec.ctr2, rec.ctr3));
                  RETURN;
         END;
    end;
    declare
         tons TestTableOfNumber_t;
         counts TestTableOfNumber_t;
         status test_pkg.TestStatusRec;
         statusList test_pkg.TestStatusTab;
    begin
         status := test_pkg.FillTmpTable('MAIN');
         dbms_output.put_line('main thread:'
              || ' sid #' || status.sid
              || ' / #' || status.ctr1 || ' inserted '
              || ' / #' || status.ctr2 || ' before commit'
              || ' / #' || status.ctr3 || ' after commit');     
         select value bulk collect into tons from TestTmpTable;
         select * bulk collect into statusList from TABLE(test_pkg.ptf(CURSOR(select /*+ parallel(tab,2) */ value from TestTmpTable tab)));
         for i in 1..StatusList.count loop
              dbms_output.put_line('worker thread #' || i  || ':'
              || ' sid #' || statusList(i).sid
              || ' / #' || statusList(i).ctr1 || ' inserted '
              || ' / #' || statusList(i).ctr2 || ' before commit'
              || ' / #' || statusList(i).ctr3 || ' after commit');
         end loop;
    end;
    /The output is:
    main thread: sid #881 / #100 inserted  / #100 before commit / #100 after commit
    worker thread #1: sid #421 / #100 inserted  / #0 before commit / #0 after commit
    worker thread #2: sid #321 / #100 inserted  / #0 before commit / #0 after commitThe 1st line is for the main thread invoking FillTmpTable().
    The next #2 lines are for the worker threads of the parallel pipelined table function for invoking the same FillTmpTable().
    For the main thread everything is as expected.
    But for the worker threads the logs for before commit and after commit both give #0 for the number of available records in the global temporary table.
    However all indicate #100 for the SQL insert
    regards,
    Frank
    Edited by: user8704911 on Jul 7, 2011 10:13 AM
    Edited by: user8704911 on Jul 7, 2011 10:20 AM
    Edited by: user8704911 on Jul 7, 2011 10:27 AM

    SQL> select * from v$version;
    BANNER
    Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
    PL/SQL Release 11.1.0.7.0 - Production
    CORE    11.1.0.7.0      Production
    TNS for Linux: Version 11.1.0.7.0 - Production
    NLSRTL Version 11.1.0.7.0 - Production
    SQL> set serveroutput on;
    SQL> drop type TestTableOfNumber;
    drop type TestTableOfNumber
    ERROR at line 1:
    ORA-04043: object TESTTABLEOFNUMBER does not exist
    SQL> /
    drop type TestTableOfNumber
    ERROR at line 1:
    ORA-04043: object TESTTABLEOFNUMBER does not exist
    SQL> 
    SQL> create or replace type TestTableOfNumber_t is table of number;
      2  /
    Type created.
    SQL> 
    SQL> drop type TestStatusObj;
    drop type TestStatusObj
    ERROR at line 1:
    ORA-04043: object TESTSTATUSOBJ does not exist
    SQL> /
    drop type TestStatusObj
    ERROR at line 1:
    ORA-04043: object TESTSTATUSOBJ does not exist
    SQL> 
    SQL> create or replace type TestStatusObj as object(
      2   sid number,
      3   ctr1 number,
      4   ctr2 number,
      5   ctr3 number
      6  );
      7  /
    Type created.
    SQL> 
    SQL> drop type TestStatusList;
    drop type TestStatusList
    ERROR at line 1:
    ORA-04043: object TESTSTATUSLIST does not exist
    SQL> /
    drop type TestStatusList
    ERROR at line 1:
    ORA-04043: object TESTSTATUSLIST does not exist
    SQL> 
    SQL> create or replace type TestStatusList is table of TestStatusObj;
      2  /
    Type created.
    SQL> 
    SQL> drop table TestTmpTable;
    drop table TestTmpTable
    ERROR at line 1:
    ORA-00942: table or view does not exist
    SQL> /
    drop table TestTmpTable
    ERROR at line 1:
    ORA-00942: table or view does not exist
    SQL> 
    SQL> create global temporary table TestTmpTable (
      2   value number
      3  ) on commit preserve rows;
    Table created.
    SQL> /
    create global temporary table TestTmpTable (
    ERROR at line 1:
    ORA-00955: name is already used by an existing object
    SQL> 
    SQL> create or replace package test_pkg
      2  as
      3  
      4   type TestStatusRec is record (
      5    sid number,
      6    ctr1 number,
      7    ctr2 number,
      8    ctr3 number
      9   );
    10  
    11   type TestStatusTab is table of TestStatusRec;
    12  
    13   function FillTmpTable(id in varchar2)
    14   return TestStatusRec;
    15  
    16   FUNCTION ptf (p_cursor  IN  sys_refcursor)
    17   RETURN TestStatusList PIPELINED
    18   PARALLEL_ENABLE(PARTITION p_cursor BY any);
    19  
    20  end;
    21  /
    Package created.
    SQL> 
    SQL> create or replace package body test_pkg
      2  as
      3  
      4   function FillTmpTable(id in varchar2)
      5   return TestStatusRec
      6   is
      7    PRAGMA AUTONOMOUS_TRANSACTION;
      8  
      9    result TestStatusRec;
    10  
    11    sid number;
    12  
    13    type ton is table of number;
    14    tids TestTableOfNumber_t := TestTableOfNumber_t();
    15  
    16    records number := 0;
    17   begin
    18    select userenv('SID') into sid from dual;
    19    result.sid := sid;
    20  
    21    delete from TestTmpTable;
    22  
    23    for i in 1..100 loop
    24     tids.extend;
    25     tids(tids.last) := i;
    26    end loop;
    27  
    28    forall i in 1..tids.count
    29     insert into TestTmpTable (value) values (tids(i));
    30  
    31    -- get number of records inserted
    32    records := sql%rowcount;
    33    result.ctr1 := records;
    34  
    35    -- retrieve again before commit
    36    select count(*) into records from TestTmpTable;
    37    result.ctr2 := records;
    38  
    39    commit;
    40  
    41    -- retrieve again after commit
    42    select count(*) into records from TestTmpTable;
    43    result.ctr3 := records;
    44  
    45    return result;
    46   end;
    47  
    48     FUNCTION ptf (p_cursor  IN  sys_refcursor)
    49   RETURN TestStatusList PIPELINED
    50   PARALLEL_ENABLE(PARTITION p_cursor BY any)
    51   IS
    52    rec test_pkg.TestStatusRec;
    53    value number;
    54    sid number;
    55    ctr integer := 0;
    56   BEGIN
    57    select userenv('SID') into sid from dual;
    58    rec := FillTmpTable('IN PTF');
    59    LOOP
    60     FETCH p_cursor into value;
    61     EXIT WHEN p_cursor%NOTFOUND;
    62     ctr := ctr + 1;
    63    END LOOP;
    64  
    65    -- as a result i am only interested in the results of FillTmpTable():
    66    PIPE ROW (TestStatusObj(rec.sid, rec.ctr1, rec.ctr2, rec.ctr3));
    67  
    68        RETURN;
    69   END;
    70  end;
    71  /
    Package body created.
    SQL> 
    SQL> declare
      2   tons TestTableOfNumber_t;
      3   counts TestTableOfNumber_t;
      4   status test_pkg.TestStatusRec;
      5   statusList test_pkg.TestStatusTab;
      6  begin
      7   status := test_pkg.FillTmpTable('MAIN');
      8   dbms_output.put_line('main thread:'
      9    || ' sid #' || status.sid
    10    || ' / #' || status.ctr1 || ' inserted '
    11    || ' / #' || status.ctr2 || ' before commit'
    12    || ' / #' || status.ctr3 || ' after commit');
    13  
    14   select value bulk collect into tons from TestTmpTable;
    15  
    16   select * bulk collect into statusList from TABLE(test_pkg.ptf(CURSOR(select /*+ parallel(tab,2
    ) */ value from TestTmpTable tab)));
    17  
    18   for i in 1..StatusList.count loop
    19    dbms_output.put_line('worker thread #' || i  || ':'
    20    || ' sid #' || statusList(i).sid
    21    || ' / #' || statusList(i).ctr1 || ' inserted '
    22    || ' / #' || statusList(i).ctr2 || ' before commit'
    23    || ' / #' || statusList(i).ctr3 || ' after commit');
    24   end loop;
    25  
    26  end;
    27  /
    main thread: sid #1023 / #100 inserted  / #100 before commit / #100 after commit
    worker thread #1: sid #1045 / #100 inserted  / #100 before commit / #100 after
    commit
    worker thread #2: sid #1019 / #100 inserted  / #100 before commit / #100 after
    commit
    PL/SQL procedure successfully completed.
    SQL> I am getting a different result.
    Regards
    Raj

  • Distributed queries+pipelined table function

    HI friends,
    can i get better performance for distributed queries if i use pipelined table function.I have got my data distribued across three different databases.
    thanx
    somy

    You will need to grant EXECUTE access on the pipelined table function to whatever users want it. When other users call this function, they may need to prefix the schema owner (i.e. <<owner>>.getValue('001') ) unless you've set up the appropriate synonym.
    What version of SQL*Plus do you have on the NT machine?
    Justin
    Distributed Database Consulting, Inc.
    http://www.ddbcinc.com/askDDBC

  • Using long vs. clob datatype with Oracle 8.1.7 and interMedia

    I am trying to determine the best datatype to use for a column I
    wish to search using the interMedia contains() function. I am
    developing a 100% java application using Oracle 8.1.7 on Linux.
    I'd prefer to use the standard JDBC API's for PreparedStatement,
    and not have to use Oracle extensions if possible. I've
    discovered that there are limitations in the support for LOB's
    in Oracle's 100% java driver. The PreparedStatement methods
    like setAsciiStream() and setCharacterStream() are documented to
    have flaws that may result in the corruption of data. I have
    also noticed that socket exceptions sometimes occur when a large
    amount of data is transferred. If I use the long datatype for
    my table column, the setCharacterStream() method seems to
    transfer the data correctly. When I try to search this column
    using the interMedia contains() function, I get strange
    results. If I run my search on Oracle 8.1.6 for Windows, the
    results seem to be correct. If I run the same search on Oracle
    8.1.7 for Linux, the results are usually incorrect. The same
    searches seem to work correctly on both boxes when I change the
    column type from long to clob. Using the clob type may not be
    an option for me since the standard JDBC API's to transfer data
    into internal clob fields are broken, and I may need to stick
    with standard JDBC API's. My customer wishes to purchase a
    version of Oracle for Linux that will allow us to implement the
    search capability he requires. Any guidance would be greatly
    appreciated.

    I've finally solved it!
    I downloaded the following jre from blackdown:
    jre118_v3-glibc-2.1.3-DYNMOTIF.tar.bz2
    It's the only one that seems to work (and god, have I tried them all!)
    I've no idea what the DYNMOTIF means (apart from being something to do with Motif - but you don't have to be a linux guru to work that out ;)) - but, hell, it works.
    And after sitting in front of this machine for 3 days trying to deal with Oracle's, frankly PATHETIC install, that's so full of holes and bugs, that's all I care about..
    The one bundled with Oracle 8.1.7 doesn't work with Linux redhat 6.2EE.
    Don't oracle test their software?
    Anyway I'm happy now, and I'm leaving this in case anybody else has the same problem.
    Thanks for everyone's help.

  • CLOB Datatype with JDBC Adapter

    Hi,
    we try to fill a Clob Datatype to JDBC Database.
    We try 2 ways with the JDBC Adapter:
    action="SQL_DML" with an SQL Statment and $placeholders$
    But how can i say the key element that it is a CLOB type?
    He used this a VARCHAR and there a not more than 4k Chars allowed.
    second way is action="EXECUTE" to call a Stored Procedure, but there we got the error that CLOB type is an Unsupported feature.
    Any Idea?
    Regards,
    Robin
    Message was edited by: Robin Schroeder

    Ok i will check this...
    But i'm right when i say that the only way to fill CLOB Type is to use a Stored Procedure ?
    or is there any possibility to do this with action="SQL_DML" ?
    Regards,
    Robin

  • Duplicate Rows In Oracle Pipelined Table Functions

    Hi fellow oracle users,
    I am trying to create an Oracle piplined table function that contains duplicate records. Whenever I try to pipe the same record twice, the duplicate record does not show up in the resulting pipelined table.
    Here's a sample piece of SQL:
    /* Type declarations */
    TYPE MY_RECORD IS RECORD(
    MY_NUM INTEGER
    TYPE MY_TABLE IS TABLE OF MY_RECORD;
    /* Pipelined function declaration */
    FUNCTION MY_FUNCTION RETURN MY_TABLE PIPELINED IS
    V_RECORD MY_RECORD;
    BEGIN
    -- insert first record
    V_RECORD.MY_NUM = 1;
    PIPE ROW (V_RECORD);
    -- insert second duplicate record
    V_RECORD.MY_NUM = 1;
    PIPE ROW (V_RECORD);
    -- return piplined table
    RETURN;
    END;
    /* Statement to query pipelined function */
    SELECT * FROM TABLE( MY_FUNCTION ); -- for some reason this only returns one record instead of two
    I am trying to get the duplicate row to show up in the select statement. Any help would be greatly appreciated.

    Can you provide actual output from an SQL*Plus prompt trying this? I don't see the same behavior
    SQL> SELECT * FROM V$VERSION;
    BANNER
    Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
    PL/SQL Release 10.2.0.4.0 - Production
    CORE    10.2.0.4.0      Production
    TNS for 64-bit Windows: Version 10.2.0.4.0 - Production
    NLSRTL Version 10.2.0.4.0 - Production
    SQL> CREATE TYPE MY_RECORD IS OBJECT(MY_NUM INTEGER);
      2  /
    Type created.
    SQL> CREATE TYPE MY_TABLE IS TABLE OF MY_RECORD;
      2  /
    Type created.
    SQL> CREATE OR REPLACE FUNCTION MY_FUNCTION
      2  RETURN MY_TABLE
      3  PIPELINED
      4          AS
      5                  V_RECORD        MY_RECORD;
      6          BEGIN
      7                  V_RECORD.MY_NUM := 1;
      8                  PIPE ROW(V_RECORD);
      9
    10                  V_RECORD.MY_NUM := 1;
    11                  PIPE ROW(V_RECORD);
    12
    13                  RETURN;
    14          END;
    15  /
    Function created.
    SQL> SELECT * FROM TABLE(MY_FUNCTION);
                  MY_NUM
                       1
                       1

  • Materialized View with OLAP table function

    Hi,
    I am trying to materialize OLAP cubes into relational materialized views which works quite fine. After a few loadings in background in parallel with Database Jobs and DBMS_MVIEW package the peformance is getting poor. Steps I am performing:
    1. Generate materialized view as DEFERRED and COMPLETE refresh
    2. Generate database Jobs for refreshing views with DBMS_MVIEW.REFRESH function
    3. Running Jobs in background
    I have loading times the first time 10min after then over 4 hours. I also tried with ATOMIC_REFRESH=FALSE but the same result. Database is running in ARCHIVE LOGGING. Can this degrade the performance?
    Any ideas?
    Thanks,
    Christian

    Hi,
    yes thats correct. I am creating MVs in 10.2.0.3
    Here is an example:
    CREATE MATERIALIZED VIEW "FCRSGX"."MV_F_ICCC_C11"
    ORGANIZATION HEAP PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 COMPRESS NOLOGGING
    STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
    PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
    TABLESPACE "FCRSGX_CONSO_RELATIONAL"
    BUILD DEFERRED
    USING INDEX
    REFRESH COMPLETE ON DEMAND
    USING DEFAULT LOCAL ROLLBACK SEGMENT
    DISABLE QUERY REWRITE
    AS SELECT ENTITY, REVE_ICC, RP_ICC, MV_ICC, PERIOD, MEASURE, AMOUNT, R2C
    FROM TABLE(OLAP_TABLE('FCRSGX.CONSODATA DURATION SESSION',
    DIMENSION ENTITY as varchar2(8) FROM ENTITY
    DIMENSION REVE_ICC as varchar2(8) FROM REVE_ICC
    DIMENSION RP_ICC as varchar2(8) FROM RP_ICC
    DIMENSION MV_ICC as varchar2(8) FROM MV_ICC
    DIMENSION PERIOD as varchar2(8) FROM GMONTH
    DIMENSION MEASURE as varchar2(30) FROM EXPR
    MEASURE AMOUNT as number FROM ICCC.C11
    LOOP CMPE.ICCC.C11
    ROW2CELL R2C '))
    WHERE OLAP_CONDITION(r2c, 'lmt entity to CMPE.ICCC.C11')=1
    AND OLAP_CONDITION(r2c, 'lmt reve_icc to CMPE.ICCC.C11')=1
    AND OLAP_CONDITION(r2c, 'lmt mmonth to sapload.per eq y')=1
    AND OLAP_CONDITION(r2c, 'lmt gmonth to charl(mmonth) ')=1
    AND OLAP_CONDITION(r2c, 'lmt rp_icc to CMP.ICCC.C11 ')=1
    AND OLAP_CONDITION(r2c, 'lmt mv_icc to CMP.ICCC.C11 ')=1
    AND OLAP_CONDITION(r2c, 'lmt expr to ''F.ICCC.C11'' ')=1
    MODEL
    DIMENSION BY(ENTITY,REVE_ICC,RP_ICC,MV_ICC,PERIOD,MEASURE)
    MEASURES(AMOUNT,R2C)
    RULES UPDATE SEQUENTIAL ORDER()
    ;

Maybe you are looking for

  • Does anyone know how to use Retropect back soft ware - I need help with it

    Is there anyone familiar with Retrospect Backup software here who might be able to help me with the following problem ? My 2007 iMac  with the tiger 10.4.11 OS suddenly crashed exactly two weeks ago when I told the trash to empty. The reason was that

  • How do I back up my itunes account?

    How do you backup an itunes account?  When my computer crashed and I got a new computer several years ago, Apple helped me retrieve my purchases. I was told to always back up my account.  I haven't done it in a long while, and now there doesn't appea

  • LDB FMF + supress standard selection screen

    Hi, I had developped a specific report using the LDB FMF, but i want to supress the standard selection screen. i want to use my only own specific selection screen. How to do that ? Best regards

  • Best practices to modify process chain

    Hi, What is the best practice to modify the  process chain whether in in the production or transport back to the dev. Does Query performing tuning setting should be done in production like read modes,cache settings. Thanks nikhil

  • Utility method

    I know PreparedStatements help prevent SQL injection and ticks. The only thing I notice is it doesnt handle greater than and less than such as < with a > entry in a form. When they are entered into a form that populates oracle it seems to disappear w