Query or Procedure?

Hi all,
i try to explain my need by an example because i dont know how to tell it.
i have a table like this :
product | year  | quantity
paper   | 2008  | 147 
cd      | 2008  | 258 
paper   | 2009  | 369 
cd      | 2009  | 456 
end so on ... 2007 2006i would like to obtain a result like this
product | *current period* quantity | *previous period* quantity
paper   | 369                   | 147 
cd      | 456                   | 258  where period is not always the current year ( sysdate )
in order to be able to put it in a view.
i would like to know if exist a way to do something like:
select product, case year when ??year?? then quantity else 0, case year when ??year-1?? then quantity else 0using the value of field year as a kind of parameter.
if its not possible ( or even if it is ) its better to use a procedure?
Thanks to all.
Regards
Alessandro.

Hi, Allesandro,
The usual way to have parameterized views in Oracle is to store the parameters someplace where the view can reference them.
SYS_CONTEXT variables are often used for this, because several sesssions can each have their own values of the prameters, and run queries on the same view at the same time. SYS_CONTEXT can only store strings, so you often have to use conversion functions, like TO_NUMBER.
For example:
EXEC  set_view_x_year (2009);
SELECT    product
,       SUM ( CASE year
                     WHEN  TO_NUMBER (SYS_CONTEXT ('my_app', 'view_x_year'))
               THEN  quantity
               ELSE  0
          END
           )          AS current_quantity
,       SUM ( CASE year
                     WHEN  TO_NUMBER (SYS_CONTEXT ('my_app', 'view_x_year')) - 1
               THEN  quantity
               ELSE  0
          END
           )          AS previous_quantity
FROM      table_x
GROUP BY product
;To use a view like this, you first have to call a procedure (such as set_view_x_year, above) to set the SYS_CONTEXT varaible(s).
The varaibels will stay defined that way until you end the session (or you explicitly re-set them, of course), so you don;'t have to call the procedure every time you use the view.
You may want to build in default values, so the view will have some meaning even if you don't call the set-up procedure.
For example, to make the current year the default, you could replace
TO_NUMBER (SYS_CONTEXT ('my_app', 'view_x_year'))with
TO_NUMBER ( NVL ( SYS_CONTEXT ('my_app', 'view_x_year')
              , TO_CHAR (SYSDATE, 'YYYY')
       )     )

