Thursday, December 12, 2019

Inserting Negative values into a table in Oracle

SQL> SET DEFINE OFF;
SQL> SET LINES 100;
SQL> SET PAGES 50;
SQL>
SQL> DROP TABLE t;

Table dropped.

SQL>
SQL> CREATE TABLE t(msg  VARCHAR2 (11), num_col NUMBER (9, 2));

Table created.

SQL>
SQL> INSERT INTO t (msg, num_col) VALUES ('9994999', TO_NUMBER ('9994999'));

1 row created.

SQL> INSERT INTO t (msg, num_col) VALUES ('9994999.99', TO_NUMBER ('9994999.99'));

1 row created.

SQL> INSERT INTO t (msg, num_col) VALUES ('-9994999.99', TO_NUMBER ('-9994999.99'));

1 row created.

SQL> INSERT INTO t (msg, num_col) VALUES ('+7777777.99', TO_NUMBER ('+7777777.99'));

1 row created.

SQL> COMMIT;

Commit complete.

SQL>
SQL> SELECT * FROM t;

MSG            NUM_COL
----------- ----------
9994999        9994999
9994999.99  9994999.99
-9994999.99   -9995000
+7777777.99 7777777.99

SQL>
SQL> create table b(b number);

Table created.

SQL> insert into b values(to_number('-1'));

1 row created.

SQL> insert into b values(to_number('-2'));

1 row created.

SQL> insert into b values(to_number('-3'));

1 row created.

SQL> insert into b values(to_number('-4'));

1 row created.

SQL> insert into b values(to_number('-5'));

1 row created.

SQL> commit;

Commit complete.

SQL> select * from b;

         B
----------
        -1
        -2
        -3
        -4
        -5

SQL>

Wednesday, December 11, 2019

Customize LOGIN PAGE Using CSS in Oracle Apex

1. Upload the Image to your Workspace from App Builder > App > Shared Component

2. Go to Page Desginer >  CSS > Inline and Add Below Code

Logo Design Code

span.t-Login-logo
{
  background-image: url(#APP_IMAGES#savelife_logo.jpg);
  background-size: cover;
  width: 120px;
  height:120px; 
}

Background Image Code

.t-PageBody--login .t-Body
{
    background: url(#APP_IMAGES#red.jpg);
    background-repeat: no-repeat;
    background-size: cover;
}

in (Application Express 19.2.0.00.18)

.t-PageBody--login .t-Login-container
{
    background: url(#APP_IMAGES#red.jpg);
    background-repeat: no-repeat;
    background-size: cover;
}

How to parse JSON in Oracle 11g and 12c

Oracle 11g:

SQL> set serveroutput on;
SQL> DECLARE
  2      s varchar2(32767) := '{ "a": 1, "b": ["hello", "world"]}';
  3  BEGIN
  4      apex_json.parse(s);
  5      sys.dbms_output.put_line('a is '||apex_json.get_varchar2(p_path => 'a'));
  6      sys.dbms_output.put_line('b1 is '||apex_json.get_varchar2(p_path => 'b[1]'));
  7      sys.dbms_output.put_line('b2 is '||apex_json.get_varchar2(p_path => 'b[2]'));
  8  END;
  9  /
a is 1
b1 is hello
b2 is world

PL/SQL procedure successfully completed.

SQL>
SQL> declare
  2      sample_json   varchar2 (32767)
  3          := '{
  4      "glossary": {
  5          "title": "example glossary",
  6          "GlossDiv": {
  7              "title": "S",
  8              "GlossList": {
  9                  "GlossEntry": {
 10                      "ID": "SGML",
 11                      "SortAs": "SGML",
 12                      "GlossTerm": "Standard Generalized Markup Language",
 13                      "Acronym": "SGML",
 14                      "Abbrev": "ISO 8879:1986",
 15                      "GlossDef": {
 16                          "para": "A meta-markup language, used to create markup languages such as DocBook.",
 17                          "GlossSeeAlso": ["GML", "XML"]
 18                      },
 19                      "GlossSee": "markup"
 20                  }
 21              }
 22          }
 23      }
 24  }';
 25  begin
 26      apex_json.parse (sample_json);
 27      dbms_output.put_line (apex_json.get_varchar2 ('glossary.GlossDiv.title'));
 28      dbms_output.put_line (apex_json.get_varchar2 ('glossary.GlossDiv.GlossList.GlossEntry.GlossTerm'));
 29      dbms_output.put_line (apex_json.get_varchar2 ('glossary.GlossDiv.GlossList.GlossEntry.GlossDef.GlossSeeAlso[%d]', 2));
 30  end;
 31  /
S
Standard Generalized Markup Language
XML

PL/SQL procedure successfully completed.

SQL>
SQL> declare
  2      sample_json   varchar2 (32767)
  3          := '{
  4     "parameters":    {
  5        "active_users": "%",
  6        "all_completions": "Y",
  7        "content_object_id": "47630968",
  8        "email": "%",
  9        "excl_status_list": "N,I,BK",
 10        "expired_date_from": "%",
 11        "folder_id": "%",
 12        "get_cert_by_oe_last_update": "N",
 13        "is_completed": "%",
 14        "modified_date_from": "09-DEC-2019",
 15        "modified_date_to": "20-DEC-2019",
 16        "object_id": "%",
 17        "org_id": "%",
 18        "sDateDisplay": "E",
 19        "sTruncateDateOnly": "N"
 20     },
 21     "reportStatus":    {
 22        "runId": 322053,
 23        "status": "Running",
 24        "statusInfo": null,
 25        "startDate": "2019-12-11T00:07:02",
 26        "endDate": null,
 27        "timeTaken": "00:00:01",
 28        "totalResults": 0
 29     }
 30  }';
 31  begin
 32      apex_json.parse (sample_json);
 33      dbms_output.put_line (apex_json.get_varchar2 ('parameters.modified_date_from'));
 34      dbms_output.put_line (apex_json.get_varchar2 ('parameters.modified_date_to'));
 35
 36      dbms_output.put_line (apex_json.get_varchar2 ('reportStatus.runId'));
 37      dbms_output.put_line (apex_json.get_varchar2 ('reportStatus.status'));
 38      dbms_output.put_line (apex_json.get_varchar2 ('reportStatus.statusInfo'));
 39      dbms_output.put_line (apex_json.get_varchar2 ('reportStatus.startDate'));
 40      dbms_output.put_line (apex_json.get_varchar2 ('reportStatus.endDate'));
 41      dbms_output.put_line (apex_json.get_varchar2 ('reportStatus.timeTaken'));
 42      dbms_output.put_line (apex_json.get_varchar2 ('reportStatus.totalResults'));
 43  end;
 44  /
09-DEC-2019
20-DEC-2019
322053
Running
2019-12-11T00:07:02
00:00:01
0

PL/SQL procedure successfully completed.

SQL>


Oracle 12c:

CREATE TABLE json_documents (
  id    RAW(16) NOT NULL,
  data  CLOB,
  CONSTRAINT json_documents_pk PRIMARY KEY (id),
  CONSTRAINT json_documents_json_chk CHECK (data IS JSON)
);

INSERT INTO json_documents (id, data)
VALUES (SYS_GUID(),
        '{
          "FirstName"      : "John",
          "LastName"       : "Doe",
          "Job"            : "Clerk",
          "Address"        : {
                              "Street"   : "99 My Street",
                              "City"     : "My City",
                              "Country"  : "UK",
                              "Postcode" : "A12 34B"
                             },
          "ContactDetails" : {
                              "Email"    : "john.doe@example.com",
                              "Phone"    : "44 123 123456",
                              "Twitter"  : "@johndoe"
                             },
          "DateOfBirth"    : "01-JAN-1980",
          "Active"         : true
         }');


SELECT a.data FROM json_documents a;

json value respponse


SELECT a.data.FirstName,
       a.data.LastName,
       a.data.Address.Postcode AS Postcode,
       a.data.ContactDetails.Email AS Email
FROM   json_documents a;


FIRSTNAME       LASTNAME        POSTCODE   EMAIL
--------------- --------------- ---------- -------------------------
Jayne           Doe             A12 34B    jayne.doe@example.com
John            Doe             A12 34B    john.doe@example.com

2 rows selected.

How to consume Web Service (POST) in Oracle


SET DEFINE OFF;
SET SERVEROUTPUT ON;

DECLARE
   P_REPORT_CODE   VARCHAR2 (100) := '111.111';
   P_OFFSET        NUMBER := 1;
   P_LIMIT         NUMBER := 20000;
   req             UTL_HTTP.req;
   resp            UTL_HTTP.resp;
   l_buffer        VARCHAR2 (32767);
   x_clob          CLOB;
   my_scheme       VARCHAR2 (256);
   my_realm        VARCHAR2 (256);
   my_proxy        BOOLEAN;
   url             VARCHAR2 (500);
   content         VARCHAR2 (4000);
BEGIN
   url :=
         'https://test-stage.oracle.com/ws/report/execute/'
      || P_REPORT_CODE
      || '?offset='
      || P_OFFSET
      || '&limit='
      || P_LIMIT;

   content :=
         '{
"modified_date_from":  "'
      || TO_CHAR (SYSDATE - 2, 'DD-MON-YYYY')
      || '",
"modified_date_to": "'
      || TO_CHAR (SYSDATE, 'DD-MON-YYYY')
      || '",
"content_object_id": "47630968",
"sDateDisplay": "E"
}';

   UTL_TCP.close_all_connections ();
   UTL_HTTP.set_wallet ('file:/u01/app/oracle/dba/rdbms/test/wallet');
   UTL_HTTP.set_proxy ('http://dmz-proxy-test.us.oracle.com:80');
   UTL_HTTP.set_response_error_check (FALSE);
   req := UTL_HTTP.begin_request (url, 'POST', 'HTTP/1.1');
   UTL_HTTP.set_body_charset (req, 'UTF-8');
   UTL_HTTP.set_header (
      req,
      'Authorization',
      'Bearer abcdefghijklmnopqrstuvwxyz');
   UTL_HTTP.set_header (req, 'Content-Type', 'application/json');
   UTL_HTTP.set_header (req, 'Content-Length', LENGTHB (content));
   UTL_HTTP.set_header (req, 'Connection', 'Keep-Alive');
   DBMS_OUTPUT.put_line ('url=' || url);
   DBMS_OUTPUT.put_line ('content=' || content);
   UTL_HTTP.write_text (req, content);
   resp := UTL_HTTP.get_response (req);
   DBMS_OUTPUT.put_line ('HTTP response status code: ' || resp.status_code);
   DBMS_OUTPUT.put_line (
      'HTTP response reason phrase: ' || resp.reason_phrase);

   /* Copy the response to local*/
   DBMS_LOB.createtemporary (x_clob, FALSE);
   DBMS_LOB.open (x_clob, DBMS_LOB.lob_readwrite);

   BEGIN
      LOOP
         UTL_HTTP.read_text (resp, l_buffer);
         DBMS_LOB.writeappend (x_clob, LENGTH (l_buffer), l_buffer);
      END LOOP;
   EXCEPTION
      WHEN UTL_HTTP.end_of_body
      THEN
         DBMS_OUTPUT.PUT_LINE ('x_clob=' || x_clob);
         UTL_HTTP.END_RESPONSE (resp);
   END;
