Browsing "Older Posts"

APEX-AT-WORK no image

Example Merge Procedure

Von Tobias Arnhold → 8.18.2013
I often have used UPDATE and INSERT statements during my development. In some complex updates especially when I had to select from other tables I sometimes got strange problems.

I even was able to update the wrong data because my statement was not correctly designed. After this experience I decided to switch to MERGE-statements. Merge Statements are easy to read especially when you use difficult select statements inside.

Here is an example package with an MERGE statement inside. It should show you how such an statement could look like and for me it is a good reminder how to design the code.

create or replace 
PACKAGE BODY PKG_MERGE_EXAMPLE AS
/* Package Variables */
  gv_proc_name    VARCHAR2(100);
  gv_action       VARCHAR2(4000);
  gv_ora_error    VARCHAR2(4000);
  gv_custom_error VARCHAR2(4000);
  gv_parameter    VARCHAR2(4000);
  gv_user         VARCHAR2(20) := UPPER(NVL(v('APP_USER'),USER));
  
/* Save errors */
/*
  --------------------------------------------------------
  --  DDL for Table ZTA_ERR_LOG
  --------------------------------------------------------

  CREATE TABLE "ERR_LOG" 
   ( "PROC_NAME" VARCHAR2(200), 
 "ACTION" VARCHAR2(4000), 
 "APP_ID" NUMBER, 
 "APP_PAGE_ID" NUMBER, 
 "APP_USER" VARCHAR2(20), 
 "ORA_ERROR" VARCHAR2(4000), 
 "CUSTOM_ERROR" VARCHAR2(4000), 
 "PARAMETER" VARCHAR2(4000), 
 "TIME_STAMP" DATE
   ) ;
/

*/
PROCEDURE ADD_ERR  IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
     INSERT
     INTO ERR_LOG
      ( PROC_NAME,ACTION,APP_ID,APP_PAGE_ID,APP_USER,ORA_ERROR,CUSTOM_ERROR,PARAMETER,TIME_STAMP )
      VALUES
      ( gv_proc_name,gv_action,nvl(v('APP_ID'),0),nvl(v('APP_PAGE_ID'),0),nvl(nvl(v('APP_USER'),USER),'Unknown'),
        gv_ora_error,gv_custom_error,gv_parameter,sysdate );
     COMMIT;
END;


/* ************************************************************************************************************************************** */
/* Merge Example                                                                                                                          */  
/* ************************************************************************************************************************************** */

PROCEDURE prc_merge_example
IS
BEGIN
  gv_proc_name := 'pkg_merge_example.prc_merge_example';
  gv_parameter := '';
  
  gv_action := 'Merge Data instead of update and insert'; 
  MERGE INTO TBL_MERGE_FACILITY t1
   USING (
          SELECT  t2.id,
                  t2.facility_name,
                  t3.address
                  gv_user as current_user,
                  sysdate as current_timestamp
          FROM TBL_FACILITY t2, TBL_ADDRESS t3
          WHERE t2.address_id = t3.id
          AND   t2.activ = 1
         ) t4
  ON (t1.facility_id = t4.id)
  WHEN MATCHED THEN
    UPDATE SET
      t1.facility_name    = t4.facility_name,
      t1.facility_address = t4.address,
      t1.updated_by       = t4.current_user,
      t1.updated_on       = t4.current_timestamp
  WHEN NOT MATCHED THEN
    INSERT
  (
    facility_id,
    facility_name,
    facility_address,
    created_by,
    created_on
  )
  VALUES
  (
    t4.id,
    t4.facility_name,
    t4.address,
    t4.current_user,
    t4.current_timestamp
  );

  gv_action := 'Updated rows: ' sql%rowcount; 
  
  COMMIT;
EXCEPTION
WHEN OTHERS THEN   
      gv_ora_error := SQLERRM;
      gv_custom_error := 'Internal Error. Action canceled.';
      ROLLBACK;
      ADD_ERR; raise_application_error(-20001, gv_custom_error);
END;
 
END PKG_MERGE_EXAMPLE;
APEX-AT-WORK no image

Connect a grouped report to an ungrouped report with virtual ID column

Von Tobias Arnhold → 8.16.2013
Seems to be a simple problem. I have and grouped report where I want to see all facilities on a address.

