2021- Parameter Data Type Checks

This post a quick eplanation of how Oracle validates datatype when compiling and executing code.

Parameter Datatypes

Parameter datatype are very important because they dictates the behavior of the PL/SQL compiler. For example the get_pname function has 2 parameters:

  • p_os – the number of the operating system – the datatype is number so it will not accept anything else.
  • p_mrn – the patients mrn – the datatype varchar2 so it will accepts strings and/or numbers
FUNCTION get_pname ( p_os NUMBER,
                      p_mrn VARCHAR2 )
         RETURN VARCHAR2 IS
  v_ret_val VARCHAR2(30);
BEGIN
  SELECT ( SELECT patient_name
             FROM patient
            WHERE patient_id = pmrn.patient_id )
    INTO v_ret_val
    FROM patient_mrn pmrn
   WHERE ordering_system = p_os
     AND patient_mrn = p_mrn;
  RETURN(v_ret_val);
EXCEPTION
  WHEN OTHERS THEN
    RETURN(NULL);
END;

And here are some example calls specifying the correct types of data.

-- First call finds Patient 1
-- Second call finds nothing and returns NULL
BEGIN
  DBMS_OUTPUT.PUT_LINE(patient_pkg.get_pname(1,'MRN123'));
  DBMS_OUTPUT.PUT_LINE(patient_pkg.get_pname(1,'NOTTHERE'));
END;
Patient 1

What if we try passing incorrect datatypes such as a date? The PL/SQL compile recognizes that the NOTANUMBER text cannot be converted to a number so raise the error.

-- raises ORA-06502: PL/SQL: numeric or value error: character to
-- number conversion error
BEGIN
  DBMS_OUTPUT.PUT_LINE(patient_pkg.get_pname('NOTANUMBER','MRN123'));
END;

One way to ensure the parameter is the correct datatype is using the VALIDATE_CONVERSION function. It returns 1 if the defined conversion is possible. The first call below cannot translate NOTANUMBER to a NUMBER so it display an incorrect datatype message. The second call converts 1 to a number and then calls the get_pname function.

BEGIN
  IF VALIDATE_CONVERSION('NOTANUMBER' AS NUMBER) = 1 THEN
    DBMS_OUTPUT.PUT_LINE(patient_pkg.get_pname('NOTANUMBER','MRN123'));
  ELSE
    DBMS_OUTPUT.PUT_LINE('Please pass correct datatypes');
  END IF;
  IF VALIDATE_CONVERSION(1 AS NUMBER) = 1 THEN
    DBMS_OUTPUT.PUT_LINE(patient_pkg.get_pname(1,'MRN123'));
  ELSE
    DBMS_OUTPUT.PUT_LINE('Please pass correct datatypes');
  END IF;
END;
Please pass correct datatypes
Patient 1

The compiler is pretty good with DATE parameters as well. For example it notices the SYSDATE function returns a DATE value in thus call and raises┬áPLS-00306: wrong number or types of arguments in call to ‘GET_PNAME’

BEGIN
  DBMS_OUTPUT.PUT_LINE(patient_pkg.get_pname(SYSDATE,SYSDATE));
END;

It even notices local variables. This call fails.

DECLARE
  v_date DATE;
BEGIN
  DBMS_OUTPUT.PUT_LINE(patient_pkg.get_pname(v_date,v_date));
END;

It wont even allows a procedure to be created if the parameters types mismatch.

This raises – PLS-00306: wrong number or types of arguments in call to ‘GET_PNAME’

CREATE OR REPLACE PROCEDURE x AS
  v_date DATE;
BEGIN
  DBMS_OUTPUT.PUT_LINE(patient_pkg.get_pname(v_date,v_date));
END;

It’s very thorough. Even traps code that will never exist!

CREATE OR REPLACE PROCEDURE x AS
  v_date DATE;
BEGIN
  IF 1 = 2 THEN
    DBMS_OUTPUT.PUT_LINE(patient_pkg.get_pname(v_date,v_date));
  END IF;
END;

Thanks for reading!

Leave a Comment