EXCEPTION
   WHEN UTL_HTTP.end_of_body
   THEN
      UTL_HTTP.end_response (resp);
   WHEN UTL_HTTP.too_many_requests
   THEN
      UTL_HTTP.end_response (resp);
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.PUT_LINE ('Oracle Error:' || SQLERRM);
END;
/

Monday, December 9, 2019

NULL functions ( NVL, NVL2, NULLIF and COALESCE) in Oracle

SQL> COLUMN RESULT FORMAT A10
SQL> SELECT NVL('X','Y') AS RESULT FROM DUAL;

RESULT
----------
X

SQL> SELECT NVL(NULL,'Y') AS RESULT FROM DUAL;

RESULT
----------
Y

SQL> SELECT NVL(NULL,NULL) AS RESULT FROM DUAL;

RESULT
----------


SQL>
SQL> SELECT NVL2('X','Y','Z') AS RESULT FROM DUAL;

RESULT
----------
Y

SQL> SELECT NVL2(NULL,'Y','Z') AS RESULT FROM DUAL;

RESULT
----------
Z

SQL> SELECT NVL2('X',NULL,'Z') AS RESULT FROM DUAL;

RESULT
----------


SQL> SELECT NVL2(NULL,'Y',NULL) AS RESULT FROM DUAL;

RESULT
----------


SQL> -- both parameters are same then returns NULL else first parameter as output
SQL> SELECT NULLIF('X','X') AS RESULT FROM DUAL;

RESULT
----------


SQL> SELECT NULLIF('X','Y') AS RESULT FROM DUAL;

RESULT
----------
X

SQL> SELECT NULLIF(NULL,'Y') AS RESULT FROM DUAL;
SELECT NULLIF(NULL,'Y') AS RESULT FROM DUAL
              *
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected - got CHAR


SQL> SELECT NULLIF('X',NULL) AS RESULT FROM DUAL;

RESULT
----------
X

SQL> -- returns first not null parameter value
SQL> SELECT COALESCE('A','B','C','D') AS RESULT FROM DUAL;

RESULT
----------
A

SQL> SELECT COALESCE(NULL,'B','C','D') AS RESULT FROM DUAL;

RESULT
----------
B

SQL> SELECT COALESCE(NULL,NULL,'C','D') AS RESULT FROM DUAL;

RESULT
----------
C

SQL> SELECT COALESCE(NULL,NULL,NULL,'D') AS RESULT FROM DUAL;

RESULT
----------
D

SQL> SELECT COALESCE(NULL,NULL,NULL,NULL) AS RESULT FROM DUAL;

RESULT
----------


SQL>

How to get unique records without using distinct in oracle

nSQL> set lines 100
SQL> set pages 50
SQL> drop table employee;

Table dropped.

SQL> create table employee(empno number,ename varchar2(10));

Table created.

SQL> insert into employee values (1,'raj');

1 row created.

SQL> insert into employee values (1,'raj');

1 row created.

SQL> insert into employee values (2,'siva');

1 row created.

SQL> insert into employee values (3,'pavan');

1 row created.

SQL> insert into employee values (3,'pavan');

1 row created.

SQL> commit;

Commit complete.

SQL> select * from employee;

     EMPNO ENAME
---------- ----------
         1 raj
         1 raj
         2 siva
         3 pavan
         3 pavan

Using DISTINCT:

SQL> select distinct empno,ename from employee order by 1,2;

     EMPNO ENAME
---------- ----------
         1 raj
         2 siva
         3 pavan

Without using DISTINCT:

SQL> select unique empno,ename from employee order by 1,2;

     EMPNO ENAME
---------- ----------
         1 raj
         2 siva
         3 pavan

SQL> select empno,ename from employee group by empno,ename order by 1,2;

     EMPNO ENAME
---------- ----------
         1 raj
         2 siva
         3 pavan

SQL> select empno,ename from employee
  2  union
  3  select empno,ename from employee;

     EMPNO ENAME
---------- ----------
         1 raj
         2 siva
         3 pavan

SQL> select empno,ename from employee
  2  union
  3  select null,null from employee where 1=2;

     EMPNO ENAME
---------- ----------
         1 raj
         2 siva
         3 pavan

SQL> select empno,ename from employee
  2  minus
  3  select null,null from employee where 1=2;

     EMPNO ENAME
---------- ----------
         1 raj
         2 siva
         3 pavan

SQL> select empno,ename from
  2  (
  3  select empno,ename,
  4  row_number() over(partition by empno,ename order by empno,ename) as rn from employee
  5  )
  6  where rn=1;

     EMPNO ENAME
---------- ----------
         1 raj
         2 siva
         3 pavan

SQL> select empno,ename from
  2  (
  3  select empno,ename,
  4  rank() over(partition by empno,ename order by rownum) as rn from employee
  5  )
  6  where rn=1;

     EMPNO ENAME
---------- ----------
         1 raj
         2 siva
         3 pavan

SQL>
SQL> select empno,ename from
  2  (
  3  select empno,ename,
  4  dense_rank() over(partition by empno,ename order by rownum) as rn from employee
  5  )
  6  where rn=1;

     EMPNO ENAME
---------- ----------
         1 raj
         2 siva
         3 pavan

SQL>

Wednesday, December 4, 2019

PL/SQL Standards

 1. Use Soft Parsing ( Bind variables) instead of hard parsing
(https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2588723819082)
 2. Use Table Cast if reuired
 3. Use EXISTS instead of IN Operator
 4. Maintain Comments across Code
 5. Local Variable names prefix with V_
Global Variables prefix with G_
Constant variables prefix with C_
Date variables prefix with D_
Function Name Prefix with F_
Procedure name prefix with P_
Type names prefix with T_
Object names prefix with O_
Cursor Names prefix with Cur_
Ref cursor Variables prefix with Ref_
 6. Try to avoid Loops as much as possible
 7. Try to Avoid Like Operator use = if possible
 8. Use appropriate Hints if required
 9. Use EXECUTE IMMEDIATE Statement to perform DDL, DML Operations (Dynamic SQL)
 10. Use NOLOGGING while creating table dynamically
 11. Reuse code from common packages if required and create common packages if useful to all API's
 12. Use Global Temporary tables if request xml contains any lists ( occurance >1)
 13. Follow Indentation better to understand the code

************************************************ CRITICAL ************************************************************

1. SQL - Avoid CROSS JOIN queries
--------------------------------------------------------------------------------------------------------------------------------
A CROSS JOIN query will return all records where each row from the first table is combined with each row from the second table. This means that such a query returns the cartesian product of the sets of rows from the joined tables (which is why it is also know as "cartesian product query").
Such a query can return a huge amount of data, and therefore should be used only with great caution and only when really needed.
Here are the 2 kind of syntaxes for cross join queries:

BEGIN
  -- Standard ANSI syntax
  SELECT *
    INTO employeeArray
    FROM employee CROSS JOIN department; -- Non-Compliant
END;
/

and

BEGIN
  -- Old syntax
  SELECT *
    INTO employeeArray
    FROM employee, department; -- Non-Compliant
END;
/

2. SQL - Avoid using DELETE or UPDATE without a WHERE clause
-------------------------------------------------------------------------------------------------------------------------
DELETE or UPDATE queries have most of the time a WHERE clause. Therefore, the rare cases in which the WHERE clause is missing should be reviewed to ensure that it was not unintentionally forgotten - which could lead to data loss.

For example:

DECLARE
  maxAge PLS_INTEGER := 60;
BEGIN
  UPDATE employee SET status = 'retired'; -- Non-Compliant - the WHERE was forgotten
END;
/

should be replaced by:

DECLARE
  maxAge PLS_INTEGER := 60;
BEGIN
  UPDATE employee SET status = 'retired' WHERE age > maxAge; -- Compliant
END;
/

3. Pipelined functions should have at least one PIPE ROW statement and not return any expression (PLS-00633)
-----------------------------------------------------------------------------------------------------------------------
Pipelined functions offers the ability to create programmatically generated tables. One of the benefits of such functions is that they reduce memory consumption as results are not all kept in memory before being returned. Instead of relying on RETURN, PIPE ROW must be used to return the results, one row at a time.
Trying to return an expression from a pipelined function raises PLS-00633: RETURN statement in a pipelined function cannot contain an expression

For instance:

CREATE OR REPLACE TYPE myScalarType AS OBJECT
(
  dummy   VARCHAR2(42)
)
/
CREATE OR REPLACE TYPE myTableType AS TABLE OF myScalarType;
/

CREATE OR REPLACE FUNCTION foo RETURN myTableType PIPELINED AS  -- Non-Compliant, should contain at least one PIPE ROW
  result myTableType := myTableType();