Similar Messages

  • Query Approcal Procedure per line for SO

    Dear all expert,
    I would like to make query approval procedure that will tell user to ask approval every time they enter transaction that has gross margin < 0. This approval will work per line transaction. I mean if in line 1 has gross margin > 0 but in line 2, the gross margin is < 0, the approval procedures will run.
    Thanks for all your help

    Hi,
    AFAIK it's not possible to have query approvl on document lines, but only on document header or footer.
    Without using the SDK, I know no ways to achieve it.
    Regards,
    Eric

  • Query builder, procedural builder - Oracle 8.17

    I'm running Oracle 8.17 and I can't find query builder, procedural builder, report builder form builder and other builders. Where can I get these? I tried the universal installer and there are no options to install them.

    Hi Fraser,
    Thank you for responding.
    I think I fixed that problem,actually there was a spelling
    mistake in one of the parameter files.
    But now I get another error message, says:
    "ORA: 02068: following severe error from MSOLEDB
    ORA: 28511: lost RPC connection to heterogenous
    remote agent using
    SID = (DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)
    (HOST=LOCAL_HOST)(PORT=1521)))(CONNECT_DATA=
    (SERVICE_NAME=<SERVICE_NAME>)))
    Do I have to configure the SQL Server network utilities?
    I pinged both the servers ,they talk to each other.
    But when I use tnsping ,the client machine (i.e.,the SQL Server
    machine)talks to server(Oracle machine) but the server doesn't
    talk to the client.
    I am definitely not doing something right.
    Asha.

  • SAP Query creation procedure

    Hi,
    Can any one send me complete procedure for creation of query in SQ03. Please give me step by step procedure
    Thanks,
    Regards,
    Mukul

    hi,
    in sq02 define the infoset. here u define the tables and the join relation between them. generate the infoset. in sq03 create user grps (if not already existing) and then assign the infosets to them. assign user ids to the the user grps.   in sq01 create the query in the infoset and define the list and selection fields. make sure u check the query area in which the infodset and the query is created (global or client sprcific).
    saurabh

  • To connect a datablock to a query - stored procedure: problem

    I have the following table...
    CREATE TABLE I_TIPOLOGIA (
    CODICE NUMBER(6),
    DESCRIZIONE VARCHAR2(100),
    CONSTRAINT I_TIPOLOGIA_PK PRIMARY KEY (CODICE) );
    and the following package to connect a datablock to
    previous table with a stored procedure...
    CREATE or REPLACE PACKAGE DATABANKER_TIPOLOGIE AS
    TYPE TipTableOfRec IS TABLE OF I_TIPOLOGIA%ROWTYPE;
    PROCEDURE leggi(resultset IN OUT TipTableOfRec);
    END DATABANKER_TIPOLOGIE;
    CREATE or REPLACE PACKAGE BODY DATABANKER_TIPOLOGIE AS
    PROCEDURE leggi(resultset IN OUT TipTableOfRec) AS
    BEGIN
    SELECT * BULK COLLECT INTO resultset
    FROM I_TIPOLOGIA;
    END leggi;
    END DATABANKER_TIPOLOGIE;
    When I compile the form I receive in QUERY-PROCEDURE trigger
    en error 306: "number or type of arguments are wrong in POPULATE_BLOCK"
    I post the trigger auto generated by Forms Builder 6i...
    DECLARE
    bk_data DATABANKER_TIPOLOGIE.TIPTABLEOFREC;
    BEGIN
    DATABANKER_TIPOLOGIE.leggi3(bk_data);
    PLSQL_TABLE.POPULATE_BLOCK(bk_data, 'BLOCCO50'); -- <- error here
    END;
    How can I solve this problem? Maybe there is a bug?
    P.S. I'm using Oracle Database 9i

    CREATE or REPLACE PACKAGE DATABANKER_TIPOLOGIE AS
    TYPE TipTableOfRec IS TABLE OF I_TIPOLOGIA%ROWTYPE;
    PROCEDURE leggi(resultset IN OUT TipTableOfRec);
    END DATABANKER_TIPOLOGIE;I have solved with this replacement 1) -> 2)
    1) TYPE TipTableOfRec IS TABLE OF I_TIPOLOGIA%ROWTYPE;
    2) TYPE TipTableOfRec IS TABLE OF I_TIPOLOGIA%ROWTYPE
    INDEX BY BINARY_INTEGER;
    with 2) now works.
    Now I have stored-procedures for query, insert, delete
    and update.
    I have some problems with delete and update of the records
    because it seems that they are locked.
    I think that it is due to the absence of lock
    stored-procedure... there's someone that can help me with
    the lock SP implementation?

  • Update query in procedure

    I have 2 tables aas below.
    create table main_data(id number,all_set_flag char(1),set_time timestamp)
    create table sub_data(id number,set_time timestamp);
    insert into main_data values(1,'','');
    insert into main_data values(1,'','');
    insert into main_data values(1,'','');
    insert into main_data values(1,'','');
    insert into main_data values(2,'Y','');
    insert into main_data values(2,'Y','');
    insert into main_data values(2,'Y','');
    My requirement is 1)For a particular id if all the all_set_flag is 'Y' then I need to insert the distinct id record and set_time as systimestamp in sub_data table
    2)Afer inserting into subdata for that particular id I need to update back in main_data set_time same as set_time in sub_data.
    a)For the part -1 I wrote an insert statement like this.For part-2 how can I update it bk?.
    b)I am going to use the below query in a procedure.Is there any better way to achieve this than below approach.Please note that my main_data have more columns(200 columns)
    and there are millions of records.10 million atleast.Please suggest.
    insert into sub_data(id,set_time)
    (select
    distinct
    id,
    systimestamp
    from
    select
    id,
    sum(case when all_set_flag = 'Y' then 1 else 0 end) over (partition by id) as match_cnt,
    count(*) over (partition by id) as total_count
    from main_data where not exists (Select null from sub_data where sub_data.id = main_data.id
    where match_cnt = total_count);
    select * from sub_data

    I am using a PL/SQL Collection type and doing it. Was think of doing it in plain SQL but combaining the Insert and Update i guess needs some PL/SQL.
    Here is what i did
    declare
      type main_data_id is table of main_data.id%type;
      type main_data_tm is table of main_data.set_time%type;
      lMainDataId main_data_id;
      lmainDataTm main_data_tm;
    begin
      select distinct id, systimestamp
      bulk collect into lMainDataId, lMainDataTm
        from (
              select a.* , count(*) over(partition by id) id_cnt, count(decode(all_set_flag, 'Y',1,null)) over(partition by id) flag_cnt
                from main_data a
       where id_cnt = flag_cnt;
      forall i in 1..lMainDataId.count
        insert into sub_data(id, set_time) values (lMainDataId(i), lMainDataTm(i));
      forall i in 1..lMainDataId.count
        update main_data set set_time = lMainDataTm(i) where id = lMainDataId(i);
      commit;
    end;
    /Waiting to see if someone has a better approach to it :)
    Note: I have not used LIMIT clause in BULK COLLECT because i dont have idea of the volume of data involved. If there is large volume of data then you need to consider using it.

  • Oracle 10g Insert query performs inconsistent as a query vs procedure and p

    Database Version: Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
    No error messages....
    I am facing a very weird issue that I have a insert statement in a procedure... pretty much
    inert
    into oracle_Table
    SELECT cr.a AS a,
    cr.b AS b,
    cr.c AS c,
    max(d.column_name) as d
    FROM "table 1"@Pmo.World Cr,
    [email protected] d
    WHERE d."a" = cr."column name"
    GROUP BY cr.a,
    cr.b,
    cr.c
    @Pmo.World is a database link to a MSSQL...
    The problem I am having right now is, every time I run this insert as a query. Everything works as what it should be... However, when I put this insert into a procedure, it inserts nothing...
    Simple test Proceudre:
    declare
    -- Local variables here
    i integer;
    begin
    inert
    into oracle_Table
    SELECT cr.a AS a,
    cr.b AS b,
    cr.c AS c,
    max(d.column_name) as d
    FROM "table 1"@Pmo.World Cr,
    [email protected] d
    WHERE d."a" = cr."column name"
    GROUP BY cr.a,
    cr.b,
    cr.c
    end;
    Thinking about character conversion issue I changed the procedure to
    inert
    into oracle_Table
    SELECT to_char(cr.a) AS a,
    to_char(cr.b) AS b,
    to_char(cr.c) AS c,
    max(d.column_name) as d
    FROM "table 1"@Pmo.World Cr,
    [email protected] d
    WHERE d."a" = cr."column name"
    GROUP BY cr.a,
    cr.b,
    cr.c
    Then this Inser works in the procedure... however when I revert it back with the original version that doesnt have to_char... it is working still... then I kept it running for few days... since it runs once per day, it was working for the first 2 days and then stopped working the third day... I verified the source table and every time this procedure runs, source tables were not empty...
    It is so confusing because if I manually run the insert as a query, it worked every time I ran it... however if I put that into a procedure, it works from time to time..
    Any help is highly apprecaited
    Edited by: 986006 on Feb 4, 2013 8:51 AM

    986006 wrote:
    Thanks for the hints up... I have updated my post... As I post the test procedure...it is about the exact the same as the insert query... Every time, the insert would actually insert data into the table but every time I run the test procedure, nothing gets inserted in... It sounds unbelievable but it happens... ThanksYou obviously haven't read the FAQ, or at least you haven't bothered doing what it asks. Help us to help you.
    Can you recreate the problem with simpler data on your local machine? If so provide create table and insert statements for test data.
    Format your code and place between tags.
    At the very least post the *exact* SQL or PL/SQL you are trying to run: what you've posted isn't even valid SQL.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

  • 2 set of conditions to use in a Single Select query in procedure

    Good day
    I have one procedure, want to use one 2 set of conditions in Where clause
    like
    where condition1 < value
    AND condition 2 > value
    AND condition 3 = value
    where condition 1 > value
    AND condition 2 < value
    AND condition 4 = value
    How we should combine in a single select statement where cluase.
    Please accept my sincere thanks first and looking your advice asap.
    Regards
    M.K.Thamaraiselvan

    Hi,
    While we use this procdure to run at that time it is not picking up any values also it is not running in it, taking very long time.What is not picking the value? Where clause is not picking the value, or
    where clause is picking the value but you are not getting the output.
    If it is you are not getting the output.
    I suggest to run the sql query individually without pl/sql and check if the records actually exist.
    Since it is taking very long time, I feel the sql query is actually being executed in the database but could be you are not getting the records (check if records actualy exist or if you are correctly passing the where clause)
    Regards
    Anurag
    PS:
    v_sql_string := 'SELECT table/viewname.colomn_name,'||v_order_by||','||v_report_line ||','||
    v_output_line||',table/viewname.check_amount'||v_from_clause||v_where_clause||' ORDER BY '||v_order_by;So you are using dynamic sql, can you add an extra line
    dbms_output.put_line(v_sql_string);
    and check what the actual query is formed by pl/sql, if you are satisified the query is correct run it through sql plus and check why oracle does not give the result. MAy be there is no records satisfiying this condition. And I am sure you meant either table or viewname in (table/viewname.colomn_name) and not something like what you posted.
    Edited by: Anurag Tibrewal on Oct 8, 2009 9:15 AM

  • FIFO in pl/sql query or procedure

    Hi,
    I have two tables:
    1)Table of recieved items
    create table receipts
    (item_id number(5),
    recieved_date date,
    recieved_quantity number,
    receipt_id number(5));
    insert into receipts(item_id, recieved_date, recieved_quantity, receipt_id)
    values(668, '29/12/10', 400, 441);
    insert into receipts(item_id, recieved_date, recieved_quantity, receipt_id)
    values(668, '29/12/10', 100, 442);
    insert into receipts(item_id, recieved_date, recieved_quantity, receipt_id)
    values(668, '03/02/11', 150, 444);2)Table of sold items
    create table deliveries
    (item_id number(5),
    delivered_date date,
    delivered_quantity number,
    delivery_id number(5));
    insert into deliveries(item_id, delivered_date, delivered_quantity, delivery_id)
    values(668, '01/02/11', 10, 1301);
    insert into deliveries(item_id, delivered_date, delivered_quantity, delivery_id)
    values(668, '02/02/11', 450, 1303);
    insert into deliveries(item_id, delivered_date, delivered_quantity, delivery_id)
    values(668, '08/02/11', 15, 1305);
    insert into deliveries(item_id, delivered_date, delivered_quantity, delivery_id)
    values(668, '09/02/11', 90, 1306);I need to track down from which batch goods are taken (for each delivery) using FIFO method.
    FIFO priorities are RECIEVED_DATE, RECEIPT_ID for INs and DELIVERED_DATE, DELIVERY_ID for OUTs.
    Desired output should be something like this:
    {noformat}
    ITEM_ID          DELIVERED_DATE  DELIVERED_QUANTITY      DELIVERY_ID     FROM_RECEIPT    STOCK_QUANTITY(*)
    668          01/02/11     10               1301          441          390
    668          02/02/11     390(**)               1303          441          0
    668          02/02/11     60(**)               1303          442          40
    668          08/02/11     15               1305          442          25
    668          09/02/11     25(**)               1306          442          0
    668          09/02/11     65(**)               1306          443          85
    {noformat}(*)Where STOCK_QUANTITY is the remaining quantity from that batch at the moment after according delivery amount deduction.
    (**)If the delivery gets the goods from different batches, the row should be split to display the amount taken from each batch.
    How can I make pl/sql query/procedure to track down this?
    Any help is very appreciated.
    DB version is: Oracle Database 11g Enterprise Edition Release 11.1.0.6.0
    Thank you,
    Nikita

    Hi, Nikita,
    Thanks for posting the CREATE TABLE and INSERT statements; that's very helpful.
    Use the analytic SUM functuion to get a running total of how much has been receeived and delivered to date. I did this in the sub-queries deliveries_rt and reciepts_rt:
    WITH     receipts_rt     AS
         SELECT     item_id
         ,     received_date
         ,     received_quantity
         ,     SUM (received_quantity) OVER ( PARTITION BY  item_id
                                        ORDER BY          received_date
                                    ,               receipt_id
                                  )      AS received_total
         ,     receipt_id
         FROM    receipts
    ,     deliveries_rt     AS
         SELECT     item_id
         ,     delivered_date
         ,     delivered_quantity
         ,     SUM (delivered_quantity) OVER ( PARTITION BY  item_id
                                         ORDER BY      delivered_date
                                     ,                delivery_id
                                  )      AS delivered_total
         ,     delivery_id
         FROM    deliveries
    SELECT       d.item_id
    ,       d.delivered_date
    ,       LEAST ( received_total  + delivered_quantity - delivered_total
                , delivered_total + received_quantity  - received_total
              , delivered_quantity    -- *****  See correction, below  *****
              )          AS delivered_quantity
    ,       d.delivery_id
    ,       r.receipt_id          AS from_receipt
    ,       GREATEST ( received_total - delivered_total
                   , 0
                 )          AS stock_quantity
    FROM       deliveries_rt     d
    JOIN       receipts_rt     r  ON     d.item_id        = r.item_id
                        AND     d.delivered_total  > r.received_total  - r.received_quantity
                      AND     r.received_total   > d.delivered_total - d.delivered_quantity
    ORDER BY  d.item_id
    ,            d.delivered_date
    ,       d.delivery_id
    ,            r.received_date
    ,       r.receipt_id
    ;What role does item_id play in this problem? I made a guess, but guessing isn't a very good way to solve problems.
    It may help to think of each row as having a low running total (or low_rt, the total quantity up to, but NOT including the current row) and a high running total (high_rt, the total qualntity up to AND including the current row). In the sub-queries above, I only computed the high_rt, since it's easy enough to get the low_rt from that by subtraction.
    Each row in the deliveries table will be joined to a row in the receipts table if the running totals overlap, that is, if the high_rt of each row is greaterr than the low_rt of the other.
    Delivered_quantity is the minimum of the high_rt from either table minus the low_rt of the other, but it can never be greater than the delivered_quantity.
    Edited by: Frank Kulash on Mar 3, 2011 10:06 AM
    Brief explanation added.
    Edited by: Frank Kulash on Apr 23, 2013 12:56 PM
    <H3>Correction</H3>
    The computation of delivered_quantity in the main query should have 1 more argument to LEAST, like this:
    ,       LEAST ( r.received_total  + d.delivered_quantity - d.delivered_total
                , d.delivered_total + r.received_quantity  - r.received_total
              , d.delivered_quantity
              , r.received_quantity               -- ***  Added  ***
              )          AS delivered_quantityThanks to Jean Marie Delhaze ( {message:id=10980754} below) for finding and correcting my mistake.

  • Problem binding variable to query in procedure

    Hi folks,
    I'm having an issue binding a variable to a query.  For example the following works in my procedure;
    DECLARE V_PLANT NVARCHAR(4) := 'ACME';
    tempVar = select field1 from myView where Plant = :V_PLANT;
    When I debug my procedure I can see the variable V_PLANT = 'ACME' and tempVar contains 1 single value (field1) record.
    Now, alternatively, if I try passing my variable like this it is not working (get error: no data found);
    DECLARE V_PLANT NVARCHAR(4) := 'ACME';
    ABCVariable NVARCHAR(45) := '';
    select field1 into ABCVariable from myView where Plant = :V_PLANT;
    However if I hard code the plant variable as a literal string like this I indeed get data;
    DECLARE V_PLANT NVARCHAR(4) := 'ACME';
    ABCVariable NVARCHAR(45) := '';
    select field1 into newVariable from myView where Plant = 'ACME';
    Result is I have a value of 'ACME' in ABCVariable.  It seems when I'm using SELECT INTO syntax I can no longer use variables in the where condition.
    Any suggestions?
    Thanks,
    -Patrick

    Hi Patrick
    I cannot reproduce this problem:
    create procedure get_article_by_label (IN v_article_label varchar)
    language sqlscript
    as
    begin
        declare v_article_id integer := -1;
        select max(article_id) into v_article_id
        from efashion.article_lookup
        where UPPER(article_label) like '%' || UPPER(:v_article_label) || '%';
        select * from efashion.article_lookup
        where article_id = :v_article_id;
    end;
    call get_article_by_label ('Leather Belt');
    ARTICLE_ID  ARTICLE_LABEL           CATEGORY            SALE_PRICE  FAMILY_NAME FAMILY_CODE
    143848      Patchwork Leather Belt  Belts,bags,wallets  88.9        Accessories F60       
    As you see I use the input variable in the WHERE condition, and reuse the found ID to select data again.
    Not sure though, why it doesn't work in your case.
    Is the target variable in your working example also ABCVariable or indeed newVariable?
    - Lars

  • View calling SQL query in procedure

    Hi,
    is it possible to see in SQL procedure the SQL query, which calls this procedure? I want to log that SQL when some error occurs.
    Thanks
    SASA

    I'll be interested to see if anyone has an easy solution to this. Here's a function that will get all the currently open cursors but that's not quite the solution ...
    create or replace function f
        return varchar2 is
        v_sql_text varchar2(32767);
    begin
        for rec in (
            select v$sqltext_with_newlines.sql_text
            into v_sql_text
            from v$open_cursor,
                v$sqltext_with_newlines
            where v$open_cursor.address = v$sqltext_with_newlines.address
                and v$open_cursor.hash_value = v$sqltext_with_newlines.hash_value
                and v$open_cursor.sid = (
                    select sid
                    from v$mystat
                    where rownum = 1)
                and (v$open_cursor.address, v$open_cursor.hash_value) != (
                    select sql_address,
                        sql_hash_value
                    from v$session
                    where sid = (
                        select sid
                        from v$mystat
                        where rownum = 1))
            order by v$sqltext_with_newlines.address,
                v$sqltext_with_newlines.piece
            ) loop
            v_sql_text := v_sql_text || rec.sql_text;
        end loop;
        return v_sql_text;
    end;

  • Need Help in with Querying Stored Procedures from UCCX Database

    Hi All
    We are trying to build a custom reporting solution using a BI tool and for which we have provided the ODBC connectivity to the UCCX database to our SQL server.
    We have installed the ODBC drivers on our SQL server and made a connection to UCCX version 10.0 successfully. we are using the username 'uccxhruser' to connect to the DSN.
    We want to query the stored procedure sp_csq_activity from the Microsoft SQL Server Management Studio. When we add the Linked Server in the SQL Server, we are able to see the Data Tables and also query them using the select statement. However, we are not able to see any of the Stored procedures within the Linked Server Tab.
    Can someone guide us in the right direction as to how to go about the process. Is calling the stored proedure the right way or we need to query the individual tables as mentioned in the Database Schema Guide and then once the historical tables our there in our server , then build the report.
    Any help will be much appreciated.
    Regards
    Abhinav

    Hi,
    what happens if you try to execute the above SP? They should be accessible AFAIK.
    G.

  • How do i fire a query/Stored procedure only once

    Hi,
    I have a master frame and multiple child frames. Master frame triggers child1 frame which triggers child 2 frame etc using some common keys between the frame.
    Now each frame executes a stored procedure and then uses the Db2 cursor as a record set. However when the same frame is fired again then the stored procedure is triggered again. But i could very well use the same record set from the record set that i already have,
    In other words i need to fire the stored procedure/query only once and not every time the frame is fired.
    I just need to get the record set for each frame and then operate on the retrieved record sets.
    Is there a way to do this?
    Currently I experience serious performance issues as the stored procedures get fired repeatedly thousands of times
    Any help will be greatly appreciated
    Thanks
    anand

    I am still haveing problems so I will try and attach my program and see if you can help a little more that. It will probably be easier for you to look at this way. When you look at the diagram sequence 0 is the one the problem is in. In that sequence you will see a case structure and that is where the finite pulse train vi is. When case 1 is selected the finite pulse train will run again and again until I leave case 1. I need to have the program run the finite pulse train once and then wait and do nothing until the case is changed. The finite pulse train will be in all cases inside the case structure I just haven't done that yet, I am waiting until it works. The pulse train is used to move a stepper motor that is why running only once is im
    portant because the stepper motor is used to position something.
    Attachments:
    AMC_Eagle_Both_Inputs_Working_2.vi ‏266 KB

  • Convert normalized query to procedure to function

    Hi,
    I have a table with this structure:
    CREATE TABLE TRANS
      ITEM_ID    VARCHAR2(8 BYTE),
      ITEM_TYPE  VARCHAR2(20 BYTE),
      ITEM_YEAR  NUMBER,
      JAN        FLOAT(126),
      FEB        FLOAT(126),
      MAR        FLOAT(126),
      APR        FLOAT(126),
      MAY        FLOAT(126),
      JUN        FLOAT(126),
      JUL        FLOAT(126),
      AUG        FLOAT(126),
      SEP        FLOAT(126),
      OCT        FLOAT(126),
      NOV        FLOAT(126),
      DEC        FLOAT(126)
    )I wrote the following PL/SQL to normalize the data into a few columns. Now I need help converting this to a package procedure, and this is where I am stuck.
    DECLARE
       TYPE c IS REF CURSOR;
       cur    c;
       TYPE r IS RECORD (
          itm   trans.item_id%TYPE,
          mth   VARCHAR2 (3),
          val   FLOAT
       rec    r;
       stmt   VARCHAR2 (200);
       item   VARCHAR (8)    := 'AB054240';
    BEGIN
       FOR i IN 1 .. 12
       LOOP
    -- calls function to return abbreviated month name
          stmt :=
                'SELECT item_id,  get_month_abbrev ('
             || i
             || '), '
             || get_month_abbrev (i)
             || ' FROM trans t WHERE t.item_id = '''
             || item
             || '''';
          OPEN cur FOR stmt;
          LOOP
             FETCH cur
              INTO rec;
             EXIT WHEN cur%NOTFOUND;
    -- test
             DBMS_OUTPUT.put_line ( rec.itm || chr(9) || rec.mth || chr(9) || rec.val);
          END LOOP;
       END LOOP;
       CLOSE cur;
    END;In searching online, I got the idea of creating an Object Type for the 'record' type and a Collection Type for the table based on the former.
    I would then open the table using a sys_refcursorUnfortunately, I could not get this to work. Ideally I would like to keep it all encapsulated in one procedure. I can't figure out a way to make an OUT parameter that will hold the table.
    The end result is that I have a client program that will execute this procedure/function to return the normalized query result set for display.
    Any suggestion or critique would be appreciated.

    I still don't understand why you feel the need for looping round to create your dynamic SQL when you could just use static SQL (eg, like the query I gave you earlier)?
    If you're wanting to take a row and turn it on its side, then the query I provided would do what you wanted:
    with trans as (select 1 item_id, 'A' item_type, 2009 item_year, 10 jan, 20 feb, 30 mar, 40 apr, 50 may, 60 jun, 70 jul, 80 aug, 90 sep, 100 oct, 110 nov, 120 dec from dual union all
                   select 1 item_id, 'A' item_type, 2008 item_year, 110 jan, 120 feb, 130 mar, 140 apr, 150 may, 160 jun, 170 jul, 180 aug, 190 sep, 1100 oct, 1110 nov, 1120 dec from dual union all
                   select 2 item_id, 'C' item_type, 2009 item_year, 210 jan, 220 feb, 230 mar, 240 apr, 250 may, 260 jun, 270 jul, 280 aug, 290 sep, 2100 oct, 2100 nov, 2120 dec from dual),
    -- end of mimicking data in your table
    month_tab as (select 'JAN' month_name from dual union all
                   select 'FEB' month_name from dual union all
                   select 'MAR' month_name from dual union all
                   select 'APR' month_name from dual union all
                   select 'MAY' month_name from dual union all
                   select 'JUN' month_name from dual union all
                   select 'JUL' month_name from dual union all
                   select 'AUG' month_name from dual union all
                   select 'SEP' month_name from dual union all
                   select 'OCT' month_name from dual union all
                   select 'NOV' month_name from dual union all
                   select 'DEC' month_name from dual)
    SELECT tr.item_id "Item",
           mt.month_name "Month",
           DECODE(mt.month_name, 'JAN', tr.jan,
                                 'FEB', tr.feb,
                                 'MAR', tr.mar,
                                 'APR', tr.apr,
                                 'MAY', tr.may,
                                 'JUN', tr.jun,
                                 'JUL', tr.jul,
                                 'AUG', tr.aug,
                                 'SEP', tr.sep,
                                 'OCT', tr.oct,
                                 'NOV', tr.nov,
                                 'DEC', tr.dec) "Amount"
    FROM   trans tr,
           month_tab mt
    WHERE  tr.item_id = 1 --p_item_id
    AND    tr.item_year = 2009 --p_item_year;
          Item Month     Amount
             1 JAN           10
             1 FEB           20
             1 MAR           30
             1 APR           40
             1 MAY           50
             1 JUN           60
             1 JUL           70
             1 AUG           80
             1 SEP           90
             1 OCT          100
             1 NOV          110
             1 DEC          120There are several advantages for using one static query:
    1. Easier to debug: the query is right there - you can copy it out of the procedure, change the parameters and then run it to see what values were being returned. You do not have to manually construct the query prior to running it.
    2. Less code, less steps - therefore increased performance and easier maintenance. You no longer have an extra function call that the database needs to execute every time it runs the query.
    3. More efficient code; no need to access the table 12 times, as the above query only accesses the table once. Again, leading to improved performance.
    4. Easier to read and there maintain.
    5. The PL/SQL engine won't check dynamic sql until runtime; if you've made a syntax error, the code will still compile, but will fail at runtime. With static SQL, the code won't compile until you've fixed all syntax errors.
    6. Dynamic sql won't show up in the dependencies views (eg. user_dependencies), so makes it harder to track what tables are used by your code.
    In short, avoid dynamic SQL if you can, stick to doing as much of the work in SQL as you can and hopefully you'll have faster and easier-to-maintain code.

  • A query as procedure parameter

    Dear members,
    (Forms 6i c/s)
    I'd like to send a query through a parameter to a procedure.
    The query has to be in a cursor.
    How can I do ?
    Can I send the text of the query, and tell Forms to use it as a query when declaring the cursor ?
    Can I send the cursor through a parameter ?
    Thanks for your help.

    Can you, sure. Should you? At most, rarely.
    You can use dynamic SQL (EXECUTE IMMEDIATE or DBMS_SQL) to execute an arbitrary string as a SQL statement. There are serious security issues if someone figures out how to pass a dangerous SQL statement in (i.e. update the USERS table, delete all the data from some important table, etc). If you are passing in a SELECT statement and you don't know the structure of the result set, you have to use DBMS_SQL rather than the simpler EXECUTE IMMEDIATE and use a more complicated API to describe the result set.
    Justin

  • SQL QUERY into PROCEDURE

    Hi! I am a newbie in PL/SQL..
    Can somebody teach me on how to make this SQL QUERY into a PROCEDURE?
    TABLE 1: LOGS
    TABLE 2: MASTER LIST
    Logs = records the logs
    Master list = list of all registered name.
    select * from table1
    where not exists
    select host, user, name
    from table2
    where table2.host = table1.host and
    table2.user = table1.user and
    table2.name = table1.name
    TABLE 1
    HOST | USER | NAME
    ==============
    1 | A | A1
    1 | A | A1
    1 | A | A1
    1 | A | D1
    TABLE 2
    HOST | USER | NAME
    =============
    1 | A | A1
    1 | A | B1
    1 | A | C1
    Result:
    HOST | USER | NAME
    ===============
    1 | A | D1
    Thanks. :)

    QKWS wrote:
    Hi! I am a newbie in PL/SQL..
    Can somebody teach me on how to make this SQL QUERY into a PROCEDURE?
    TABLE 1: LOGS
    TABLE 2: MASTER LIST
    Logs = records the logs
    Master list = list of all registered name.
    select * from table1
    where not exists
    select host, user, name
    from table2
    where table2.host = table1.host and
    table2.user = table1.user and
    table2.name = table1.name
    TABLE 1
    HOST | USER | NAME
    ==============
    1 | A | A1
    1 | A | A1
    1 | A | A1
    1 | A | D1
    TABLE 2
    HOST | USER | NAME
    =============
    1 | A | A1
    1 | A | B1
    1 | A | C1
    Result:
    HOST | USER | NAME
    ===============
    1 | A | D1
    Thanks. :)Hi,
    Question is not clear, really.
    Do you want that, I don't sure?
    CREATE TABLE t1 ( CHOST NUMBER,  CUSER VARCHAR2(10), CNAME VARCHAR2(10));
    INSERT INTO t1 VALUES(1,'A','A1');
    INSERT INTO t1 VALUES(1,'A','A1');
    INSERT INTO t1 VALUES(1,'A','A1');
    INSERT INTO t1 VALUES(1,'A','D1');
    Commit;
    CREATE TABLE t2 AS  SELECT *  FROM t1;
    INSERT INTO t2 VALUES(1,'A','A1');
    INSERT INTO t2 VALUES(1,'A','B1');
    INSERT INTO t2 VALUES(1,'A','C1');
    commit;
    select * from t1  table1
    WHERE NOT EXISTS
    ( SELECT 1 FROM t2 table2
       WHERE table2.chost = table1.chost
         AND table2.cuser = table1.cUSER
         AND table2.cNAME = table1.cNAME
    DECLARE
    P_HOST T1.CHOST%TYPE;
    P_USER T1.CUSER%TYPE;
    P_NAME T1.CNAME%TYPE;
    BEGIN
    select CHOST, CUSER,CNAME INTO P_HOST,P_USER, P_NAME
    from t1  table1
    WHERE NOT EXISTS
    ( SELECT 1 FROM t2 table2
       WHERE table2.chost = table1.chost
         AND table2.cuser = table1.cUSER
         AND table2.cNAME = table1.cNAME
    dbms_output.put_line('HOST | USER | NAME  : '|| TO_CHAR(P_HOST)||' | '||P_USER||' | '||P_NAME);
    END;
    /Regards
    Mahir M. Quluzade

Maybe you are looking for