Fetch cursor with a variable column number

Hello guys,
this is the first time I write to this forum, as far as I remember. hence, if this is not the right place to ask this question, please point me to the right resource.
I have the following Procedure (the function split splits a string into an array):
BEGIN
/* SPLIT IN GROUPS AND BUILD THE PARAMETER STRINGS */
tokens_in := string_fnc.split(in_groups, '.');
for i in 1..tokens_in.count loop
IDX_REM := i;
sql_par1 := sql_par1 || ', GRP' || i || '.NAME "GROUP_' || i || '"';
sql_par2 := sql_par2 || ', DEV_XCSA.WFA_GROUP GRP' || i;
IF i = 1 THEN
sql_par3 := sql_par3 || ' AND S.ID = GRP1.FK_PARENT_SEC_ID ';
ELSE
sql_par3 := sql_par3 || ' AND GRP' || i || '.FK_PARENT_GROUP_ID ( + ) = GRP' || (i-1) || '.ID';
END IF;
end loop;
sql_par3 := sql_par3 || ' AND SGQ.FK_GROUP_ID ( + ) = GRP' || IDX_REM || '.ID';
/* BUILD THE QUERY STRING */
sql_stmt := 'SELECT A.NAME "APPRAISAL" , AQ.NAME "PROJECT" , S.NAME "SECTION"';
sql_stmt := sql_stmt || sql_par1;
sql_stmt := sql_stmt || ', SGQ.NAME "QUESTION" , SGQ.VALUE "ANSWER"     FROM DEV_XCSA.WFA_APPRAISAL A, DEV_XCSA.WFA_QUESTIONNAIRE AQ, DEV_XCSA.WFA_SECTION S';
sql_stmt := sql_stmt || sql_par2;                                             
sql_stmt := sql_stmt || ', DEV_XCSA.WFA_QUESTION SGQ WHERE A.CPHID = ''' ||USER_NAME || ''' AND A.ID = AQ.FK_APPRAISAL_ID     AND AQ.ID = S.FK_QUESTIONNAIRE_ID';
sql_stmt := sql_stmt || sql_par3;                                             
/* RUN THE QUERY */
OPEN QUEST_CUR FOR sql_stmt;
You can see that now the select statement has a variable number of return columns.
I would like to fetch the result of the query in a loop assigning the records to variables or to a record variable.
But after reading the documentation it looks that I can only declare record variables before the query string is built and there is not an easy way to fetch a cursor into a variable number of variables.
Is it possible to do what I am trying to do? Can you suggest a better approach?
Please help me,
TN

Tremal Naik wrote:
Ok, thanks to you both.
Please, bear in mind that I am really a PL/SQL novice and I may have misunderstood BluShadow's hints.
I will have a closer look at it and let you know my thoughts.Here's a cleaner commented example that should help you to understand what it's doing...
SQL> CREATE OR REPLACE PROCEDURE run_query(p_sql IN VARCHAR2) IS
  2    v_v_val     VARCHAR2(4000);
  3    v_n_val     NUMBER;
  4    v_d_val     DATE;
  5    v_ret       NUMBER;
  6    c           NUMBER;
  7    d           NUMBER;
  8    col_cnt     INTEGER;
  9    f           BOOLEAN;
10    rec_tab     DBMS_SQL.DESC_TAB;
11    col_num     NUMBER;
12    v_rowcount  NUMBER := 0;
13  BEGIN
14    -- create a cursor
15    c := DBMS_SQL.OPEN_CURSOR;
16    -- parse the SQL statement into the cursor
17    DBMS_SQL.PARSE(c, p_sql, DBMS_SQL.NATIVE);
18    -- execute the cursor
19    d := DBMS_SQL.EXECUTE(c);
20    --
21    -- Describe the columns returned by the SQL statement
22    DBMS_SQL.DESCRIBE_COLUMNS(c, col_cnt, rec_tab);
23    --
24    -- Bind local return variables to the various columns based on their types
25    FOR j in 1..col_cnt
26    LOOP
27      CASE rec_tab(j).col_type
28        WHEN 1 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000); -- Varchar2
29        WHEN 2 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_n_val);      -- Number
30        WHEN 12 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_d_val);     -- Date
31      ELSE
32        DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000);  -- Any other type return as varchar2
33      END CASE;
34    END LOOP;
35    --
36    -- Display what columns are being returned...
37    FOR j in 1..col_cnt
38    LOOP
39      DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' - '||case rec_tab(j).col_type when 1 then 'VARCHAR2'
40                                                                                when 2 then 'NUMBER'
41                                                                                when 12 then 'DATE'
42                                                       else 'Other' end);
43    END LOOP;
44    --
45    -- This part outputs the DATA
46    LOOP
47      -- Fetch a row of data through the cursor
48      v_ret := DBMS_SQL.FETCH_ROWS(c);
49      -- Exit when no more rows
50      EXIT WHEN v_ret = 0;
51      v_rowcount := v_rowcount + 1;
52      DBMS_OUTPUT.PUT_LINE('Row: '||v_rowcount);
53      DBMS_OUTPUT.PUT_LINE('--------------');
54      -- Fetch the value of each column from the row
55      FOR j in 1..col_cnt
56      LOOP
57        -- Fetch each column into the correct data type based on the description of the column
58        CASE rec_tab(j).col_type
59          WHEN 1  THEN DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);
60                       DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' : '||v_v_val);
61          WHEN 2  THEN DBMS_SQL.COLUMN_VALUE(c,j,v_n_val);
62                       DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' : '||v_n_val);
63          WHEN 12 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_d_val);
64                       DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' : '||to_char(v_d_val,'DD/MM/YYYY HH24:MI:SS'));
65        ELSE
66          DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);
67          DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' : '||v_v_val);
68        END CASE;
69      END LOOP;
70      DBMS_OUTPUT.PUT_LINE('--------------');
71    END LOOP;
72    --
73    -- Close the cursor now we have finished with it
74    DBMS_SQL.CLOSE_CURSOR(c);
75  END;
76  /
Procedure created.
SQL> exec run_query('select empno, ename, deptno from emp where deptno = 10');
EMPNO - NUMBER
ENAME - VARCHAR2
DEPTNO - NUMBER
Row: 1
EMPNO : 7782
ENAME : CLARK
DEPTNO : 10
Row: 2
EMPNO : 7839
ENAME : KING
DEPTNO : 10
Row: 3
EMPNO : 7934
ENAME : MILLER
DEPTNO : 10
PL/SQL procedure successfully completed.
SQL> exec run_query('select * from emp where deptno = 10');
EMPNO - NUMBER
ENAME - VARCHAR2
JOB - VARCHAR2
MGR - NUMBER
HIREDATE - DATE
SAL - NUMBER
COMM - NUMBER
DEPTNO - NUMBER
Row: 1
EMPNO : 7782
ENAME : CLARK
JOB : MANAGER
MGR : 7839
HIREDATE : 09/06/1981 00:00:00
SAL : 2450
COMM :
DEPTNO : 10
Row: 2
EMPNO : 7839
ENAME : KING
JOB : PRESIDENT
MGR :
HIREDATE : 17/11/1981 00:00:00
SAL : 5000
COMM :
DEPTNO : 10
Row: 3
EMPNO : 7934
ENAME : MILLER
JOB : CLERK
MGR : 7782
HIREDATE : 23/01/1982 00:00:00
SAL : 1300
COMM :
DEPTNO : 10
PL/SQL procedure successfully completed.
SQL> exec run_query('select * from dept where deptno = 10');
DEPTNO - NUMBER
DNAME - VARCHAR2
LOC - VARCHAR2
Row: 1
DEPTNO : 10
DNAME : ACCOUNTING
LOC : NEW YORK
PL/SQL procedure successfully completed.
SQL>As you can see, you can use DBMS_SQL to query any SQL string you like, regardless of the number of returned columns and their datatypes and the DBMS_SQL package can tell your code all the information it needs to know so that it can read the names, datatypes and data from that query.

Similar Messages

  • Slow performance when using cursor with bind variable

    i'm facing the problem mentioned in the subject.
    whenever i use the bind variable it would take more than 5mins to fetch 157 records, but if i hardcode the value ( not using variable ) it would take only 10sec to fetch 157 records.
    can anyone give me some guide to solve this problem? thank you..
    Code :
    DECLARE
    cursor cur1(l_startdate IN varchar2,l_enddate IN varchar2) IS
    select * from shipment ship where ship.insertion_date >= to_date(l_startdate,'DD-MM-YYYY HH24:MI:SS') and ship.insertion_date < to_date(l_enddate ,'DD-MM-YYYY HH24:MI:SS')
    TYPE shipment_aat IS TABLE OF cur1%ROWTYPE INDEX BY PLS_INTEGER;
    l_shpt shipment_aat;
    limit_in INTEGER := 100;
    BEGIN
    v_startdate := '10-06-2008 14:00:00';
    v_enddate := '10-06-2008 17:00:00';
    OPEN C_shpt(v_startdate,v_enddate);
    LOOP --start shipment loop   
    FETCH C_shpt BULK COLLECT INTO l_shpt LIMIT limit_in;
         FOR indx IN 1 .. l_shpt.COUNT
    LOOP
    DBMS_OUTPUT.PUT_LINE('l_shpt value ' || l_shpt(indx).ship_number || '/' || l_shpt(indx).insertion_date);
    END LOOP;
    EXIT WHEN l_shpt.COUNT < limit_in;
    END LOOP; -- end of shipment loop
    CLOSE cur1;
    END;

    When your query takes too long ...

  • How to trigger n number of jobs by processing  using fetch cursor.

    We have report which retrieves all the data from the master table using the open fetch cursor with the packet size 10,000
    FOR EXAMPLE:
    If there are 50,000 records(total)
    For each 10,000 records it should trigger a job  (we are trying to call a common program and submit the program in background through the main program )  were all the validation will be done only through the program
    Totally we are expecting 5 job's to be trieggered.
    Purpose : we want all the records validation to be completed Simultaneously with fraction of difference.

    Hi,
    You might need to rethink on your scenario.
    Where are the values for Vendor Region are getting stored for a PO? You might not be able to handle N number of Vendor regions for N number of Plants....You actually have to come to a 1:1 mapping.

  • How to generate report with dynamic variable number of columns?

    How to generate report with dynamic variable number of columns?
    I need to generate a report with varying column names (state names) as follows:
    SELECT AK, AL, AR,... FROM States ;
    I get these column names from the result of another query.
    In order to clarify my question, Please consider following table:
    CREATE TABLE TIME_PERIODS (
    PERIOD     VARCHAR2 (50) PRIMARY KEY
    CREATE TABLE STATE_INCOME (
         NAME     VARCHAR2 (2),
         PERIOD     VARCHAR2 (50)     REFERENCES TIME_PERIODS (PERIOD) ,
         INCOME     NUMBER (12, 2)
    I like to generate a report as follows:
    AK CA DE FL ...
    PERIOD1 1222.23 2423.20 232.33 345.21
    PERIOD2
    PERIOD3
    Total 433242.23 56744.34 8872.21 2324.23 ...
    The TIME_PERIODS.Period and State.Name could change dynamically.
    So I can't specify the state name in Select query like
    SELECT AK, AL, AR,... FROM
    What is the best way to generate this report?

    SQL> -- test tables and test data:
    SQL> CREATE TABLE states
      2    (state VARCHAR2 (2))
      3  /
    Table created.
    SQL> INSERT INTO states
      2  VALUES ('AK')
      3  /
    1 row created.
    SQL> INSERT INTO states
      2  VALUES ('AL')
      3  /
    1 row created.
    SQL> INSERT INTO states
      2  VALUES ('AR')
      3  /
    1 row created.
    SQL> INSERT INTO states
      2  VALUES ('CA')
      3  /
    1 row created.
    SQL> INSERT INTO states
      2  VALUES ('DE')
      3  /
    1 row created.
    SQL> INSERT INTO states
      2  VALUES ('FL')
      3  /
    1 row created.
    SQL> CREATE TABLE TIME_PERIODS
      2    (PERIOD VARCHAR2 (50) PRIMARY KEY)
      3  /
    Table created.
    SQL> INSERT INTO time_periods
      2  VALUES ('PERIOD1')
      3  /
    1 row created.
    SQL> INSERT INTO time_periods
      2  VALUES ('PERIOD2')
      3  /
    1 row created.
    SQL> INSERT INTO time_periods
      2  VALUES ('PERIOD3')
      3  /
    1 row created.
    SQL> INSERT INTO time_periods
      2  VALUES ('PERIOD4')
      3  /
    1 row created.
    SQL> CREATE TABLE STATE_INCOME
      2    (NAME   VARCHAR2 (2),
      3       PERIOD VARCHAR2 (50) REFERENCES TIME_PERIODS (PERIOD),
      4       INCOME NUMBER (12, 2))
      5  /
    Table created.
    SQL> INSERT INTO state_income
      2  VALUES ('AK', 'PERIOD1', 1222.23)
      3  /
    1 row created.
    SQL> INSERT INTO state_income
      2  VALUES ('CA', 'PERIOD1', 2423.20)
      3  /
    1 row created.
    SQL> INSERT INTO state_income
      2  VALUES ('DE', 'PERIOD1', 232.33)
      3  /
    1 row created.
    SQL> INSERT INTO state_income
      2  VALUES ('FL', 'PERIOD1', 345.21)
      3  /
    1 row created.
    SQL> -- the basic query:
    SQL> SELECT   SUBSTR (time_periods.period, 1, 10) period,
      2             SUM (DECODE (name, 'AK', income)) "AK",
      3             SUM (DECODE (name, 'CA', income)) "CA",
      4             SUM (DECODE (name, 'DE', income)) "DE",
      5             SUM (DECODE (name, 'FL', income)) "FL"
      6  FROM     state_income, time_periods
      7  WHERE    time_periods.period = state_income.period (+)
      8  AND      time_periods.period IN ('PERIOD1','PERIOD2','PERIOD3')
      9  GROUP BY ROLLUP (time_periods.period)
    10  /
    PERIOD             AK         CA         DE         FL                                             
    PERIOD1       1222.23     2423.2     232.33     345.21                                             
    PERIOD2                                                                                            
    PERIOD3                                                                                            
                  1222.23     2423.2     232.33     345.21                                             
    SQL> -- package that dynamically executes the query
    SQL> -- given variable numbers and values
    SQL> -- of states and periods:
    SQL> CREATE OR REPLACE PACKAGE package_name
      2  AS
      3    TYPE cursor_type IS REF CURSOR;
      4    PROCEDURE procedure_name
      5        (p_periods   IN     VARCHAR2,
      6         p_states    IN     VARCHAR2,
      7         cursor_name IN OUT cursor_type);
      8  END package_name;
      9  /
    Package created.
    SQL> CREATE OR REPLACE PACKAGE BODY package_name
      2  AS
      3    PROCEDURE procedure_name
      4        (p_periods   IN     VARCHAR2,
      5         p_states    IN     VARCHAR2,
      6         cursor_name IN OUT cursor_type)
      7    IS
      8        v_periods          VARCHAR2 (1000);
      9        v_sql               VARCHAR2 (4000);
    10        v_states          VARCHAR2 (1000) := p_states;
    11    BEGIN
    12        v_periods := REPLACE (p_periods, ',', ''',''');
    13        v_sql := 'SELECT SUBSTR(time_periods.period,1,10) period';
    14        WHILE LENGTH (v_states) > 1
    15        LOOP
    16          v_sql := v_sql
    17          || ',SUM(DECODE(name,'''
    18          || SUBSTR (v_states,1,2) || ''',income)) "' || SUBSTR (v_states,1,2)
    19          || '"';
    20          v_states := LTRIM (SUBSTR (v_states, 3), ',');
    21        END LOOP;
    22        v_sql := v_sql
    23        || 'FROM     state_income, time_periods
    24            WHERE    time_periods.period = state_income.period (+)
    25            AND      time_periods.period IN (''' || v_periods || ''')
    26            GROUP BY ROLLUP (time_periods.period)';
    27        OPEN cursor_name FOR v_sql;
    28    END procedure_name;
    29  END package_name;
    30  /
    Package body created.
    SQL> -- sample executions from SQL:
    SQL> VARIABLE g_ref REFCURSOR
    SQL> EXEC package_name.procedure_name ('PERIOD1,PERIOD2,PERIOD3','AK,CA,DE,FL', :g_ref)
    PL/SQL procedure successfully completed.
    SQL> PRINT g_ref
    PERIOD             AK         CA         DE         FL                                             
    PERIOD1       1222.23     2423.2     232.33     345.21                                             
    PERIOD2                                                                                            
    PERIOD3                                                                                            
                  1222.23     2423.2     232.33     345.21                                             
    SQL> EXEC package_name.procedure_name ('PERIOD1,PERIOD2','AK,AL,AR', :g_ref)
    PL/SQL procedure successfully completed.
    SQL> PRINT g_ref
    PERIOD             AK         AL         AR                                                        
    PERIOD1       1222.23                                                                              
    PERIOD2                                                                                            
                  1222.23                                                                              
    SQL> -- sample execution from PL/SQL block
    SQL> -- using parameters derived from processing
    SQL> -- cursors containing results of other queries:
    SQL> DECLARE
      2    CURSOR c_period
      3    IS
      4    SELECT period
      5    FROM   time_periods;
      6    v_periods   VARCHAR2 (1000);
      7    v_delimiter VARCHAR2 (1) := NULL;
      8    CURSOR c_states
      9    IS
    10    SELECT state
    11    FROM   states;
    12    v_states    VARCHAR2 (1000);
    13  BEGIN
    14    FOR r_period IN c_period
    15    LOOP
    16        v_periods := v_periods || v_delimiter || r_period.period;
    17        v_delimiter := ',';
    18    END LOOP;
    19    v_delimiter := NULL;
    20    FOR r_states IN c_states
    21    LOOP
    22        v_states := v_states || v_delimiter || r_states.state;
    23        v_delimiter := ',';
    24    END LOOP;
    25    package_name.procedure_name (v_periods, v_states, :g_ref);
    26  END;
    27  /
    PL/SQL procedure successfully completed.
    SQL> PRINT g_ref
    PERIOD             AK         AL         AR         CA         DE         FL                       
    PERIOD1       1222.23                           2423.2     232.33     345.21                       
    PERIOD2                                                                                            
    PERIOD3                                                                                            
    PERIOD4                                                                                            
                  1222.23                           2423.2     232.33     345.21                       

  • Can I retrieve cursor's value with variable columns?

    I have a loop to check a bunch of columns in a cursor, I'd like to use a variable columns like following:
    cursor cur
    while ....
    loop
    cur.XXX
    end loop;
    here XXX are dynamical generated VARCHAR2.
    Could you please tell me is it possible, or not?
    Thanks alot

    Thanks for reply, first. I have couple of columns like abc_1 to abc_100 in the table, I need to check their value one by one. I want to check them using something like abc_X, in the cursor. my thought is like below,
    while i<= 100
    loop
    cur_name.abc_X
    end loop
    Just replace X with 1 to 100.

  • Dynamic REF Cursor with Dynamic Fetch - Urgent

    i have a pl/sql package with generates dynamic SQL statments. my problem is i want to open this SQL statment dynamically and fetch data in dynamic variable.
    declare
    type type_temp is REF CURSOR;
    cur_temp type_temp;
    mv_sql varchar2(4000);
    begin
    -- this will be dunamically generated and
    -- hence could have any no. of columns.
    mv_sql := select f1, f2, f3, f4 from table_temp;
    open cur_temp for mv_sql;
    fetch cur_temp into c1, c2, c3, c4;
    close cur_temp;
    end;
    problem is my sql statment will have N no. of columns how can i fetch this N no. of columns.

    Very hard problem, because ref cursors do not (directly) support description!
    Se mine (non-ideal) solution (it may be doable, but it isn't very practical
    or easily maintainable):
    1. "Generic" package
    CREATE OR REPLACE PACKAGE dyn_fetch IS
    TYPE ref_cur_t IS REF CURSOR;
    g_query VARCHAR2 (32000);
    g_count NUMBER;
    g_desc_tab DBMS_SQL.DESC_TAB;
    varchar2_type CONSTANT PLS_INTEGER := 1;
    number_type CONSTANT PLS_INTEGER := 2;
    date_type CONSTANT PLS_INTEGER := 12;
    rowid_type CONSTANT PLS_INTEGER := 11;
    char_type CONSTANT PLS_INTEGER := 96;
    long_type CONSTANT PLS_INTEGER := 8;
    raw_type CONSTANT PLS_INTEGER := 23;
    mlslabel_type CONSTANT PLS_INTEGER := 106;
    clob_type CONSTANT PLS_INTEGER := 112;
    blob_type CONSTANT PLS_INTEGER := 113;
    bfile_type CONSTANT PLS_INTEGER := 114;
    PROCEDURE describe_columns;
    FUNCTION record_def RETURN VARCHAR2;
    END;
    CREATE OR REPLACE PACKAGE BODY dyn_fetch IS
    PROCEDURE describe_columns IS
    l_cur INTEGER;
    BEGIN
    l_cur := DBMS_SQL.OPEN_CURSOR;
    DBMS_SQL.PARSE (l_cur, g_query, DBMS_SQL.NATIVE);
    DBMS_SQL.DESCRIBE_COLUMNS (l_cur, g_count, g_desc_tab);
    DBMS_SQL.CLOSE_CURSOR (l_cur);
    EXCEPTION
    WHEN OTHERS THEN
    IF DBMS_SQL.IS_OPEN (l_cur) THEN
    DBMS_SQL.CLOSE_CURSOR (l_cur);
    END IF;
    RAISE;
    END;
    FUNCTION record_def RETURN VARCHAR2 IS
    l_record_def VARCHAR2 (32000);
    l_type VARCHAR2 (100);
    l_col_type PLS_INTEGER;
    l_col_max_len PLS_INTEGER;
    l_col_precision PLS_INTEGER;
    l_col_scale PLS_INTEGER;
    BEGIN
    FOR i IN 1..g_count LOOP
    l_col_type := g_desc_tab(i).col_type;
    l_col_max_len := g_desc_tab(i).col_max_len;
    l_col_precision := g_desc_tab(i).col_precision;
    l_col_scale := g_desc_tab(i).col_scale;
    IF l_col_type = varchar2_type THEN
    l_type := 'VARCHAR2(' || l_col_max_len || ')';
    ELSIF l_col_type = number_type THEN
    l_type := 'NUMBER(' || l_col_precision || ',' || l_col_scale || ')';
    ELSIF l_col_type = date_type THEN
    l_type := 'DATE';
    ELSIF l_col_type = rowid_type THEN
    l_type := 'ROWID';
    ELSIF l_col_type = char_type THEN
    l_type := 'CHAR(' || l_col_max_len || ')';
    -- ELSIF l_col_type = ...
    -- long_type, raw_type ...
    END IF;
    l_record_def := l_record_def || ' col_' || i || ' ' || l_type || ',';
    END LOOP;
    l_record_def := RTRIM (l_record_def, ',');
    RETURN l_record_def;
    END;
    END;
    Note that procedure "record_def" creates columns names as col_1 (col_2 ...)
    because SELECT clause in your query can be without aliases, for example
    "SELECT deptno || dname FROM dept".
    2. Your package which returns query nad ref cursor
    CREATE OR REPLACE PACKAGE test IS
    PROCEDURE set_query (p_query VARCHAR2 := NULL);
    FUNCTION ref_cur RETURN dyn_fetch.ref_cur_t;
    END;
    CREATE OR REPLACE PACKAGE BODY test IS
    PROCEDURE set_query (p_query VARCHAR2 := NULL) IS
    l_query VARCHAR2 (32000) :=
    ' SELECT e.empno, e.ename,' ||
    ' e.deptno, d.dname' ||
    ' FROM emp e,' ||
    ' dept d' ||
    ' WHERE e.deptno = d.deptno';
    BEGIN
    IF p_query IS NULL THEN
    dyn_fetch.g_query := l_query;
    ELSE
    dyn_fetch.g_query := p_query;
    END IF;
    END;
    FUNCTION ref_cur RETURN dyn_fetch.ref_cur_t IS
    l_ref_cur dyn_fetch.ref_cur_t;
    BEGIN
    OPEN l_ref_cur FOR dyn_fetch.g_query;
    RETURN l_ref_cur;
    END;
    END;
    Why we need two separate procedures (functions) in your package ?
    a) Receiving program must use dynamic SQL, but in dynamic block we can access
    only PL/SQL code elements that have global scope (standalone functions and procedures,
    and elements defined in the specification of a package).
    Unfortunately, cursor variables cannot be defined in the specification of a package
    (cannot be global variables).
    b) Receiving program must get the column list before ref cursor.
    So, we have two options: call (in receiving program) the same function two times
    (once to get the column list and once to return a ref cursor)
    or use one procedure (or function) for returning query (to get the column list)
    and second function for returning a ref cursor.
    3. Your receiving program
    CREATE OR REPLACE PROCEDURE test_fetch_ref_cur (p_query VARCHAR2 := NULL) IS
    l_statement VARCHAR2 (32000);
    FUNCTION process_def RETURN VARCHAR2 IS
    l_process_def VARCHAR2 (32000);
    BEGIN
    l_process_def := 'DBMS_OUTPUT.PUT_LINE (';
    FOR i IN 1 .. dyn_fetch.g_count LOOP
    l_process_def := l_process_def || ' l_record.col_' || i || ' || ''>>'' || ';
    END LOOP;
    l_process_def := RTRIM (l_process_def, ' || ''>>'' || ') || ');';
    RETURN l_process_def;
    END;
    BEGIN
    test.set_query (p_query);
    dyn_fetch.describe_columns;
    l_statement :=
    ' DECLARE' ||
    ' TYPE record_t IS RECORD (' ||
    dyn_fetch.record_def || ');' ||
    ' l_record record_t;' ||
    ' l_ref_cur dyn_fetch.ref_cur_t;' ||
    ' BEGIN' ||
    ' l_ref_cur := test.ref_cur;' ||
    ' LOOP' ||
    ' FETCH l_ref_cur INTO l_record;' ||
    ' EXIT WHEN l_ref_cur%NOTFOUND;' ||
    process_def ||
    ' END LOOP;' ||
    ' CLOSE l_ref_cur;' ||
    ' END;';
    EXECUTE IMMEDIATE l_statement;
    END;
    You can test this with:
    SET SERVEROUTPUT ON;
    EXECUTE test_fetch_ref_cur;
    Note that we can try to use more generic solution:
    CREATE OR REPLACE PACKAGE dyn_fetch IS
    -- SAME AS BEFORE, PLUS:
    PROCEDURE fetch_ref_cur (
    p_function_ref_cur VARCHAR2,
    p_process_def VARCHAR2);
    END;
    CREATE OR REPLACE PACKAGE BODY dyn_fetch IS
    -- SAME AS BEFORE, PLUS:
    PROCEDURE fetch_ref_cur (
    p_function_ref_cur VARCHAR2,
    p_process_def VARCHAR2)
    IS
    l_statement VARCHAR2 (32000);
    BEGIN
    l_statement :=
    ' DECLARE' ||
    ' TYPE record_t IS RECORD (' ||
    record_def || ');' ||
    ' l_record record_t;' ||
    ' l_ref_cur dyn_fetch.ref_cur_t;' ||
    ' BEGIN' ||
    ' l_ref_cur := ' ||
    p_function_ref_cur || ';' ||
    ' LOOP' ||
    ' FETCH l_ref_cur INTO l_record;' ||
    ' EXIT WHEN l_ref_cur%NOTFOUND;' ||
    p_process_def ||
    ' END LOOP;' ||
    ' CLOSE l_ref_cur;' ||
    ' END;';
    EXECUTE IMMEDIATE l_statement;
    END;
    END;
    CREATE OR REPLACE PROCEDURE test_fetch_ref_cur (p_query VARCHAR2 := NULL) IS
    FUNCTION process_def RETURN VARCHAR2 IS
    -- SAME AS BEFORE
    END;
    BEGIN
    test.set_query (p_query);
    dyn_fetch.describe_columns;
    dyn_fetch.fetch_ref_cur (
    p_function_ref_cur => 'test.ref_cur',
    p_process_def => process_def);
    END;
    Regards,
    Zlatko Sirotic

  • Dynamic Ref Cursor with Dynamic Fetch

    Hi,
    I'm using dynamic sql (DBMS_SQL) to define columns of ref cursor.
    It works Ok but the problem is when i'm using PL/SQL CURSOR in the REF CURSOR. Then,
    I'm getting :
    Error at line 3
    ORA-00932: inconsistent datatypes: expected NUMBER got CURSER
    ORA-06512: at "SYS.DBMS_SQL", line 1830
    ORA-06512: at "TW.PRINT_REF_CURSOR", line 28
    ORA-06512: at line 9
    Here is my code:
    set serveroutput on
    exec DBMS_OUTPUT.ENABLE(1000000);
    declare
    l_cursor sys_refcursor;
    begin
    OPEN l_cursor FOR
    SELECT SERVICE_TABLE.SERVICE, SERVICE_TABLE.SERVICE_GROUP, SERVICE_TABLE.SERVICE_DESC,
    CURSOR(SELECT SERVICE_TABLE.SERVICE_CD FROM SERVICE_TABLE) SERVICE_CD_CURSOR
    FROM SERVICE_TABLE ;
    print_ref_cursor( l_cursor );
    end;
    =========================
    CREATE OR REPLACE procedure print_ref_cursor
    ( p_query in out sys_refcursor,
    p_date_fmt in varchar2 default 'dd-mon-yyyy hh24:mi:ss' )
    is
    l_theCursor integer;
    l_columnValue varchar2(4000);
    l_descTbl dbms_sql.desc_tab2;
    l_colCnt number;
    l_date date;
    l_cursor SYS_REFCURSOR;
    begin
    l_theCursor := dbms_sql.to_cursor_number( p_query );
    dbms_sql.describe_columns2
    ( l_theCursor, l_colCnt, l_descTbl );
    -- define all columns to be cast to varchar2's, we
    -- are just printing them out
    for i in 1 .. l_colCnt loop
    if ( l_descTbl(i).col_type in ( 12, 178, 179, 180, 181, 231 ) )
    then
    dbms_sql.define_column
    (l_theCursor, i, l_date );
    else
    dbms_sql.define_column
    (l_theCursor, i, l_columnValue, 4000);
    end if;
    end loop;
    while ( dbms_sql.fetch_rows(l_theCursor) > 0 )
    loop
    for i in 1 .. l_colCnt loop
    if ( l_descTbl(i).col_type in ( 12, 178, 179, 180, 181, 231 ) )
    then
    dbms_sql.column_value( l_theCursor, i, l_date );
    l_columnValue := to_char( l_date, p_date_fmt );
    else
    dbms_sql.column_value( l_theCursor, i, l_columnValue );
    end if;
    dbms_output.put_line
    ( rpad( l_descTbl(i).col_schema_name || '.' ||
    l_descTbl(i).col_name, 30 ) || ': ' || l_columnValue );
    end loop;
    dbms_output.put_line( '-----------------' );
    end loop;
    dbms_sql.close_cursor( l_theCursor );
    end;
    Is there a solution or bypass?
    Regards,
    Tamir Geva

    No. The problem is that one cannot use DBMS_SQL.define_column() to define that column in the SQL projection as a cursor, and then use DBMS_SQL.column_value() to read it into a ref cursor variable.
    You can however detect the cursor column - the DBMS_SQL.describe_columns3() call will return a col_type value of 102. In which case you can treat it as an exception (i.e. not process that column in the projection).
    As a general issue - a cursor as a SQL column projection does not make sense to me. I have never used this in any production code. Nor do I see any reasons why.
    If you want that column in the projection to contain a "list" of sorts (the results of the cursor), then a nested table type can be used as projected type and the MultiSet() function used to execute the in-line SQL and provide that SQL cursor's result as an array/nested table.
    But even this approach raises the question why a standard relational join is not used?

  • Is there any way to spool with variable column size?

    Hi, I'm spooling to a CSV file with the following script (the real SELECT is different but similar, Oracle 10.2.0.3.0):
    SET COLSEP ';'
    SET FEEDBACK OFF
    SET LINESIZE 2000
    SET PAGESIZE 0
    SET TERMOUT OFF
    SET TRIMSPOOL ON
    SET VERIFY OFF
    SPOOL test.csv REPLACE
    SELECT 'COLUMN1', 'COLUMN2', 'COLUMN3' FROM dual UNION ALL
    SELECT 'value1', NULL, NULL FROM dual UNION ALL
    SELECT 'value2', NULL, NULL FROM dual;
    SPOOL OFF
    EXIT SUCCESS COMMITThis produces the following output:
    COLUMN1;COLUMN2;COLUMN3
    value1 ;       ;
    value2 ;       ;Is there any way to get the following output with variable column size
    COLUMN1;COLUMN2;COLUMN3
    value1;;
    value2;;I've tried SET NULL '' but I see no difference. Thanks in advance!
    Markus

    In short, No, because SQL*Plus is laying out the data in columns.
    You could either combine the data into a single column by concatenating as strings or use some other method e.g.
    As sys user:
    CREATE OR REPLACE DIRECTORY TEST_DIR AS '\tmp\myfiles'
    GRANT READ, WRITE ON DIRECTORY TEST_DIR TO myuser
    /As myuser:
    CREATE OR REPLACE PROCEDURE run_query(p_sql IN VARCHAR2
                                         ,p_dir IN VARCHAR2
                                         ,p_header_file IN VARCHAR2
                                         ,p_data_file IN VARCHAR2 := NULL) IS
      v_finaltxt  VARCHAR2(4000);
      v_v_val     VARCHAR2(4000);
      v_n_val     NUMBER;
      v_d_val     DATE;
      v_ret       NUMBER;
      c           NUMBER;
      d           NUMBER;
      col_cnt     INTEGER;
      f           BOOLEAN;
      rec_tab     DBMS_SQL.DESC_TAB;
      col_num     NUMBER;
      v_fh        UTL_FILE.FILE_TYPE;
      v_samefile  BOOLEAN := (NVL(p_data_file,p_header_file) = p_header_file);
    BEGIN
      c := DBMS_SQL.OPEN_CURSOR;
      DBMS_SQL.PARSE(c, p_sql, DBMS_SQL.NATIVE);
      d := DBMS_SQL.EXECUTE(c);
      DBMS_SQL.DESCRIBE_COLUMNS(c, col_cnt, rec_tab);
      FOR j in 1..col_cnt
      LOOP
        CASE rec_tab(j).col_type
          WHEN 1 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000);
          WHEN 2 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_n_val);
          WHEN 12 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_d_val);
        ELSE
          DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000);
        END CASE;
      END LOOP;
      -- This part outputs the HEADER
      v_fh := UTL_FILE.FOPEN(upper(p_dir),p_header_file,'w',32767);
      FOR j in 1..col_cnt
      LOOP
        v_finaltxt := ltrim(v_finaltxt||','||lower(rec_tab(j).col_name),',');
      END LOOP;
      --  DBMS_OUTPUT.PUT_LINE(v_finaltxt);
      UTL_FILE.PUT_LINE(v_fh, v_finaltxt);
      IF NOT v_samefile THEN
        UTL_FILE.FCLOSE(v_fh);
      END IF;
      -- This part outputs the DATA
      IF NOT v_samefile THEN
        v_fh := UTL_FILE.FOPEN(upper(p_dir),p_data_file,'w',32767);
      END IF;
      LOOP
        v_ret := DBMS_SQL.FETCH_ROWS(c);
        EXIT WHEN v_ret = 0;
        v_finaltxt := NULL;
        FOR j in 1..col_cnt
        LOOP
          CASE rec_tab(j).col_type
            WHEN 1 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);
                        v_finaltxt := ltrim(v_finaltxt||',"'||v_v_val||'"',',');
            WHEN 2 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_n_val);
                        v_finaltxt := ltrim(v_finaltxt||','||v_n_val,',');
            WHEN 12 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_d_val);
                        v_finaltxt := ltrim(v_finaltxt||','||to_char(v_d_val,'DD/MM/YYYY HH24:MI:SS'),',');
          ELSE
            v_finaltxt := ltrim(v_finaltxt||',"'||v_v_val||'"',',');
          END CASE;
        END LOOP;
      --  DBMS_OUTPUT.PUT_LINE(v_finaltxt);
        UTL_FILE.PUT_LINE(v_fh, v_finaltxt);
      END LOOP;
      UTL_FILE.FCLOSE(v_fh);
      DBMS_SQL.CLOSE_CURSOR(c);
    END;This allows for the header row and the data to be written to seperate files if required.
    e.g.
    SQL> exec run_query('select * from emp','TEST_DIR','output.txt');
    PL/SQL procedure successfully completed.Output.txt file contains:
    empno,ename,job,mgr,hiredate,sal,comm,deptno
    7369,"SMITH","CLERK",7902,17/12/1980 00:00:00,800,,20
    7499,"ALLEN","SALESMAN",7698,20/02/1981 00:00:00,1600,300,30
    7521,"WARD","SALESMAN",7698,22/02/1981 00:00:00,1250,500,30
    7566,"JONES","MANAGER",7839,02/04/1981 00:00:00,2975,,20
    7654,"MARTIN","SALESMAN",7698,28/09/1981 00:00:00,1250,1400,30
    7698,"BLAKE","MANAGER",7839,01/05/1981 00:00:00,2850,,30
    7782,"CLARK","MANAGER",7839,09/06/1981 00:00:00,2450,,10
    7788,"SCOTT","ANALYST",7566,19/04/1987 00:00:00,3000,,20
    7839,"KING","PRESIDENT",,17/11/1981 00:00:00,5000,,10
    7844,"TURNER","SALESMAN",7698,08/09/1981 00:00:00,1500,0,30
    7876,"ADAMS","CLERK",7788,23/05/1987 00:00:00,1100,,20
    7900,"JAMES","CLERK",7698,03/12/1981 00:00:00,950,,30
    7902,"FORD","ANALYST",7566,03/12/1981 00:00:00,3000,,20
    7934,"MILLER","CLERK",7782,23/01/1982 00:00:00,1300,,10The procedure allows for the header and data to go to seperate files if required. Just specifying the "header" filename will put the header and data in the one file.
    Adapt to output different datatypes and styles are required.

  • Pivot table with variables columns

    I need a helo to pivot table with variable columns,
    I have a pivot table :
    SELECT a.*
    FROM (SELECT codigo_aluno,nome_aluno , id_curso,dia FROM c_frequencia where dia like '201308%') PIVOT (sum(null)   FOR dia IN ('20130805' ,'20130812','20130819','20130826')) a
    but I need to run the select with values for dia , getting from a other table :
    SELECT a.*
    FROM (SELECT codigo_aluno,nome_aluno , id_curso,dia FROM c_frequencia where dia like '201308%') PIVOT (sum(null)   FOR dia IN (
    select dia from v_dia_mes )) a
    thank you

    The correct answer should be "Use the Pivoted Report Region Plugin".
    But, as far as I know, nobody has created/posted that type of APEX plugin.
    You may have to use a Basic Report (not an IR) so that you can use "Function returning SELECT" for your Source.
    You would need two functions:
    One that dynamically generates the Column Names
    One that dynamically generates the SELECT statement
    These should be in a PL/SQL Package so that the later can call the former to ensure that the column data matches the column names.
    i.e. -- no 'SELECT *'
    MK

  • Can we specify the next screen number with a variable?

    hi
    can we specify the next screen number with a variable?

    yes, dynamicaly u can. i.e using set screen or call screen.
    but u cant obviously set a variable in the attributes.

  • Need help with Fluid Grid Layout and variable column balance.

    I'm using the fluid grid layout.  I have multiple columns that are actually fluid grid layout columns done by Dreamweaver.  I'd like them to extend as high as each other (all to the maximum height of each other) within the same section.  An added catch is that in the desktop layout, I have three side by side under one that takes the whole width of the page.  On tablet size, it's 2x2 in a square grid.  On mobile, they're vertically stacked.  I'm trying to get it so that background colour and/or borders looks decent and is fully balanced, no matter which layout is hit with the fluid layout.  The columns reflow, no problem.  But the height of any background and/or border is variable. 
    Any help on fixing this? 
    Example at:  https://music2help.thoughtburst.net/ 
    The example doesn't have borders or colours, as it looked silly unbalanced.  The music2help.css is the only one I'm modifying manually.
    Love the fluid grid layout, but I need a way to make it behave decently with backgrounds/borders.  Any help would be hugely appreciated!
    Thanks!
    mark->

    I tried the solution Nancy posted.  It altered things, but doesn't seem to do the trick.
    Just some quick background.  I did HTML from 1994 through about five years ago by hand in vi on *nix systems.  I learned HTML through 4.01, and never bothered with XHTML at all.  I learned CSS through most of CSS2.  The CSS3 and HTML5 stuff is all new to me, but it can't be that hard.  I'm not exactly a novice in JS (I've done a fair bit of AJAX programming), but it's not even close to my primary language (I'm a Perl guy).
    I'm "stuck on" wanting to use Fluid Grid Layouts.  It's billed as one of the selling points of DW CS6, and I really like the concept and results.  I just want the results embellished a little, namely with sensible identical heights on grid containers set in the same row, so that you can apply background colours, dropshadows, and borders.  That's really all I want to do that it doesn't already do.
    I have a test page at:  http://music2help.thoughtburst.net/ that you can try with your Quick Columns.  I'd be interested to know if you can get it to work.
    Here's the catch, though...  Resize the browser, shrinking it inwards.  (I suggest Firefox, as Chrome only shrinks so far, and you won't get to Mobile width.)  As you can see, on a Tablet, one of the columns that should be equal height actually moves up a row and should be equal height with the row that, on a desktop, would take the entire width of the page area.  So that's like a 4-up output in printing terms.  At Mobile size, the entire thing is vertical, so none of the columns should be resized.
    If your product works and can accomodate these conditions, I think I would be interested in spending the $35 it costs. 
    Let me know?  Thanks!
    EDIT:  Changed URL to be non-SSL.  The server has multiple vhosts on it, and I keep forgetting that I don't have a cert on this new one.  Sorry about that.  You can just add anything to one of the the three middle columns, if you're pulling it down to test.

  • Problem with fetch cursor statement

    Hi,
    I am using FETCH CURSOR statement to fetch the data from a database table with package size. For the fetched records I am doing parallel processing using parallel processing frame work in banking system.
    Here the problem is for the first iteration it works fine but when it comes to FETCH NEXT CURSOR in the second iteration , programs gets dumping by saying that 'CURSOR already closed'.
    I am not closing the cursor in the program but some how it got closed some where in the standard function module which I used for parallel processing.
    I used WITHHOLD also along with FETCH CURSOR but no use. Please let me know how to avoid the cursor to get close.
    Below is my code
    IF NOT l_tab_product IS INITIAL.
        OPEN CURSOR WITH HOLD lv_cursor FOR
         SELECT contract_int prodint cn_currency mig_grp
              INTO TABLE gt_cont
                FROM bca_contract
                FOR ALL ENTRIES IN l_tab_product
                WHERE prodint = l_tab_product-prodint
                AND   mig_grp IN s_migrp.
        DO.
          FETCH NEXT CURSOR lv_cursor
                            INTO TABLE gt_cont
                                 PACKAGE SIZE lv_size.
          IF sy-subrc <> 0.
            CLOSE CURSOR lv_cursor.
            EXIT.
          ELSE.
    parallel processing logic
    ENDDO.
    ENDIF.

    Using Withhold will not make sure that the cursor will not get closed because of commits.
    SAP Doc says
    If the addition WITH HOLD is specified, the database cursor is not closed by a database commit executed using Native SQL. The addition does not have an influence, however, on implicit database commits or on any rollbacks which always close the database cursor.
    You have to check the part written in your parallel processing logic.
    As Brad said please donot dump your old threads like this.

  • Using column number inplace of column name in SQL Select statement

    Is there a way to run sql select statements with column numbers in
    place of column names?
    Current SQL
    select AddressId,Name,City from AddressIs this possible
    select 1,2,5 from AddressThanks in Advance

    user10962462 wrote:
    well, ok, it's not possible with SQL, but how about PL/SQL?As mentioned, using DBMS_SQL you can only really use positional notation... and you can also use those positions to get the other information such as what the column is called, what it's datatype is etc.
    CREATE OR REPLACE PROCEDURE run_query(p_sql IN VARCHAR2) IS
      v_v_val     VARCHAR2(4000);
      v_n_val     NUMBER;
      v_d_val     DATE;
      v_ret       NUMBER;
      c           NUMBER;
      d           NUMBER;
      col_cnt     INTEGER;
      f           BOOLEAN;
      rec_tab     DBMS_SQL.DESC_TAB;
      col_num     NUMBER;
      v_rowcount  NUMBER := 0;
    BEGIN
      -- create a cursor
      c := DBMS_SQL.OPEN_CURSOR;
      -- parse the SQL statement into the cursor
      DBMS_SQL.PARSE(c, p_sql, DBMS_SQL.NATIVE);
      -- execute the cursor
      d := DBMS_SQL.EXECUTE(c);
      -- Describe the columns returned by the SQL statement
      DBMS_SQL.DESCRIBE_COLUMNS(c, col_cnt, rec_tab);
      -- Bind local return variables to the various columns based on their types
      FOR j in 1..col_cnt
      LOOP
        CASE rec_tab(j).col_type
          WHEN 1 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000); -- Varchar2
          WHEN 2 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_n_val);      -- Number
          WHEN 12 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_d_val);     -- Date
        ELSE
          DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000);  -- Any other type return as varchar2
        END CASE;
      END LOOP;
      -- Display what columns are being returned...
      DBMS_OUTPUT.PUT_LINE('-- Columns --');
      FOR j in 1..col_cnt
      LOOP
        DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' - '||case rec_tab(j).col_type when 1 then 'VARCHAR2'
                                                                                  when 2 then 'NUMBER'
                                                                                  when 12 then 'DATE'
                                                         else 'Other' end);
      END LOOP;
      DBMS_OUTPUT.PUT_LINE('-------------');
      -- This part outputs the DATA
      LOOP
        -- Fetch a row of data through the cursor
        v_ret := DBMS_SQL.FETCH_ROWS(c);
        -- Exit when no more rows
        EXIT WHEN v_ret = 0;
        v_rowcount := v_rowcount + 1;
        DBMS_OUTPUT.PUT_LINE('Row: '||v_rowcount);
        DBMS_OUTPUT.PUT_LINE('--------------');
        -- Fetch the value of each column from the row
        FOR j in 1..col_cnt
        LOOP
          -- Fetch each column into the correct data type based on the description of the column
          CASE rec_tab(j).col_type
            WHEN 1  THEN DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);
                         DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' : '||v_v_val);
            WHEN 2  THEN DBMS_SQL.COLUMN_VALUE(c,j,v_n_val);
                         DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' : '||v_n_val);
            WHEN 12 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_d_val);
                         DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' : '||to_char(v_d_val,'DD/MM/YYYY HH24:MI:SS'));
          ELSE
            DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);
            DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' : '||v_v_val);
          END CASE;
        END LOOP;
        DBMS_OUTPUT.PUT_LINE('--------------');
      END LOOP;
      -- Close the cursor now we have finished with it
      DBMS_SQL.CLOSE_CURSOR(c);
    END;
    SQL> exec run_query('select empno, ename, deptno, sal from emp where deptno = 10');
    -- Columns --
    EMPNO - NUMBER
    ENAME - VARCHAR2
    DEPTNO - NUMBER
    SAL - NUMBER
    Row: 1
    EMPNO : 7782
    ENAME : CLARK
    DEPTNO : 10
    SAL : 2450
    Row: 2
    EMPNO : 7839
    ENAME : KING
    DEPTNO : 10
    SAL : 5000
    Row: 3
    EMPNO : 7934
    ENAME : MILLER
    DEPTNO : 10
    SAL : 1300
    PL/SQL procedure successfully completed.
    SQL> exec run_query('select * from emp where deptno = 10');
    -- Columns --
    EMPNO - NUMBER
    ENAME - VARCHAR2
    JOB - VARCHAR2
    MGR - NUMBER
    HIREDATE - DATE
    SAL - NUMBER
    COMM - NUMBER
    DEPTNO - NUMBER
    Row: 1
    EMPNO : 7782
    ENAME : CLARK
    JOB : MANAGER
    MGR : 7839
    HIREDATE : 09/06/1981 00:00:00
    SAL : 2450
    COMM :
    DEPTNO : 10
    Row: 2
    EMPNO : 7839
    ENAME : KING
    JOB : PRESIDENT
    MGR :
    HIREDATE : 17/11/1981 00:00:00
    SAL : 5000
    COMM :
    DEPTNO : 10
    Row: 3
    EMPNO : 7934
    ENAME : MILLER
    JOB : CLERK
    MGR : 7782
    HIREDATE : 23/01/1982 00:00:00
    SAL : 1300
    COMM :
    DEPTNO : 10
    PL/SQL procedure successfully completed.
    SQL> exec run_query('select * from dept where deptno = 10');
    -- Columns --
    DEPTNO - NUMBER
    DNAME - VARCHAR2
    LOC - VARCHAR2
    Row: 1
    DEPTNO : 10
    DNAME : ACCOUNTING
    LOC : NEW YORK
    PL/SQL procedure successfully completed.
    SQL>

  • Create collection from query with bind variable

    Apex 4.0.2
    Per Joel Re: Collection with bind variable the apex_collection.create_collection_from_query_b supports queries containing bind variable references (:P1_X) but I am not sure how to use this feature, the documentation doesn't have an example, just the API signature for the overloaded version has changed.
    If the query contains 2 bind variable references to session state (:P1_X and :P1_Y), can someone please show an example of what to pass in for the p_names and p_values parameters to the API?
    Thanks
    procedure create_collection_from_query_b(
        -- Create a named collection from the supplied query using bulk operations.  The query will
        -- be parsed as the application owner.  If a collection exists with the same name for the current
        -- user in the same session for the current Flow ID, an application error will be raised.
        -- This procedure uses bulk dynamic SQL to perform the fetch and insert operations into the named
        -- collection.  Two limitations are imposed by this procedure:
        --   1) The MD5 checksum for the member data will not be computed
        --   2) No column value in query p_query can exceed 2,000 bytes
        -- Arguments:
        --     p_collection_name   =  Name of collection.  Maximum length can be
        --                            255 bytes.  Note that collection_names are case-insensitive,
        --                            as the collection name will be converted to upper case
        --     p_query             =  Query to be executed which will populate the members of the
        --                            collection.  If p_query is numeric, it is assumed to be
        --                            a DBMS_SQL cursor.
        -- example(s):
        --     l_query := 'select make, model, caliber from firearms';
        --     apex_collection.create_collection_from_query_b( p_collection_name => 'Firearm', p_query => l_query );
        p_collection_name in varchar2,
        p_query           in varchar2,
        p_names           in wwv_flow_global.vc_arr2,
        p_values          in wwv_flow_global.vc_arr2,
        p_max_row_count   in number default null)
        ;

    VANJ wrote:
    Apex 4.0.2
    Per Joel Re: Collection with bind variable the apex_collection.create_collection_from_query_b supports queries containing bind variable references (:P1_X) but I am not sure how to use this feature, the documentation doesn't have an example, just the API signature for the overloaded version has changed.
    If the query contains 2 bind variable references to session state (:P1_X and :P1_Y), can someone please show an example of what to pass in for the p_names and p_values parameters to the API?Not tried it, but guessing something like
    apex_collection.create_collection_from_query_b(
        p_collection_name => 'foobar'
      , p_query => 'select f.foo_id, b.bar_id, b.baz from foo f, bar b where f.foo_id = b.foo_id and f.x = to_number(:p1_x) and b.y = :p1_y'
      , p_names => apex_util.string_to_table('p1_x:p1_y')
      , p_values => apex_util.string_to_table(v('p1_x') || ':' || v('p1_y')))

  • Cursor based on variable?

    I posted this issue in the APEX forum since I call my procedure through APEX, but I'm including it in here as well since the issue is with my cursor/loop:
    In APEX, I have a process that calls apex_mail. I have a cursor/loop that pulls records meeting my criteria and lists them in the body of the mail. This all works. However, I added another field (field b) which in the app is dependent on field a. Rather than having 11 cursors defined that run according to my 'if' statements, I would like one cursor that is equal to the end result of my variable (v_sql). When I run the code below, I receive the following error: ORA-06550: line 11, column 22: PLS-00382: expression is of wrong type ORA-06550: line 11, column 3: PL/SQL: Statement ignored ORA-06550: line 68, column 18: PLS-00221: 'GATHER_USRS_CUR' is not a procedure or is undefined ORA-06550: line 68, column 3: PL/SQL: Statement ignored.
    Code:
    declare
    e_body_1 CLOB;
    e_body_2 CLOB;
    j_sql CLOB :=null;
    v_sql varchar2(2000);
    -- Define cursor as SYS_REFCURSOR?
    gather_usrs_cur SYS_REFCURSOR;
    BEGIN
    -- make cursor equal to variable of v_sql
    gather_usrs_cur := v_sql;
    -- Generate body of e-mail
    e_body_1 := 'This e-mail is being generated to inform you that ... Those users are: '||utl_tcp.crlf||utl_tcp.crlf;
    e_body_1 := e_body_1||'USER ID, FIRST, LAST, PHONE, E-MAIL'||utl_tcp.crlf;
    e_body_1 := e_body_1||'==================================='||utl_tcp.crlf;
    e_body_2 := utl_tcp.crlf||'Please review the accounts identified above and inform us .... We appreciate your follow-up regarding the account activity in your State.'||utl_tcp.crlf||utl_tcp.crlf;
    e_body_2 := e_body_2||'Should you have any concerns/questions, please respond to the e-mail members on this e-mail.'||utl_tcp.crlf||utl_tcp.crlf;
    e_body_2 := e_body_2||' Sincerely,'||utl_tcp.crlf||utl_tcp.crlf;
    e_body_2 := e_body_2||' Team'||utl_tcp.crlf;
    -- Conditions for determing value of v_sql which would ultimately be reflected in cursor, gather_usrs_cur
    v_sql := 'select Q_APEX_ID,
    USER_ID,
    Q_USER_TYPE,
    Q_FIRST,
    Q_LAST,
    C_PHONE,
    C_EMAIL,
    C_STATE
    from Q_AUDIT
    where MATCH = ''Y'' and
    UPDT_ID is null and
    UPDT_TS is null and
    COMMENTS is null and
    Q_USER_TYPE = :P32_USER_TYPE ';
    if :P32_RO_USER_TYPE <> 'ALL' then
    if :P32_RO_USER_TYPE = 1 then
    v_sql := v_sql ||' and C_STATE in (''CT'',''MA'',''ME'',''NH'',''RI'',''VT'') ';
    end if;
    if :P32_RO_USER_TYPE = 2 then
    v_sql := v_sql ||' and C_STATE in (''NJ'',''NY'',''PR'',''VI'') ';
    end if;
    if :P32_RO_USER_TYPE = 3 then
    v_sql := v_sql ||' and C_STATE in (''DE'',''DC'',''MD'',''PA'',''VA'',''WV'') ';
    end if;
    if :P32_RO_USER_TYPE = 4 then
    v_sql := v_sql ||' and C_STATE in (''AL'',''FL'',''GA'',''KY'',''MS'',''NC'',''SC'',''TN'') ';
    end if;
    if :P32_RO_USER_TYPE = 5 then
    v_sql := v_sql ||' and C_STATE in (''IL'',''IN'',''MI'',''MN'',''OH'',''WI'') ';
    end if;
    if :P32_RO_USER_TYPE = 6 then
    v_sql := v_sql ||' and C_STATE in (''AR'',''LA'',''NM'',''OK'',''TX'') ';
    end if;
    if :P32_RO_USER_TYPE = 7 then
    v_sql := v_sql ||' and C_STATE in (''IA'',''KS'',''MO'',''NE'') ';
    end if;
    if :P32_RO_USER_TYPE = 8 then
    v_sql := v_sql ||' and C_STATE in (''CO'',''MT'',''ND'',''SD'',''UT'',''WY'') ';
    end if;
    if :P32_RO_USER_TYPE = 9 then
    v_sql := v_sql ||' and C_STATE in (''AZ'',''CA'',''HI'',''NV'') ';
    end if;
    if :P32_RO_USER_TYPE = 10 then
    v_sql := v_sql ||' and C_STATE in (''AK'',''ID'',''OR'',''WA'') ';
    end if;
    end if;
    -- call and loop through cursor for body of e-mail
    for usr_rec in gather_usrs_cur
    loop
    begin
    j_sql := j_sql ||usr_rec.user_id||', '||usr_rec.Q_first||', '||usr_rec.Q_last||', '||usr_rec.C_phone||', '||usr_rec.C_email||utl_tcp.crlf;
    end;
    end loop;
    commit;
    -- Call mail procedure
    apex_mail.send(
    P_TO => :P32_E_RECIPIENT,
    P_CC => '[email protected], [email protected]',
    P_FROM => '[email protected]',
    P_BODY => e_body_1||j_sql||e_body_2,
    P_SUBJ => 'Q Accounts Requiring Review');
    end;
    Is it possible to create one cursor that is equal to the 11 possible combinations, based on v_sql? Note that the :P32_X variables are set via buttons/fields in my APEX application. Thanks in advance for your help.

    I went ahead and rewrote this for you. Obviously I can't test it so no guarantees....
    Are you putting this code directly in APEX? If so, notice how I took ":P32_USER_TYPE" out from being a literal in your string and put in a bind variable.
    DECLARE
    e_body_1 CLOB;
    e_body_2 CLOB;
    j_sql CLOB := NULL;
    v_sql VARCHAR2 (2000);
    usr_rec q_audit%ROWTYPE;
    TYPE auditcurtype IS REF CURSOR;
    v_audit_cur auditcurtype;
    BEGIN
    -- Generate body of e-mail
    e_body_1 :=
    'This e-mail is being generated to inform you that ... Those users are: '
    || UTL_TCP.crlf
    || UTL_TCP.crlf;
    e_body_1 :=
    e_body_1 || 'USER ID, FIRST, LAST, PHONE, E-MAIL' || UTL_TCP.crlf;
    e_body_1 :=
    e_body_1 || '===================================' || UTL_TCP.crlf;
    e_body_2 :=
    UTL_TCP.crlf
    || 'Please review the accounts identified above and inform us .... We appreciate your follow-up regarding the account activity in your State.'
    || UTL_TCP.crlf
    || UTL_TCP.crlf;
    e_body_2 :=
    e_body_2
    || 'Should you have any concerns/questions, please respond to the e-mail members on this e-mail.'
    || UTL_TCP.crlf
    || UTL_TCP.crlf;
    e_body_2 := e_body_2 || ' Sincerely,' || UTL_TCP.crlf || UTL_TCP.crlf;
    e_body_2 := e_body_2 || ' Team' || UTL_TCP.crlf;
    -- Conditions for determing value of v_sql which would ultimately be reflected in cursor, gather_usrs_cur
    v_sql :=
    'select *
    from Q_AUDIT
    where MATCH = ''Y'' and
    UPDT_ID is null and
    UPDT_TS is null and
    COMMENTS is null and
    Q_USER_TYPE = :1';
    IF :p32_ro_user_type <> 'ALL'
    THEN
    IF :p32_ro_user_type = 1
    THEN
    v_sql :=
    v_sql
    || ' and C_STATE in (''CT'',''MA'',''ME'',''NH'',''RI'',''VT'') ';
    END IF;
    IF :p32_ro_user_type = 2
    THEN
    v_sql := v_sql || ' and C_STATE in (''NJ'',''NY'',''PR'',''VI'') ';
    END IF;
    IF :p32_ro_user_type = 3
    THEN
    v_sql :=
    v_sql
    || ' and C_STATE in (''DE'',''DC'',''MD'',''PA'',''VA'',''WV'') ';
    END IF;
    IF :p32_ro_user_type = 4
    THEN
    v_sql :=
    v_sql
    || ' and C_STATE in (''AL'',''FL'',''GA'',''KY'',''MS'',''NC'',''SC'',''TN'') ';
    END IF;
    IF :p32_ro_user_type = 5
    THEN
    v_sql :=
    v_sql
    || ' and C_STATE in (''IL'',''IN'',''MI'',''MN'',''OH'',''WI'') ';
    END IF;
    IF :p32_ro_user_type = 6
    THEN
    v_sql :=
    v_sql || ' and C_STATE in (''AR'',''LA'',''NM'',''OK'',''TX'') ';
    END IF;
    IF :p32_ro_user_type = 7
    THEN
    v_sql := v_sql || ' and C_STATE in (''IA'',''KS'',''MO'',''NE'') ';
    END IF;
    IF :p32_ro_user_type = 8
    THEN
    v_sql :=
    v_sql
    || ' and C_STATE in (''CO'',''MT'',''ND'',''SD'',''UT'',''WY'') ';
    END IF;
    IF :p32_ro_user_type = 9
    THEN
    v_sql := v_sql || ' and C_STATE in (''AZ'',''CA'',''HI'',''NV'') ';
    END IF;
    IF :p32_ro_user_type = 10
    THEN
    v_sql := v_sql || ' and C_STATE in (''AK'',''ID'',''OR'',''WA'') ';
    END IF;
    END IF;
    OPEN v_audit_cur FOR v_sql using :P32_USER_TYPE;
    LOOP
    FETCH v_audit_cur
    INTO usr_rec;
    EXIT WHEN v_audit_cur%NOTFOUND;
    j_sql :=
    j_sql
    || usr_rec.user_id
    || ', '
    || usr_rec.q_first
    || ', '
    || usr_rec.q_last
    || ', '
    || usr_rec.c_phone
    || ', '
    || usr_rec.c_email
    || UTL_TCP.crlf;
    END LOOP;
    CLOSE v_audit_cur;
    -- No need for this, you aren't changing anything
    -- COMMIT;
    -- Call mail procedure
    apex_mail.send (p_to => :p32_e_recipient,
    p_cc => '[email protected], [email protected]',
    p_from => '[email protected]',
    p_body => e_body_1 || j_sql || e_body_2,
    p_subj => 'Q Accounts Requiring Review'
    END;
    Hope this helps,
    Steve
    Alliance Technologies

Maybe you are looking for