BEGIN
  FOR i IN 1 .. 3 LOOP
    result.EXTEND;
    result(i) := myScalarType('Dummy ' || i);
  END LOOP;

  RETURN result;                                                -- Non-Compliant, will raise PLS-00633
END;
/

LINE/COL ERROR
-------- -----------------------------------------------------------------
9/3      PLS-00633: RETURN statement in a pipelined function cannot
         contain an expression

SELECT * FROM TABLE(foo());

DROP FUNCTION foo;
DROP TYPE myTableType;
DROP TYPE myScalarType;

should be refactored into:

-- ...

CREATE OR REPLACE FUNCTION foo RETURN myTableType PIPELINED AS -- Compliant
BEGIN
  FOR i IN 1 .. 3 LOOP
    PIPE ROW(myScalarType('Dummy ' || i));
  END LOOP;

  RETURN;                                                      -- Compliant
END;
/


SQL> SELECT * FROM TABLE(foo());

DUMMY
------------------------------------------
Dummy 1
Dummy 2
Dummy 3


4. PL/SQL - Do not mix positional and named arguments in invocations (PLS-00312)
----------------------------------------------------------------------------------------------------
For better readability, and to prevent the PLS-00312: a positional parameter association may not follow a named association exception from being raised,
do not mix named and positional argument invocations.
The following code snippet illustrates this rule:

SET SERVEROUTPUT ON

DECLARE
  PROCEDURE sub(op1 PLS_INTEGER, op2 PLS_INTEGER) AS
  BEGIN
    DBMS_OUTPUT.PUT_LINE('Sub = ' || (op1 - op2));
  END;
BEGIN
  sub(10, 2); -- Compliant
  sub(op1 => 10, op2 => 2); -- Compliant

  sub(10, op2 => 2); -- Non-Compliant
  sub(op1 => 10, 2); -- Non-Compliant - raises PLS-00312: a positional parameter association may not follow a named association
END;
/

5. Sensitive SYS owned functions should not be used
--------------------------------------------------------------------------------------------------------------
Some Oracle packages contain powerful SYS owned functions that can be used to perform malicious operations.
For instance, DBMS_SYS_SQL.PARSE_AS_USER can be used to execute a statement as another user.
Most programs do not need those functions and this rule allows to hunt them in order to prevent security risks.

Example:

DECLARE
  c INTEGER;
  sqltext VARCHAR2(100) := 'ALTER USER system IDENTIFIED BY hacker'; -- Might be injected by the user
BEGIN
  c := SYS.DBMS_SYS_SQL.OPEN_CURSOR();                               -- Non-Compliant

   -- Will change 'system' user's password to 'hacker'
  SYS.DBMS_SYS_SQL.PARSE_AS_USER(c, sqltext, DBMS_SQL.NATIVE, UID);  -- Non-Compliant

  SYS.DBMS_SYS_SQL.CLOSE_CURSOR(c);                                  -- Non-Compliant
END;
/

List of package names that should be detected Default Value:
DBMS_SYS_SQL,DBMS_BACKUP_RESTORE,DBMS_LOB,DBMS_NAMESPACE,DBMS_SCHEDULER,DBMS_RANDOM,EMD_SYSTEM,UTL_FILE,UTL_HTTP,UTL_SMTP,UTL_TCP


*************************************** BLOCKER **************************************************

1. PL/SQL - Do not declare a variable more than once in a given scope (PLS-00371)
-------------------------------------------------------------------------------------------
At most one declaration of a variable in a given scope is allowed in PL/SQL. The PLS-00371 error will be raised at runtime when attempting to reference a variable declared more than once.

The following code snippet:

SET SERVEROUTPUT ON

DECLARE
  foo VARCHAR2(42) := 'foo';
  foo VARCHAR2(42) := 'bar'; -- Non-Compliant
BEGIN
  DBMS_OUTPUT.PUT_LINE(foo); -- Raises PLS-00371: at most one declaration for 'FOO' is permitted
END;
/

should be refactored into:

SET SERVEROUTPUT ON

DECLARE
  foo VARCHAR2(42) := 'foo';
  bar VARCHAR2(42) := 'bar'; -- Compliant
BEGIN
  DBMS_OUTPUT.PUT_LINE(foo);
END;
/

2. SQL - Do not COMMIT/ROLLBACK from a trigger unless it is in an autonomous transaction
--------------------------------------------------------------------------------------------------
Calling COMMIT or ROLLBACK from within a trigger will lead to an ORA-04092 exception, unless the trigger has its own autonomous transaction.

The following code snippet illustrates this rule:

SET SERVEROUTPUT ON

CREATE TABLE accounts(
  balance NUMBER
);

INSERT INTO accounts VALUES(0);

CREATE TABLE log(
  message VARCHAR2(100)
);

-- Version 1: Does not log anything, as the INSERT is rolled back together with the main transaction
CREATE TRIGGER beforeLogger
  BEFORE UPDATE ON accounts
  FOR EACH ROW
BEGIN
  INSERT INTO log VALUES('Attempt to update the value from ' || :OLD.balance || ' to ' || :NEW.balance);
END;
/

-- Version 2: Fails with a "ORA-04092: cannot COMMIT in a trigger", the trigger cannot commit the main transaction
CREATE OR REPLACE TRIGGER beforeLogger
  BEFORE UPDATE ON accounts
  FOR EACH ROW
BEGIN
  INSERT INTO log VALUES('Attempt to update the value from ' || :OLD.balance || ' to ' || :NEW.balance);
  COMMIT; -- Non-Compliant, will fail with a ORA-04092
END;
/

-- Version 3: This is the correct way
CREATE OR REPLACE TRIGGER beforeLogger
  BEFORE UPDATE ON accounts
  FOR EACH ROW
DECLARE
  PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  INSERT INTO log VALUES('Attempt to update the value from ' || :OLD.balance || ' to ' || :NEW.balance);
  COMMIT; -- Compliant, commits the trigger's autonomous transaction, not the main one
END;
/

-- We want to be able to log any attempt to update the "accounts" table
BEGIN
  UPDATE accounts SET balance = 99;
  ROLLBACK; -- Ultimately, this update is rolled back, however we still want to log it
END;
/

SELECT * FROM log;

DROP TRIGGER beforeLogger;

DROP TABLE log;

DROP TABLE accounts;

3. NULL - Use IS NULL and IS NOT NULL instead of direct NULL comparisons
----------------------------------------------------------------------------------------

In PL/SQL, the following code snippet:

SET SERVEROUTPUT ON

DECLARE
  name VARCHAR2(42) := ''; /* This is equivalent to name := NULL; */
BEGIN
  IF name = '' THEN /* Non-Compliant - always evaluates to FALSE and is equivalent to name = NULL */
    DBMS_OUTPUT.PUT_LINE('True'); /* Unreachable */
  ELSE
    DBMS_OUTPUT.PUT_LINE('False');
  END IF;
END;
/

will display False, which is counter-intuitive and can lead to unreachable code.

The correct way to write the code above is:

SET SERVEROUTPUT ON

DECLARE
  name VARCHAR2(42) := ''; /* This is equivalent to name := NULL; */
BEGIN
  IF name IS NULL THEN /* Compliant */
    DBMS_OUTPUT.PUT_LINE('True');
  ELSE
    DBMS_OUTPUT.PUT_LINE('False');
  END IF;
END;
/

4. PL/SQL - A variable declared NOT NULL must have an initialization assignment (PLS-00218)
-------------------------------------------------------------------------------------------------------
Variables and fields declared as NOT NULL must be immediately initialized, as they cannot be implicitly initialized to the NULL value. This rule prevents PLS-00218 exceptions from being raised at runtime.

The following code snippet illustrates this rule:

SET SERVEROUTPUT ON

DECLARE
  test PLS_INTEGER; -- This variable is implicitly initialized to NULL

 foo1 PLS_INTEGER NOT NULL; -- Non-Compliant PLS-00218 a variable declared NOT NULL must have an initialization assignment
  foo2 PLS_INTEGER NOT NULL := 42; -- Compliant

  TYPE myType IS RECORD(
   foo1 PLS_INTEGER NOT NULL, -- Non-Compliant PLS-00218 a variable declared NOT NULL must have an initialization assignment
    foo2 PLS_INTEGER NOT NULL := 42, -- Compliant
    bar PLS_INTEGER NULL
  );
BEGIN
  IF test IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('test is NULL');
  ELSE
    DBMS_OUTPUT.PUT_LINE('test is NOT NULL');
  END IF;
END;
/

5. DATATYPES - Do not constrain types that cannot be constrained (PLS-00566)
--------------------------------------------------------------------------
Some types cannot be constrained, and attempting to do so results in the exception PLS-00566: type name "..." cannot be constrained being raised.

The following code:

DECLARE
  foo BLOB(42); -- Non-Compliant - raises PLS-00566: type name "BLOB" cannot be constrained
BEGIN
  NULL;
END;
/

should be refactored into:

DECLARE
  foo BLOB; -- Compliant
BEGIN
  NULL;
END;
/

6. DATATYPES - Do not specify a scale on float types (PLS-00510)
--------------------------------------------------------------------------
Float data types, such as FLOAT, DOUBLE PRECISION or REAL cannot have a scale constraint. Trying to specify a scale results in the exception PLS-00510: Float cannot have scale being raised.

The following code:

DECLARE
  foo FLOAT(10, 3); -- Non-Compliant - raises PLS-00510
BEGIN
  NULL;
END;
/

should be refactored into:

DECLARE
  foo FLOAT(10); -- Compliant
BEGIN
  NULL;
END;
/

7. DATATYPES - Do not use improper constraint forms (PLS-00572)
------------------------------------------------------------------------------
Not every data types supports the RANGE or scale constraints. Using these constraints on those types result in an PLS-00572: improper constraint form used exception being raised.

The following code:

DECLARE
  foo INTEGER RANGE 0 .. 42; -- Non-Compliant - raises PLS-00572 as NUMBER does not support the RANGE constraint
BEGIN
  NULL;
END;
/

should be refactored into:

