1

I'm using SQL Developer/Oracle and I need to check in a trigger if the the value inserted on a specific field is an integer or just a "string".

I tried isnumeric(), but this function doesn't exist in Oracle. What's the equivalent in Oracle since I can't find it anywhere?

Sam
  • 7,252
  • 16
  • 46
  • 65
  • http://stackoverflow.com/questions/5666986/how-can-i-determine-if-a-string-is-numeric-in-sql – dnapierata Nov 16 '13 at 16:12
  • Are you asking how to tell if the column is numeric or varchar datatype or whether the contents of a varchar column can be converted to a number? – eaolson Nov 16 '13 at 16:25
  • I'm using an if. This means if the value inserted is varhchar I will raise an application error, otherwise I will do nothing. –  Nov 16 '13 at 16:26

2 Answers2

3

From your last comment to the @Ben's answer

'1234' should be considered as a string and fail

it seems like you want to do a data type checking of a literal upon insertion and allow to insert only literals of numeric data types. Oracle does an implicit data type conversion when it makes sense. For example, you have a column of number data type in your table. When you try to insert a character literal '123' to that column, the operation will succeed despite the fact that the literal is of character data type(char, simple character literals are of CHAR data type not varchar2 by default), because Oracle takes a look at the data type of a column, then at data type and elements of the character literal and decides 'Yes, it makes sense to convert that character literal to a number.' and does it. As @Ben said , it probably would be better to let your application do the checking whether a value you are trying to insert into a table is of number or character data type.

Having said that, the probably simplest method to do a data type checking and allow to insert only literals or variables of numeric data types would be creating a package with one overloading function, say isnumber(). First version of the function has a formal parameter of varchar2 data type and its overloaded version has formal parameter of number data type. Depending on a data type of actual parameter Oracle will choose appropriate version of the function:

SQL> create or replace package Util1 as
  2    function isnumber(p_val in varchar2)
  3      return varchar2;
  4    function isnumber(p_val in number)
  5      return number;
  6  end;
  7  /
Package created

SQL> create or replace package body Util1 as
  2    function isnumber(p_val in varchar2)
  3      return varchar2 is
  4    begin
  5      raise_application_error(-20000, 'Not a numeric data type');
  6    end;
  7  
  8    function isnumber(p_val in number)
  9       return number is
 10    begin
 11      return p_val;
 12    end;
 13  end;
 14  /
Package body created

When you call util1.isnumber() function with actual parameter of numeric data type it simply returns it back, and when the function is called with an actual parameter of a character data type exception will be raised.

SQL> create table t1(col number);
Table created

SQL> insert into t1(col) values(util1.isnumber(123));
1 row inserted

SQL> commit;
Commit complete

SQL> insert into t1(col) values(util1.isnumber('123'));

ORA-20000: Not a numeric data type
ORA-06512: at "HR.UTIL1", line 5

SQL> insert into t1(col) values(util1.isnumber('12345f'));

ORA-20000: Not a numeric data type
ORA-06512: at "HR.UTIL1", line 5

Note This approach wont work in a trigger because of implicit data type conversion. In trigger you would have to do the following:

 :new.col_name := util1.isnumber(:new.col_name)

As col_name is of number data type, Oracle will always call version of isnumber() function with formal parameter of number data type and insert will succeed even if actual value being inserted is (say) '123'.

Community
  • 1
  • 1
Nick Krasnov
  • 26,886
  • 6
  • 61
  • 78
0

I'm using an if. This means if the value inserted is varhchar I will raise an application error, otherwise I will do nothing.

When you insert a character into a numeric field you'll get an "invalid number" exception raised (ORA-01722). This makes your choice easier; don't test to see if the string you're inserting is a character. Capture the raised exception when a user inserts a character into a numeric field and re-raise as an application error (if you really feel you have to).

There's then no need to test at all.

For example:

create table test ( a number );

begin
   insert into test values ('a');
exception when INVALID_NUMBER then
   raise_application_error(-20000, 'The number wasn''t a number');
end;
/

It's worth noting that you could also test if something's a number in your application code (if it's an application). You wouldn't have to do the round trip to the database then.

Ben
  • 51,770
  • 36
  • 127
  • 149
  • I really need to re_raise since this is for a college project and my teacher will do everything that is in his power in order to crash my code. So if i have custom exceptions I can show him I considered every possibility, you see? –  Nov 16 '13 at 16:41
  • That's a "business decision" @André; personally I'm not usually in favour of obscuring the error in the database. It's better if the application catches the exception and decides what to do with it because a layer of obfuscation is removed. – Ben Nov 16 '13 at 16:46
  • There is a small catch here - implicit data type conversion. OP needs to define integer and string. Yes, if a column is of (say) number data type and you are inserting a non numeric character then yes, error `ORA-01722` will be raised. But, when the column is of number data type and you are trying to insert `'1233'` (still a character literal, not a number) implicit data type conversion will take place. – Nick Krasnov Nov 16 '13 at 16:57
  • Is there a situation where Oracle _won't_ implicitly convert @Nicholas? If it's a valid number then, as far as I know, [it always will](http://www.sqlfiddle.com/#!4/d41d8/20808). – Ben Nov 16 '13 at 17:05
  • Right. But I was talking about how OP defines integer and string. Is '123' a string or a number(it's not a pure number now, but it will be after it implicitly converted), and should `insert` succeed in this situation or fail? Yes, 'a' not a numeric value and insert should fail. `123` is obviously a number, and `insert` should succeed. Now, how OP will define '1234'? Should it be treated as a number and succeed or should it be treated as a string and fail? – Nick Krasnov Nov 16 '13 at 19:42
  • '1234' should be considered as a string and fail. –  Nov 16 '13 at 21:20