For example:
Grouped View
EditAddressAmount of facilities
xGermany, Dresden, Dresdner Strasse 12
xGermany, Frankfurt, Frankfurter Strasse 13

Detail View
AddressFacility
Germany, Dresden, Dresdner Strasse 1Computer System EXAXY
Germany, Dresden, Dresdner Strasse 1Computer System KI
Germany, Frankfurt, Frankfurter Strasse 1Manufactoring System 007
Germany, Frankfurt, Frankfurter Strasse 1Manufactoring System 009
Germany, Frankfurt, Frankfurter Strasse 1Manufactoring System 028

How to achieve this when we do not have a primary key and our key column includes commas which breaks the link. We easily generate an own ID column via an analytical function. In both reports we use an Oracle view to get the data from and our view looks like that:
select   facility_address,
         facility_name,
         dense_rank() over (order by facility_address) as facility_id
from     facilities
Via the function dense_rank and the partition by facility_address we get an unique ID for all facilities based on the address.
The grouped report looks like that:
select   facility_id,
         facility_address,
         count(facility_name) as amount_of_facilities
from     facilities
The detail report looks like that
select   facility_address,
         facility_name
from     facilities
where    facility_id = :P2_FACILITY_ID
Now you need to add a link in the report attributes section inside the grouped report. We set the item :P2_FACILITY_ID with our column #FACILITY_ID#.
That's it.

Getting the amount of rows from report with jQuery

Von Tobias Arnhold → 5.16.2013
I had the task to show the amount of displayed rows from a standard report on another position of the page. As "Pagination Scheme" in the "Report Attributes" I used: "Row Ranges X to Y from Z"

To get this Z value I needed to check the HTML code:



<td nowrap="nowrap" class="pagination">
   <span class="fielddata">Zeile(n) 1 - 15 von 329</span>
</td>
Inside class "fielddata" was my value Z. To get the value I needed this little piece of jQuery:
var v_txt = $('.fielddata').html();
var v_num = v_txt.split(' ');
var v_return= v_num[v_num.length - 1]; 
APEX-AT-WORK no image

Expand APEX tree after page load

Von Tobias Arnhold → 5.03.2013
This little snippet of code will expand the APEX tree:
$("input:[value='Expand All']").click();
This solutions finds the HTML objects by the displayed value. Use it in a "Dynamic Action > Page Load > Execute Javascript" process.

In case you use multi language applications then this solution will fit better:
http://apextips.blogspot.de/2011/03/expand-and-collapse-all-tree-nodes.html
APEX-AT-WORK no image

Generate DDL Source Code with SQL

Von Tobias Arnhold → 3.27.2013
I just found this little piece of code to create DDL source code.
SELECT dbms_metadata.get_ddl(replace(OBJECT_TYPE, ' ', '_'), OBJECT_NAME,OWNER) as DDL_SOURCE_CODE
FROM ALL_OBJECTS
WHERE OBJECT_TYPE IN 
   ('SEQUENCE',   'TABLE',           'INDEX',
    'VIEW',       'DATABASE LINK',   'MATERIALIZED VIEW',
    'FUNCTION',   'PROCEDURE',       'PACKAGE',
    'PACKAGE BODY'
    )
AND OWNER = '#SCHMEA_NAME#';
APEX-AT-WORK no image

Migrate Sequences

Von Tobias Arnhold → 3.22.2013
During one of my projects I had an issue when I copied the DDL from my test environment into my productive system. Unfortunately I needed some of the test data in the prod system as well. For that I had to migrate most of the sequences starting with their last number. SQL Developer created those sequences starting with 1. This simple code fixed my issue.
select 'DROP SEQUENCE "'||SEQUENCE_NAME||'";' || 
       ' CREATE SEQUENCE "'||SEQUENCE_NAME||'"' ||
       ' MINVALUE 1 MAXVALUE 999999999999999999999999999' ||
       ' INCREMENT BY 1 START WITH ' || to_char(last_number+1) ||
       ' NOCACHE NOORDER NOCYCLE ; ' as seq_code
from all_sequences
where sequence_owner = '#SCHEMA_NAME#';
Cheers Tobias