DECLARE
  foo INTEGER; -- Compliant
BEGIN
  NULL;
END;
/

8. PL/SQL - RAISE_APPLICATION_ERROR must raise only error with code between -20'000 and -20'999 (ORA-21000)
----------------------------------------------------------------------------------------------------------------
RAISE_APPLICATION_ERROR must be called with an error code between -20'000 to -20'999, which is the range reserved for application errors. When called with another value, Oracle raises the exception: ORA-21000: error number argument to raise_application_error of 0 is out of range

The following code:

BEGIN
  RAISE_APPLICATION_ERROR(0, 'This is an application error'); -- Non-Compliant - raises ORA-21000
END;
/

should be refactored into:

BEGIN
  RAISE_APPLICATION_ERROR(-20000, 'This is an application error'); -- Compliant
END;
/

9. DATATYPES - Do not constrain anchored (%TYPE or %ROWTYPE) types
-----------------------------------------------------------------------------------
Anchored types, i.e. specified using either %TYPE or %ROWTYPE, cannot be constrained. Trying to do so results in the exception PLS-00573: cannot constrain scale, precision, or range of an anchored type being raised.

The following code:

DECLARE
  foo DUAL.DUMMY%TYPE(42); -- Non-Compliant - raises PLS-00573
BEGIN
  NULL;
END;
/

should be refactored into:

DECLARE
  foo DUAL.DUMMY%TYPE; -- Compliant
BEGIN
  NULL;
END;
/

10. DATATYPES - Do not use the BYTE length semantic on NCHAR / NVARCHAR2 (PLS-00639)
-----------------------------------------------------------------------------------------------------------------
NCHAR and NVARCHAR2 length semantic must be given in characters and not in bytes. Indeed, a single national character may occupy more than a single byte in memory. Oracle will allocate the appropriate amount of bytes to store the requested number of characters. Trying to specify the length semantics in bytes will result in the PLS-00639: NCHAR/NVARCHAR2 cannot be byte length semantics exception being raised.

The following code:

DECLARE
  foo NCHAR(42 BYTE); -- Non-Compliant - raises PLS-00639
BEGIN
  NULL;
END;
/

should be refactored into:

DECLARE
  foo NCHAR(42);      -- Compliant
  bar NCHAR(42 CHAR); -- Also compliant, as an alternative
BEGIN
  NULL;
END;
/

11. DATATYPES - Specify the size constraint on string types (PLS-00215)
---------------------------------------------------------------------------------
String data types, such as VARCHAR2 or NVARCHAR2 require a size constraint. Omitting the size results in the exception PLS-00215: String length constraints must be in range (1 .. 32767) being raised.

The following code:

DECLARE
  foo VARCHAR2; -- Non-Compliant - raises PLS-00215
BEGIN
  NULL;
END;
/

should be refactored into:

DECLARE
  foo VARCHAR2(42); -- Compliant
BEGIN
  NULL;
END;
/

12. PACKAGE - Avoid RETURN statements in the initialization section of PACKAGE BODY
-----------------------------------------------------------------------------------------------------
In a CREATE PACKAGE BODY, the purpose of the initialization section part is to set the initial values of the packages global variables. It is therefore surprising to find a RETURN statement there, as all its following statements will be unreachable.

The following code snippet illustrates this rule:

SET SERVEROUTPUT ON

CREATE OR REPLACE PACKAGE foo1 AS
  FUNCTION getBar RETURN PLS_INTEGER;
  bar PLS_INTEGER;
END;
/

CREATE OR REPLACE PACKAGE BODY foo1 AS
  FUNCTION getBar RETURN PLS_INTEGER AS
  BEGIN
    RETURN bar; -- Compliant
  END;
BEGIN
  bar := 42;
  DBMS_OUTPUT.PUT_LINE('package loaded');
  RETURN; -- Non-Compliant
  DBMS_OUTPUT.PUT_LINE('this is unreachable code');
END;
/

DROP PACKAGE BODY foo;

DROP PACKAGE foo;



PL/SQL - Do not declare a variable more than once in a given scope (PLS-00371)
plsql:VariableRedeclaration  

    Bug  Blocker No tags Available Since June 19, 2013 SonarQube (PL/SQL) Constant/issue: 1h 

At most one declaration of a variable in a given scope is allowed in PL/SQL. The PLS-00371 error will be raised at runtime when attempting to reference a variable declared more than once.

The following code snippet:

SET SERVEROUTPUT ON

DECLARE
  foo VARCHAR2(42) := 'foo';
  foo VARCHAR2(42) := 'bar'; -- Non-Compliant
BEGIN
  DBMS_OUTPUT.PUT_LINE(foo); -- Raises PLS-00371: at most one declaration for 'FOO' is permitted
END;
/

should be refactored into:

SET SERVEROUTPUT ON

DECLARE
  foo VARCHAR2(42) := 'foo';
  bar VARCHAR2(42) := 'bar'; -- Compliant
BEGIN
  DBMS_OUTPUT.PUT_LINE(foo);
END;
/

http://dist.sonarsource.com/reports/coverage/rules_in_plsql.html

***************************************** 1 to 20 MINOR ***************************************************************************************************

1. Single line comments should prefixed by "--"
-----------------------------------------------------------------------------------------------------
 The multi-line comment syntax "/* ... */" should not be used for single line comments, for which the "--" syntax is more appropriate.
 The following code snippet illustrates this rule:
-- This comment line is Compliant/Standard

/*
These comment lines are also Compliant
comment 1
comment 2
*/

/*
This comment line is also Compliant
*/

/* But this one is bad and should be rewritten using the "--" syntax Non-Compliant */


FORMAT - Each line in a /* ... */ comment should start with a "*"
Multi-line comments are more readable when each line is aligned using the "*" character. At most one violation is created for each comment
The following code snippet illustrates this rule:

/*
this line is not aligned and ugly Non-Compliant
no violation is created on this line, even though is it also bad
 */

/*
 * this is much better Compliant
 */

/* this is Compliant */



2.FORMAT - Reserved words should be written in upper case
--------------------------------------------------------------------------------------------------
 Writing reserved words in upper case increases the code readability.
 The following code snippet illustrates this rule:
BEGIN
  NULL;
  null; -- Non-Compliant
END;
/


Reserved words should be written in lower case
All reserved words should be written using the same case to ensure consistency in the code. This rule checks that they are all in lower case.
The following code snippet illustrates this rule:

begin
  null;
  NULL; -- Non-Compliant
end;
/


3. Complex IF statements should be replaced by CASE ones
---------------------------------------------------------------------------------------------------
Complex chains of IF, ELSIF and ELSE statements should be replaced by the more readable CASE one.
A complex IF statement has either several ELSIF clauses, or both an ELSIF and an ELSE clause.

For instance, the following code:

DECLARE
  x PLS_INTEGER := 0;
BEGIN
  IF x = 0 THEN                     -- Non-Compliant
    DBMS_OUTPUT.PUT_LINE('x = 0');
  ELSIF x = 1 THEN
    DBMS_OUTPUT.PUT_LINE('x = 1');
  ELSIF x = 2 THEN
    DBMS_OUTPUT.PUT_LINE('x = 2');
  END IF;
END;
/

should be refactored into:

DECLARE
  x PLS_INTEGER := 0;
BEGIN
  CASE x                            -- Compliant
    WHEN 0 THEN
      DBMS_OUTPUT.PUT_LINE('x = 0');
    WHEN 1 THEN
      DBMS_OUTPUT.PUT_LINE('x = 1');
    WHEN 2 THEN
      DBMS_OUTPUT.PUT_LINE('x = 2');
    ELSE
      -- Do not forget the ELSE to prevent ORA-06592
      NULL;
  END CASE;
END;
/

and, the following code:

DECLARE
  x PLS_INTEGER := 0;
  y PLS_INTEGER := 0;
BEGIN
  IF x = 0 THEN                     -- Non-Compliant
    DBMS_OUTPUT.PUT_LINE('x = 0, y = ?');
  ELSIF y = 1 THEN
    DBMS_OUTPUT.PUT_LINE('x != 0, y = 1');
  ELSE
    DBMS_OUTPUT.PUT_LINE('x != 0, y != 1');
  END IF;
END;
/

should be refactored into:

DECLARE
  x PLS_INTEGER := 0;
  y PLS_INTEGER := 0;
BEGIN
  CASE                              -- Compliant
    WHEN x = 0 THEN
      DBMS_OUTPUT.PUT_LINE('x = 0, y = ?');
    WHEN y = 1 THEN
      DBMS_OUTPUT.PUT_LINE('x != 0, y = 1');
    ELSE
      DBMS_OUTPUT.PUT_LINE('x != 0, y != 1');
  END CASE;
END;
/

4.FUNCTIONS - The last statement must be a RETURN one
-----------------------------------------------------------------------------------------------------------
Always having a RETURN statement as the last one in a function is a good practice for two main reasons:

    It prevents the ORA-06503 "PL/SQL: Function returned without value" error.
    It prevents unreachable code from being added after the RETURN.

The following code snippet illustrates this rule:

CREATE FUNCTION incorrectFunction1 RETURN PLS_INTEGER IS -- Non-Compliant
BEGIN
  RETURN 42;

   -- This is unreachable code
   NULL;
END;
/

DROP FUNCTION incorrectFunction1;

CREATE FUNCTION incorrectFunction2 RETURN PLS_INTEGER IS -- Non-Compliant
BEGIN
   NULL; -- This function was expected to return a PLS_INTEGER, but did not. Will lead to ORA-06503
END;
/

BEGIN
  DBMS_OUTPUT.PUT_LINE('Ret = ' || incorrectFunction2); -- ORA-06503 PL/SQL: Function returned without value
END;
/

DROP FUNCTION incorrectFunction2;

CREATE FUNCTION correctFunction RETURN PLS_INTEGER IS -- Compliant
BEGIN
  RETURN 42;
END;
/

DROP FUNCTION correctFunction;

5.FORMAT - Avoid initializing variables with null
---------------------------------------------------------------------------------------
Explicit variable initialization with null values are superfluous, since they are already implicitly initialized to null.

