Skip to content

G-9020: Try to use a format model and NLS_NUMERIC_CHARACTERS in string to number conversion functions.

Blocker

Changeability, Maintainability, Reliability, Security, Testability

Reason

Converting from strings to numeric datatypes (using to_number, to_binary_double, to_binary_float or cast to any of those datatypes) rely on session NLS settings for nls_numeric_characters. Typically the input string is expected to have a given decimal- and group-separator, so it is best practice to specify nls_numeric_characters in the function call. However, this requires also setting a format model, which is a good idea but can require a very large format model with many 9's if you do not know the maximum length of the string.

To avoid an inappropriate dependability on configurable NLS parameters, try to use both format model and nls_numeric_characters in the conversion function call. The exceptions can be if the input is known to always be integer with no decimal- or group-separator, or if you do not know the maximum number of digits and have control over the session nls_numeric_characters parameter.

Example (bad)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
create or replace package body employee_api is
   procedure set_salary(
      in_employee_id in employees.employee_id%type
     ,in_salary      in varchar2
   ) is
      co_employee_id constant eployees.employee_id%type := in_employee_id;
      co_salary      constant type_up.date_string       := in_salary;
   begin
      update employees
         set salary = to_number(co_salary default null on conversion error)
       where employee_id = co_employee_id;
   end set_dob;
end employee_api;
/

Example (good)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
create or replace package body employee_api is
   procedure set_salary(
      in_employee_id in employees.employee_id%type
     ,in_salary      in varchar2
   ) is
      co_employee_id constant eployees.employee_id%type := in_employee_id;
      co_salary      constant type_up.string            := in_salary;
   begin
      update employees
         set salary = to_number(
                co_salary default null on conversion error
               ,'99999999999999999999.99999'
               ,q'[nls_numeric_characters='.,']'
             )
       where employee_id = co_employee_id;
   end set_dob;
end employee_api;