The following code snippet illustrates this rule:

SET SERVEROUTPUT ON

DECLARE
  foo PLS_INTEGER := NULL; -- Non-Compliant, the null assignation is superfluous/unnecessary
  bar VARCHAR2(100) := ''; -- Non-Compliant, the null assignation is superfluous

  correctEmptyString VARCHAR2(100);
  correctInitializedString VARCHAR2(100) := 'Hello world!';
BEGIN
  IF foo IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('foo is NULL');
  ELSE
    DBMS_OUTPUT.PUT_LINE('foo is NOT NULL');
  END IF;
 
  IF correctEmptyString IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('correctEmptyString is NULL');
  ELSE
    DBMS_OUTPUT.PUT_LINE('correctEmptyString is NOT NULL');
  END IF;
END;
/

Output:

foo is NULL
correctEmptyString is NULL

PL/SQL procedure successfully completed.

6. FORMAT - Avoid long lines
----------------------------------------------------------------------------------------------
Keep the line length small for better readability of the code.
The maximum authorized line length --> Default Value:80

7. LITERALS - Avoid using magic literals
---------------------------------------------------------------------------------------------
8. NAMING CONVENTION - Constants
---------------------------------------------------------------------------------------------
Each constant name must match a given regular expression.
The following code snippet illustrates this rule:

DECLARE
  goodConstant CONSTANT PLS_INTEGER := 42; -- Compliant
  badConstant_ CONSTANT PLS_INTEGER := 42; -- Non-Compliant
BEGIN
  NULL;
END;
/

The regular expression the name should match --> Default Value:[a-zA-Z]([a-zA-Z0-9_]*[a-zA-Z0-9])?

9. NAMING CONVENTION - Cursors
----------------------------------------------------------------------------------------------------
Each cursor name must match a given regular expression.
The following code snippet illustrates this rule:

CREATE TABLE employee(
  name VARCHAR2(42)
);

DECLARE
  CURSOR goodCursor RETURN employee%ROWTYPE; -- Compliant
  CURSOR badCursor_ RETURN employee%ROWTYPE; -- Non-Compliant

  CURSOR goodCursor RETURN employee%ROWTYPE IS SELECT * FROM employee; -- Compliant
  CURSOR badCursor_ RETURN employee%ROWTYPE IS SELECT * FROM employee; -- Non-Compliant
BEGIN
  NULL;
END;
/

DROP TABLE employee;

10. NAMING CONVENTION - Exceptions
-------------------------------------------------------------------------------------------------------
Each exception name must match a given regular expression.
The following code snippet illustrates this rule:

DECLARE
  goodException EXCEPTION; -- Compliant
  badException_ EXCEPTION; -- Non-Compliant
BEGIN
  NULL;
END;
/

The regular expression the name should match --> Default Value:[a-zA-Z]([a-zA-Z0-9_]*[a-zA-Z0-9])?

11. NAMING CONVENTION - Functions and procedures parameters
----------------------------------------------------------------------------------------------------------
Each function and procedure parameter name must match a given regular expression.
The following code snippet illustrates this rule:

DECLARE
  FUNCTION myfunction1(goodParameter PLS_INTEGER) RETURN PLS_INTEGER; -- Compliant
  FUNCTION myfunction2(badParameter_ PLS_INTEGER) RETURN PLS_INTEGER; -- Non-Compliant

  PROCEDURE myprocedure1(goodParameter PLS_INTEGER); -- Compliant
  PROCEDURE myprocedure2(badParameter_ PLS_INTEGER); -- Non-Compliant

  FUNCTION myfunction1(goodParameter PLS_INTEGER) RETURN PLS_INTEGER AS -- Compliant
  BEGIN
    RETURN 42;
  END;

  FUNCTION myfunction2(badParameter_ PLS_INTEGER) RETURN PLS_INTEGER AS -- Non-Compliant
  BEGIN
    RETURN 42;
  END;

  PROCEDURE myprocedure1(goodParameter PLS_INTEGER) AS -- Compliant
  BEGIN
    NULL;
  END;

  PROCEDURE myprocedure2(badParameter_ PLS_INTEGER) AS -- Non-Compliant
  BEGIN
    NULL;
  END;
BEGIN
  NULL;
END;
/

The regular expression the name should match --> Default Value:[a-zA-Z]([a-zA-Z0-9_]*[a-zA-Z0-9])?

12. NAMING CONVENTION - Object attributes
----------------------------------------------------------------------------------------
Sharing some naming conventions is a key point to make it possible for a team to efficiently collaborate. This rule allows to check that all object attribute names match a provided regular expression.
The following code:

CREATE TYPE my_type AS OBJECT(
  foo__bar INTEGER             -- Non-Compliant
);
/

DROP TYPE my_type;

should be refactored into:

CREATE TYPE my_type AS OBJECT(
  foo_bar INTEGER              -- Compliant
);
/

DROP TYPE my_type;

The regular expression the name should match Default Value:[a-zA-Z](_?+[a-zA-Z0-9])*+

13. NAMING CONVENTION - Record fields
----------------------------------------------------------------------
Sharing some naming conventions is a key point to make it possible for a team to efficiently collaborate. This rule allows to check that all record field names match a provided regular expression.
The following code:

DECLARE
  TYPE my_type IS RECORD(
    foo__bar PLS_INTEGER   -- Non-Compliant
  );
BEGIN
  NULL;
END;
/

should be refactored into:

DECLARE
  TYPE my_type IS RECORD(
    foo_bar PLS_INTEGER    -- Compliant
  );
BEGIN
  NULL;
END;
/

14. NAMING CONVENTION - Variables
-----------------------------------------------------------------------------------------------
Each variable name must match a given regular expression.
The following code snippet illustrates this rule:

DECLARE
  goodVariable PLS_INTEGER; -- Compliant
  badVariable_ PLS_INTEGER; -- Non-Compliant
BEGIN
  NULL;
END;
/

The regular expression the name should match Default Value:[a-zA-Z]([a-zA-Z0-9_]*[a-zA-Z0-9])?

15. PARAMETER - Ensure parameters mode is explicitly specified as IN
----------------------------------------------------------------------------------
By default, the parameter mode is IN. However, mentioning it explicitly does make the code easier to read.
The following code snippet illustrates this rule:

SET SERVEROUTPUT ON

DECLARE
  PROCEDURE printNameBad(name VARCHAR2) AS -- Non-Compliant, avoid to rely on the default mode
  BEGIN
    DBMS_OUTPUT.PUT_LINE('name: ' || name);
  END;

  PROCEDURE printNameGood(name IN VARCHAR2) AS -- Compliant
  BEGIN
    DBMS_OUTPUT.PUT_LINE('name: ' || name);
  END;
BEGIN
  printNameBad('Foo');
  printNameGood('Bar');
END;
/

16. NAMING CONVENTION - Function and procedure names
-----------------------------------------------------------------------------------------------
Each function and procedure name must match a given regular expression.
The following code snippet illustrates this rule:

CREATE FUNCTION goodFunction RETURN PLS_INTEGER AS -- Compliant
BEGIN
  RETURN 42;
END;
/

CREATE FUNCTION badFunction_ RETURN PLS_INTEGER AS -- Non-Compliant
BEGIN
  RETURN 42;
END;
/

DROP FUNCTION goodFunction;

DROP FUNCTION badFunction_;

The regular expression function and procedure names should match Default Value:[a-zA-Z]([a-zA-Z0-9_]*[a-zA-Z0-9])?

17. NAMING CONVENTION - Package names
-------------------------------------------------------------------------------------------------------------------
Each package name must match a given regular expression.
The regular expression package names should match Default Value: [a-zA-Z]([a-zA-Z_]*[a-zA-Z])?

18. Return of boolean expressions should not be wrapped into an "IF-THEN-ELSE" statement
------------------------------------------------------------------------------------------
Return of boolean literal statements wrapped into IF-THEN-ELSE ones should be simplified.
Noncompliant Code Example

IF expression THEN
  RETURN TRUE;
ELSE
  RETURN FALSE;
END IF;

Compliant Solution

RETURN expression;

19. String literals should not be duplicated
-------------------------------------------------------------------------------------
Duplicated string literals make the process of refactoring error-prone, since you must be sure to update all occurrences. On the other hand, constants can be referenced from many places, but only need to be updated in a single place.
Noncompliant Code Example

BEGIN
  prepare('action1');
  execute('action1');
  release('action1');
END;
/

Compliant Solution

DECLARE
  action CONSTANT VARCHAR2(7) := 'action1';
BEGIN
  prepare(action);
  execute(action);
  release(action);
END;
/

20. Comments should not be located at the end of lines of code
--------------------------------------------------------------------------------------------------
This rule verifies that single-line comments are not located at the end of a line of code. The main idea behind this rule is that in order to be really readable, trailing comments would have to be property written and formatted (correct alignment, no interference with the visual structure of the code, not too long to be visible) but most often, automatic code formatters would not handle this correctly: the code would end up less readable. Comments are far better placed on the previous empty line of code, where they will always be visible and properly formatted.

However, this rule allows to write trailing "metadata comments" - for which the pattern is configurable, as those metadata comments are usually very short and heavily used in some cases.

// The following line is non-compliant
int a1 = b + c; // This is a trailing comment that can be very very long

// This very long comment is better placed before the line of code
int a2 = b + c;

// The following line is compliant with the default configuration of the rule
String a3 = "id"; // $NON-NLS-1$

Pattern for text of trailing comments that are allowed.Default Value:(?s)^(?:\s*+[^\s]++|\+.*+)$

******************************************* 21,22,23,24 - INFO ************************************************************************************

21. SQL - Review each usage of FULL OUTER JOIN
-----------------------------------------------------------------------
Many developers do not properly understand full outer joins, as it is not commonly used. Therefore, each usage of this language feature should be reviewed.
The following code illustrates this rule:

BEGIN
  SELECT *
  BULK COLLECT INTO result
  FROM DUAL d1
  FULL OUTER JOIN DUAL d2 ON d1.dummy != d2.dummy; -- Non-Compliant
END;
/


22. Avoid the usage of the NOSONAR marker
-----------------------------------------------------------------------------------------------
Any violation can be deactivated with the using the NOSONAR marker.
This marker is useful to exclude specific exceptions but can abusively used to hide real quality flaws.
This rule allows to review and/or forbid the use of this marker.

The following code snippet illustrates this rule:

DECLARE
  FUNCTION GET_ANSWER RETURN PLS_INTEGER IS
  BEGIN
    RETURN 42; -- NOSONAR This magic number is allowed here as an exception Non-Compliant
  END;
BEGIN
  NULL;
END;
/

23. PL/SQL parser failure
--------------------------------------------------------------------------------------------
When the PL/SQL parser fails, it is possible to record the failure as a violation on the file. This way, not only it is possible to track the number of files that do not parse but also to easily find out why they do not parse.


24. SQL - Avoid using UNION
----------------------------------------------------------------------------
UNION can sometimes cause performance issues and should therefore be used with care.
The following code illustrates this rule:

SELECT DUMMY FROM DUAL
UNION                           -- Non-Compliant
SELECT DUMMY FROM DUAL@dblink;

Monday, December 2, 2019

WITH Clause - Subquery Factoring in Oracle

SQL> set lines 100
SQL> set pages 50
SQL> select * from v$version;

BANNER                                                                               CON_ID
-------------------------------------------------------------------------------- ----------
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production              0
PL/SQL Release 12.1.0.2.0 - Production                                                    0
CORE    12.1.0.2.0      Production                                                                0
TNS for Linux: Version 12.1.0.2.0 - Production                                            0
NLSRTL Version 12.1.0.2.0 - Production                                                    0

SQL>

WITH FUNCTION GET_DNAME (I_DEPTNO NUMBER)
        RETURN VARCHAR2
     IS
        V_DNAME   VARCHAR2 (50) := NULL;
     BEGIN
        SELECT DNAME
          INTO V_DNAME
          FROM DEPT
         WHERE DEPTNO = I_DEPTNO;
        RETURN V_DNAME;
     EXCEPTION
     WHEN NO_DATA_FOUND THEN
     RETURN NULL;
     WHEN OTHERS THEN
     RETURN SQLERRM;
     END;
SELECT EMPNO,
       ENAME,
       DEPTNO,
       GET_DNAME (DEPTNO) AS DNAME
  FROM EMP;

Tuesday, November 19, 2019

How to Parse XML using DOM Parser in Oracle

SET DEFINE OFF;
SET SERVEROUTPUT ON;

DECLARE
   v_mds_xml_parser           DBMS_XMLPARSER.parser;
   v_mds_xml_doc              DBMS_XMLDOM.domdocument;
   v_Release_node             xmldom.domnode;
   node_not_exists            EXCEPTION;
   v_ShipToLocationRef_list   xmldom.domnodelist;
   v_ShipToLocationRef_node   xmldom.domnode;
   v_LocationRef_list         xmldom.domnodelist;
   v_LocationRef_node         xmldom.domnode;
   v_Location_list            xmldom.domnodelist;
   v_Location_node            xmldom.domnode;
   v_TransactionCode          VARCHAR2 (1000) := NULL;
   v_LocationGid_list         xmldom.domnodelist;
   v_LocationGid_node         xmldom.domnode;
   v_Gid_list                 xmldom.domnodelist;
   v_Gid_node                 xmldom.domnode;
   v_DomainName               VARCHAR2 (1000) := NULL;
   v_Xid                      VARCHAR2 (1000) := NULL;
   v_LocationName             VARCHAR2 (1000) := NULL;
   v_Address_list             xmldom.domnodelist;
   v_Address_node             xmldom.domnode;
   v_AddressLine1             VARCHAR2 (100) := NULL;
   v_AddressLine2             VARCHAR2 (100) := NULL;
   v_City                     VARCHAR2 (100) := NULL;
   v_Province                 VARCHAR2 (100) := NULL;
   v_PostalCode               VARCHAR2 (100) := NULL;
   v_CountryCode_list         xmldom.domnodelist;
   v_CountryCode_node         xmldom.domnode;
   v_CountryCode              VARCHAR2 (100) := NULL;

   reqxml                     CLOB
      := '<sample:Release xmlns:sample="http://xmlns.oracle.com/apps/sample/transmission/v6.4" xmlns:gtm="http://xmlns.oracle.com/apps/gtm/transmission/v6.4">
    <sample:ReleaseGid>
        <sample:Gid>
            <sample:DomainName>ABC</sample:DomainName>
            <sample:Xid>1234</sample:Xid>
        </sample:Gid>
    </sample:ReleaseGid>
    <sample:TransactionCode>CR</sample:TransactionCode>
    <sample:ShipToLocationRef>
        <sample:LocationRef>
            <sample:Location>
                <sample:TransactionCode>KK</sample:TransactionCode>
                <sample:LocationGid>
                    <sample:Gid>
                        <sample:DomainName>ABC</sample:DomainName>
                        <sample:Xid>87901111</sample:Xid>
                    </sample:Gid>
                </sample:LocationGid>
                <sample:LocationName>MADIWALA</sample:LocationName>
                <sample:Address>
                    <sample:AddressLine1>41, BTM LAYOUT</sample:AddressLine1>
                    <sample:AddressLine2/>
                    <sample:City>BANGALORE</sample:City>
                    <sample:Province/>
                    <sample:PostalCode>560076</sample:PostalCode>
                    <sample:CountryCode>
                        <sample:CountryCode2>KR</sample:CountryCode2>
                    </sample:CountryCode>
                </sample:Address>
                <sample:Contact>
                    <sample:ContactGid>
                        <sample:Gid>
                            <sample:DomainName>ABC</sample:DomainName>
                            <sample:Xid>87901111</sample:Xid>
                        </sample:Gid>
                    </sample:ContactGid>
                    <sample:IsPrimaryContact>Y</sample:IsPrimaryContact>
                </sample:Contact>
                <sample:LocationRole>
                    <sample:LocationRoleGid>
                        <sample:Gid>
                            <sample:DomainName>PUBLIC</sample:DomainName>
                            <sample:Xid>SHIPFROM/SHIPTO</sample:Xid>
                        </sample:Gid>
                    </sample:LocationRoleGid>
                </sample:LocationRole>
            </sample:Location>
        </sample:LocationRef>
    </sample:ShipToLocationRef>
</sample:Release>';

   FUNCTION f_verify_and_gettag_value (i_elem       xmldom.domelement,
                                       i_tagname    VARCHAR2)
      RETURN VARCHAR2
   IS
      pnodelist            xmldom.domnodelist;
      pnode                xmldom.domnode;
      pelement             xmldom.domelement;
      e_xmltag_notexists   EXCEPTION;
   BEGIN
      pnodelist := xmldom.getchildrenbytagname (i_elem, i_tagname);
      pnode := xmldom.item (pnodelist, 0);

      IF (xmldom.isnull (pnode))
      THEN
         RAISE e_xmltag_notexists;
      END IF;

      IF xmldom.haschildnodes (pnode)
      THEN
         IF (xmldom.getnodetype (pnode) = xmldom.element_node)
         THEN
            pnode := xmldom.getfirstchild (pnode);
            RETURN (xmldom.getnodevalue (pnode));
         END IF;
      END IF;

      RETURN NULL;
   EXCEPTION
      WHEN e_xmltag_notexists
      THEN
         RETURN NULL;
   END f_verify_and_gettag_value;

   PROCEDURE p_get_node_value (io_outval   IN OUT VARCHAR2,
                               i_tagnode          xmldom.domnode,
                               i_tagname          VARCHAR2)
   IS
      tagval               VARCHAR2 (30000);
      e_xmltag_notexists   EXCEPTION;
   BEGIN
      BEGIN
         tagval :=
            f_verify_and_gettag_value (xmldom.makeelement (i_tagnode),
                                       i_tagname);
         io_outval := tagval;
      EXCEPTION
         WHEN e_xmltag_notexists
         THEN
            io_outval := NULL;
            -- mr8328 on 12/01/2016
            -- do not set out val if already exists as tag itself not there
            NULL;
      END;
   END p_get_node_value;
BEGIN
   reqxml := REPLACE (reqxml, '&', CHR (ASCII ('&')) || 'amp;'); -- To handle &

   v_mds_xml_parser := DBMS_XMLPARSER.newparser;
   xmlparser.parseclob (v_mds_xml_parser, reqxml);
   v_mds_xml_doc := DBMS_XMLPARSER.getdocument (v_mds_xml_parser);


   /* Checking Parent Node is exists or Not and Raising Exception if not present*/
   v_Release_node :=
      xmldom.item (xmldom.getelementsbytagname (v_mds_xml_doc, 'Release'), 0);

   IF (xmldom.isnull (v_Release_node))
   THEN
      RAISE node_not_exists;
   END IF;

   /*ShipToLocationRef */
   v_ShipToLocationRef_list :=
      xmldom.getchildrenbytagname (xmldom.makeelement (v_Release_node),
                                   'ShipToLocationRef');
   v_ShipToLocationRef_node := xmldom.item (v_ShipToLocationRef_list, 0);

   /*LocationRef */
   v_LocationRef_list :=
      xmldom.getchildrenbytagname (
         xmldom.makeelement (v_ShipToLocationRef_node),
         'LocationRef');
   v_LocationRef_node := xmldom.item (v_LocationRef_list, 0);

   /*Location */
   v_Location_list :=
      xmldom.getchildrenbytagname (xmldom.makeelement (v_LocationRef_node),
                                   'Location');
   v_Location_node := xmldom.item (v_Location_list, 0);


   p_get_node_value (v_TransactionCode, v_Location_node, 'TransactionCode');
   DBMS_OUTPUT.PUT_LINE ('v_TransactionCode=' || v_TransactionCode);

   /*LocationGid */
   v_LocationGid_list :=
      xmldom.getchildrenbytagname (xmldom.makeelement (v_LocationRef_node),
                                   'LocationGid');
   v_LocationGid_node := xmldom.item (v_LocationGid_list, 0);

   /*Gid */
   v_Gid_list :=
      xmldom.getchildrenbytagname (xmldom.makeelement (v_LocationGid_node),
                                   'Gid');
   v_Gid_node := xmldom.item (v_Gid_list, 0);

   p_get_node_value (v_DomainName, v_Gid_node, 'DomainName');
   p_get_node_value (v_Xid, v_Gid_node, 'Xid');
   DBMS_OUTPUT.PUT_LINE ('v_DomainName=' || v_DomainName);
   DBMS_OUTPUT.PUT_LINE ('v_Xid=' || v_Xid);

   p_get_node_value (v_LocationName, v_Location_node, 'TransactionCode');
   DBMS_OUTPUT.PUT_LINE ('v_LocationName=' || v_LocationName);

   /*Address*/
   v_Address_list :=
      xmldom.getchildrenbytagname (xmldom.makeelement (v_Location_node),
                                   'Address');
   v_Address_node := xmldom.item (v_Address_list, 0);
   p_get_node_value (v_AddressLine1, v_Address_node, 'AddressLine1');
   p_get_node_value (v_AddressLine2, v_Address_node, 'AddressLine2');
   p_get_node_value (v_city, v_Address_node, 'City');
   p_get_node_value (v_Province, v_Address_node, 'Province');
   p_get_node_value (v_PostalCode, v_Address_node, 'PostalCode');

   DBMS_OUTPUT.PUT_LINE ('v_AddressLine1=' || v_AddressLine1);
   DBMS_OUTPUT.PUT_LINE ('v_AddressLine2=' || v_AddressLine2);
   DBMS_OUTPUT.PUT_LINE ('v_city=' || v_city);
   DBMS_OUTPUT.PUT_LINE ('v_Province=' || v_Province);
   DBMS_OUTPUT.PUT_LINE ('v_PostalCode=' || v_PostalCode);

   /*CountryCode*/
   v_CountryCode_list :=
      xmldom.getchildrenbytagname (xmldom.makeelement (v_Address_node),
                                   'Address');
   v_CountryCode_node := xmldom.item (v_Address_list, 0);

   p_get_node_value (v_CountryCode, v_CountryCode_node, 'CountryCode');
   DBMS_OUTPUT.PUT_LINE ('v_CountryCode=' || v_CountryCode);
EXCEPTION
   WHEN node_not_exists
   THEN
      DBMS_OUTPUT.put_line ('No node exists with the request XML');
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.put_line (
            'Oracle Error Number:'
         || SQLCODE
         || 'Oracle Error Message:'
         || SQLERRM);
END;
/


v_TransactionCode=NP
v_DomainName=
v_Xid=
v_LocationName=NP
v_AddressLine1=189, GASAN DIGITAL 1-RO
v_AddressLine2=
v_city=GEUMCHEON-GU
v_Province=
v_PostalCode=08503
v_CountryCode=

PL/SQL procedure successfully completed.

SQL>

XML Parsing Example

SET DEFINE OFF;
SET SERVEROUT ON;

DECLARE
   v_mds_xml_parser        DBMS_XMLPARSER.parser;
   v_mds_xml_doc           DBMS_XMLDOM.domdocument;
   v_inq_entrp_ordr_node   xmldom.domnode;
   v_OrderList             xmldom.domnodelist;
   v_orderlist_node        xmldom.domnode;
   v_activityType_list     xmldom.domnodelist;
   v_actvity_node          xmldom.domnode;
   text_node               xmldom.domnode;
   v_activityType          VARCHAR2 (200) := NULL;
   i_reqxml                CLOB
      := '<?xml version="1.0" encoding="UTF-8"?>
<!--Sample XML file generated by XMLSpy v2013 rel. 2 sp2 (x64) (http://www.altova.com)-->
<InquirePendingEnterpriseOrderResponse xsi:schemaLocation="http://csi.cingular.com/CSI/Namespaces/Container/Public/InquirePendingEnterpriseOrderResponse.xsd InquirePendingEnterpriseOrderResponse.xsd" xmlns="http://csi.cingular.com/CSI/Namespaces/Container/Public/InquirePendingEnterpriseOrderResponse.xsd" xmlns:cdm="http://csi.att.com/CSI/Namespaces/GlobalIntegratedOrderManager/Types/Public/CommonDataModel.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <OrderList>
        <orderNumber>GIOM234</orderNumber>
        <orderType>MACDs</orderType>
        <activityType>GIOM234_1</activityType>
        <activityType>GIOM234_2</activityType>
    </OrderList>
    <OrderList>
        <orderNumber>GIOM789</orderNumber>
        <orderType>New Start</orderType>
        <activityType>GIOM789_1</activityType>
        <activityType>GIOM789_2</activityType>
    </OrderList>
    <Response>
        <cdm:code>String</cdm:code>
        <cdm:description>String</cdm:description>
    </Response>
</InquirePendingEnterpriseOrderResponse>
';

   V_actType_list          VARCHAR2 (1000) := NULL;
BEGIN
   v_mds_xml_parser := DBMS_XMLPARSER.newparser;
   xmlparser.parseclob (v_mds_xml_parser, i_reqxml);
   v_mds_xml_doc := DBMS_XMLPARSER.getdocument (v_mds_xml_parser);
   /* Application Details */
   v_inq_entrp_ordr_node :=
      xmldom.item (
         xmldom.getelementsbytagname (
            v_mds_xml_doc,
            'InquirePendingEnterpriseOrderResponse'),
         0);
   /*AccountOrganizationIdentifierContent */
   v_OrderList :=
      xmldom.getchildrenbytagname (
         xmldom.makeelement (v_inq_entrp_ordr_node),
         'OrderList');

   FOR l_index IN 0 .. (xmldom.getlength (v_OrderList)) - 1
   LOOP
      v_orderlist_node := xmldom.item (v_OrderList, l_index);
      v_activityType_list :=
         xmldom.getchildrenbytagname (xmldom.makeelement (v_orderlist_node),
                                      'activityType');
      DBMS_OUTPUT.put_line ('OrderList=' || l_index);

      FOR l_index IN 0 .. (xmldom.getlength (v_activityType_list)) - 1
      LOOP
         v_actvity_node := xmldom.item (v_activityType_list, l_index);
         text_node := DBMS_XMLDOM.getfirstchild (v_actvity_node);
         v_activityType := DBMS_XMLDOM.getnodevalue (text_node);
         V_actType_list := V_actType_list || '''' || v_activityType || ''',';
         DBMS_OUTPUT.put_line ('v_activityType=' || v_activityType);
      END LOOP;
   END LOOP;
END;
/

OrderList=0
v_activityType=GIOM234_1
v_activityType=GIOM234_2
OrderList=1
v_activityType=GIOM789_1
v_activityType=GIOM789_2

PL/SQL procedure successfully completed.

SQL>

Consuming SOAP Web Services using Oracle UTL_HTTP

SET DEFINE OFF;
SET SERVEROUTPUT ON;

DECLARE
   /* $Header: $ */
   -- ------------------------------------------------------------------------------------------------
   -- $URL: $
   -- $LastChangedRevision: $
   -- $LastChangedDate: $
   -- $LastChangedBy: $
   -- $Id: $
   -- ------------------------------------------------------------------------------------------------
   -- Date        Name           Comment
   -- ----------- -------------- ---------------------------------------------------------------------
   -- 03-Aug-2018 Rajasekhar M   - To test SOAP WebService connection
   ---------------------------------------------------------------------------------------------------


   i_endpoint_url   VARCHAR2 (100)   := 'https://wsctt.pearsonvue.com/cxfws2/services/Ping?wsdl';
 
   --i_endpoint_url   VARCHAR2 (100):= 'https://wsctt.pearsonvue.com/cxfws2/services/Ping';

   i_req_xml        XMLTYPE
      := xmltype (
            '<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:sch="http://ws.pearsonvue.com/ping/schema">
    <soap:Header/>
<soap:Body>
       <sch:pingServiceRequest/>
    </soap:Body>
 </soap:Envelope>');


   o_status_code    NUMBER := NULL;
   o_status_desc    VARCHAR2 (500) := NULL;
   o_resp_xml       CLOB := NULL;

   PROCEDURE p_print (pnt_msg VARCHAR2)
   AS
   BEGIN
      IF 1 = 1
      THEN
         DBMS_OUTPUT.put_line (SYSTIMESTAMP || ': ' || pnt_msg);
         RETURN;
      END IF;
   END p_print;

   FUNCTION cloblengthb (p_clob IN CLOB)
      RETURN NUMBER
   AS
      v_temp_blob     BLOB;
      v_dest_offset   NUMBER := 1;
      v_src_offset    NUMBER := 1;
      v_amount        INTEGER := DBMS_LOB.lobmaxsize;
      v_blob_csid     NUMBER := DBMS_LOB.default_csid;
      v_lang_ctx      INTEGER := DBMS_LOB.default_lang_ctx;
      v_warning       INTEGER;
      v_total_size    NUMBER := 0;        -- Return total clob length in bytes
   BEGIN
      IF p_clob IS NOT NULL
      THEN
         DBMS_LOB.CREATETEMPORARY (lob_loc => v_temp_blob, cache => TRUE);
         DBMS_LOB.CONVERTTOBLOB (v_temp_blob,
                                 p_clob,
                                 v_amount,
                                 v_dest_offset,
                                 v_src_offset,
                                 v_blob_csid,
                                 v_lang_ctx,
                                 v_warning);
         v_total_size := DBMS_LOB.GETLENGTH (v_temp_blob);
         DBMS_LOB.FREETEMPORARY (v_temp_blob);
      ELSE
         v_total_size := NULL;
      END IF;

      RETURN v_total_size;
   END cloblengthb;

   PROCEDURE p_invoke_wsdl_over_https (i_endpoint_url   IN     VARCHAR2,
                                       i_req_xml        IN     CLOB,
                                       o_status_code       OUT NUMBER,
                                       o_status_desc       OUT VARCHAR2,
                                       o_resp_xml          OUT CLOB)
   AS
      v_wsdl_url             VARCHAR2 (1000) := NULL;
      v_soap_request         CLOB;
      v_soap_response        CLOB;
      l_http_request         UTL_HTTP.req;
      l_http_response        UTL_HTTP.resp;
      v_response_buffer      VARCHAR2 (32767) := NULL;
      v_status_code          NUMBER := 0;     -- Default value is 0 - Success;
      v_status_desc          VARCHAR2 (500) := 'Success'; -- Default value is Success';
      v_process_start_time   NUMBER;
      v_process_end_time     NUMBER;
      v_process_time_taken   NUMBER;
      v_host                 VARCHAR2 (100) := NULL;
      g_env                  VARCHAR2 (100)
         := UPPER (SYS_CONTEXT ('USERENV', 'DB_NAME', 15));
   BEGIN
      v_process_start_time := DBMS_UTILITY.GET_TIME;
      p_print ('Starting invoking webservice transaction process.');
      v_wsdl_url := i_endpoint_url;
      v_soap_request := i_req_xml;
      p_print ('v_wsdl_url:' || v_wsdl_url);

      /*Setting set_response_error_check to true will  raise an exception when the status code indicates an error.a status code in the 4xx or 5xx ranges Response error check is turned off by default*/
      UTL_HTTP.set_response_error_check (enable => TRUE);
      -- Sets the UTL_HTTP package to raise a detailed exception
      UTL_HTTP.set_detailed_excp_support (enable => TRUE);
      -- sets the proxy to be used for requests of the HTTP or other protocols
      UTL_HTTP.set_proxy (proxy => 'http://www-proxy-adcq7.us.oracle.com:80');
      -- sets the Oracle wallet used for all HTTP requests over Secured Socket Layer (SSL), namely HTTPS
      UTL_HTTP.SET_WALLET ('file:/u01/app/oracle/dba/rdbms/ouappprd/wsctt_102019', 'ou96ffd3482652ab94f2a45c6b61ef1cgbs');
      -- From Oracle 11gR2 onward, if you are using the -auto_login option on the wallet, you don't have to specify the wallet password. You just pass NULL instead of the password.
      p_print ('Wallet has been set correctly......');
      -- sets the default time out value (60) for all future HTTP requests
      UTL_HTTP.set_transfer_timeout (60);

      -- HTTP_VERSION_1_0 Denotes HTTP version 1.0 (HTTP/1.0)
      -- HTTP_VERSION_1 Denotes HTTP version 1.1 (HTTP/1.1)
      --  Begins a new HTTP request.UTL_HTTP establishes the network connection to the target Web server or the proxy server and sends the HTTP request line.

      l_http_request :=
         UTL_HTTP.begin_request (url            => v_wsdl_url,
                                 method         => 'POST',          --GET/POST
                                 http_version   => 'HTTP/1.2');

      p_print ('Connection has opened successfully......');
      UTL_HTTP.set_body_charset (l_http_request, 'UTF-8');
      -- Sets an HTTP request header. The request header is sent to the Web server as soon as it is set.
      UTL_HTTP.set_header (l_http_request,
                           'User-Agent',
                           'Mozilla/4.0 (compatible)');
      UTL_HTTP.set_header (l_http_request, 'Connection', 'Keep-Alive'); -- Keep-Alive/close
      -- SOAP 1.1
      /*UTL_HTTP.set_header (l_http_request,
                           'Content-Type',
                           'text/xml; charset=utf-8');*/
      -- SOAP 1.2
      UTL_HTTP.set_header (l_http_request,
                           'Content-Type',
                           'application/soap+xml; charset=utf-8');

      UTL_HTTP.set_header (l_http_request,
                           'content-length',
                           cloblengthb (v_soap_request));
      -- Sets HTTP authentication information in the HTTP request header. The Web server needs this information to authorize the request.
      --UTL_HTTP.set_authentication (req, v_organisation_token, '.');
      -- Writing soap request text data in the HTTP body.
      UTL_HTTP.write_text (l_http_request, v_soap_request);
      p_print ('v_soap_request: ' || v_soap_request);

      l_http_response := UTL_HTTP.get_response (l_http_request);
      p_print (
         'Response> status_code: "' || l_http_response.status_code || '"');
      p_print (
         'Response> reason_phrase: "' || l_http_response.reason_phrase || '"');
      p_print (
         'Response> http_version: "' || l_http_response.http_version || '"');

      DBMS_LOB.createtemporary (v_soap_response, TRUE);

      BEGIN
         LOOP
            p_print ('Read data.................');
            --  reads the HTTP response body in text form and returns the output in the caller-supplied buffer
            UTL_HTTP.read_text (l_http_response, v_response_buffer, 32767);
            p_print ('v_response_buffer ' || v_response_buffer);
            DBMS_LOB.writeappend (v_soap_response,
                                  -- LENGTHB (v_response_buffer),
                                  LENGTH (v_response_buffer),
                                  v_response_buffer);
         END LOOP;
      EXCEPTION
         -- The end_of_body exception will be raised if the end of the HTTP response body is reached
         WHEN UTL_HTTP.end_of_body
         THEN
            p_print ('end_of_body error -->' || SQLCODE || ':' || SQLERRM);
            -- ends the HTTP response. It completes the HTTP request and response
            UTL_HTTP.end_response (l_http_response);
         WHEN OTHERS
         THEN
            p_print (
               'Response process error -->' || SQLCODE || ':' || SQLERRM);
      END;

      p_print ('v_soap_response ' || v_soap_response);
      o_resp_xml := v_soap_response;
      o_status_code := v_status_code;
      o_status_desc := v_status_desc;
      v_process_end_time := DBMS_UTILITY.GET_TIME;
      v_process_time_taken :=
           MOD (
              ( (v_process_end_time - v_process_start_time) + POWER (2, 32)),
              POWER (2, 32))
         / 100;
      p_print (
            'invoking webservice transaction process took '
         || v_process_time_taken
         || ' Seconds');
      p_print ('Ending invoking webservice transaction process.');
   EXCEPTION
      WHEN UTL_HTTP.end_of_body
      THEN
         UTL_HTTP.end_response (l_http_response);
      WHEN UTL_HTTP.too_many_requests
      THEN
         UTL_HTTP.end_response (l_http_response);
         v_status_code := 1;
         v_status_desc := ('Failed, ' || 'Oracle exception - ' || SQLERRM);
         o_status_code := v_status_code;
         o_status_desc := v_status_desc;
      WHEN OTHERS
      THEN
         v_status_code := 1;
         v_status_desc := ('Failed, ' || 'Oracle exception - ' || SQLERRM);
         o_status_code := v_status_code;
         o_status_desc := v_status_desc;
         p_print ('Oracle Error code -->' || SQLCODE);
         p_print ('Oracle Error Message -->' || SQLERRM);
   END p_invoke_wsdl_over_https;
BEGIN
   p_invoke_wsdl_over_https (i_endpoint_url,
                             i_req_xml.getclobval (),
                             o_status_code,
                             o_status_desc,
                             o_resp_xml);
   DBMS_OUTPUT.put_line ('o_status_code=' || o_status_code);
   DBMS_OUTPUT.put_line ('o_status_desc=' || o_status_desc);
   DBMS_OUTPUT.put_line ('o_resp_xml=' || o_resp_xml);
END;
/


Response:

19-NOV-19 03.29.34.666236000 AM -07:00: Starting invoking webservice transaction process.
19-NOV-19 03.29.34.666360000 AM -07:00:
v_wsdl_url:https://wsctt.pearsonvue.com/cxfws2/services/Ping?wsdl
19-NOV-19 03.29.34.666467000 AM -07:00: Wallet has been set correctly......
19-NOV-19 03.29.34.973263000 AM -07:00: Connection has opened successfully......
19-NOV-19 03.29.34.974082000 AM -07:00: v_soap_request: <soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:sch="http://ws.pearsonvue.com/ping/schema">
    <soap:Header/>
    <soap:Body>

<sch:pingServiceRequest/>
    </soap:Body>
 </soap:Envelope>
19-NOV-19 03.29.35.281206000 AM -07:00: Response> status_code: "200"
19-NOV-19 03.29.35.281250000 AM -07:00: Response> reason_phrase: "200"
19-NOV-19 03.29.35.281264000 AM -07:00: Response> http_version: "HTTP/1.1"
19-NOV-19 03.29.35.281304000 AM -07:00: Read data.................
19-NOV-19 03.29.35.281359000 AM -07:00: v_response_buffer <soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ping:pingResponse
xmlns:ping="http://ws.pearsonvue.com/ping/schema">
    <result
status="success"/>
</ping:pingResponse></soap:Body></soap:Envelope>
19-NOV-19 03.29.35.281543000 AM -07:00: Read data.................
19-NOV-19 03.29.35.281666000 AM -07:00: end_of_body error -->-29266:ORA-29266: end-of-body reached
19-NOV-19 03.29.35.282175000 AM -07:00: v_soap_response <soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ping:pingResponse
xmlns:ping="http://ws.pearsonvue.com/ping/schema">
    <result
status="success"/>
</ping:pingResponse></soap:Body></soap:Envelope>
19-NOV-19 03.29.35.282235000 AM -07:00: invoking webservice transaction process took .62 Seconds
19-NOV-19 03.29.35.282250000 AM -07:00: Ending invoking webservice transaction process.
o_status_code=0
o_status_desc=Success
o_resp_xml=<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ping:pingResponse
xmlns:ping="http://ws.pearsonvue.com/ping/schema">
    <result
status="success"/>
</ping:pingResponse></soap:Body></soap:Envelope>

PL/SQL procedure successfully completed.

SQL>

Delete Row Button to all records of Interactive Report in Oracle Apex

 1. add 'Delete' Del column to Report Query 2. Set the Following Properties for the DEL Column Type: Link Heading: Delete Targ...