I am trying to do a comparison based on a column. Let's say, if column>5.
select * where column>5
The column contains non digits. I thought Oracle allows one to compare strings (like Java).
Apparently this is not allowed.
ORA-01722: invalid number
01722. 00000 - "invalid number"
Is there a way to do comparisons with non numeric fields?
Thanks
Yes, you have to put the 5 in quotes :
select * from table where column > '5'
To shed a bit more light on why it doesn't work.
When using a number literal 5 instead of a character literal '5' Oracle does an implicit data type conversion and tries to convert all values in your table to a number. That's why you get that error.
You should never rely on implicit data type conversion. That is bound to give you trouble sometime.
Now if you correctly compare a character literal ('5') against a character column, no data type conversion is needed and no error occurs.
However: if you expect Oracle to actually do a numeric comparison then you are mistaken. Character string are based on ASCII values. Therefor the (character) value '10' is lower than the (character) value '2' because the first character '1' is ranked lower than '2'.
If the column is varchar2, then this:
select * from some_table where some_column > 5
... does an implicit conversion of all the column values to numbers, so you're really doing:
select * from some_table where to_number(some_column) > 5
It's the to_number() that's causing the ORA-01722, even though you can't see it, when it hits a value that is not numeric. The function being called on the column value also stops any index being used (oversimplifying a bit).
You can stop it failing, and let it use the index if there is one, by doing where some_column > '5' as other have said, or where some_column > to_char(5). But you need to be careful doing the comparison as it will still be a string comparison, not a numeric one; so '10' will not be seen as > '5'; and your NLS sorting parameters might produce results you aren't expecting. Or more importantly, someone else's NLS parameters - when you put this live for example - might product results you aren't expecting and which don't match the ones you got in your environment. See the documentation for more.
You should use number columns to hold numeric values, date columns to hold dates, etc., and varchar2 only to hold text values.
you can use to_char function
select * from table where column > to_char(5)
You are missing the table:
select * where FROM tablename column>5
But this only works if column is a number. If not, you can't use >.
To compare strings, you can use LIKE or STRCMP(), check examples of them HERE.
As stated by #Gerrat, you can also use > and < but the types of both sides must be compatible (number with number or text with text). To find more about it, check THIS.
Be aware that in text comparison it will compare each character individually so '11' will be < that '2'.
Related
I have a column that is in INT type. I want to remove all the trailing zeroes and only have the number. The example below, should follow be: 3,10,20,20. I cannot have the 4 zeroes at the end.
Is there a way to do this?
You could try casting your numeric data to integer, e.g.
SELECT AS_INTEGER(col) AS col
FROM yourTable;
the 3dp is how floating point numbers print, thus you can cast to number SELECT column_name::number FROM table
If your data is a string/varient type, and not all values stored in your column always casts cleanly, in Snowflake you can hit error, with the TO_NUMBER or ::number forms, thus [TRY_TO_NUMBER][2] form should be used.
Here's what i'm having trouble with. I have a table where i have the column weight, the data in this column is varchar2, example: 60 kg.
When i try to make a WHERE condition asking to retrieve everything below 60 kg, it doesn't give me the wanted results.
I tried to convert using to_number but it's not working and giving me error "Invalid Number". I also tried to cut the kg with SUBSTR and convert, and doesn't work as well.
Any suggestions?
Thanks in advance.
You can extract leading digits and convert that to a number:
select to_number(regexp_substr(weight, '^[0-9]*'))
from t;
The regular expression is starting from the beginning of the string (the ^) and extracting digits. The * is for any number of digits. Regular expression match is "greedy" by default, meaning that it will keep matching as many digits in a row as there are.
If you have decimal places or negative values, this might be a tad bit more complicated.
I recently noticed the following issue with Hive but could not find a corresponding HIVE ticket, so would like to cross-check this.
I have a string type column which is actually a timestamp of the format yyyy-MM-dd HH:mm:ss.SSS. I am casting this column to a timestamp type as follows:
select my_str_col, cast(my_str_col as timestamp) as my_timestamp_col from my_table;
The results of the above query looks like this:
You can see that in the casted version, the last digits are ignored if any of them were 0. Why is this happening?
This is just a representation problem.
In a timestamp, just like in a number, a last decimal digit of value 0 is not meaningful; basically:
1.230 = 1.23
On the other hand, string-wise, every character matters, as well as the length of the string:
'1.230' <> '1.23'
Your datatype conversion works fine. Strings are turned to the relevant timestamp values. It is just the representation of the two datatypes that makes it look like they are different.
What is the Oracle equivalent of NVL for number datatypes?
This works since the datatype is VARCHAR:
select nvl(enrol.OUAC_APPLNO, 'blank') Invalid_OUAC_APPLNO
But this doesn't work since the datatype is NUMBER:
select nvl(enrol.ouac_type_id, 'blank') REGTYP
There is no equivalent and no Oracle functions will accept this (apart from DECODE() but don't do that); you're going to have to convert your number to a character:
select nvl(cast(enrol.OUAC_APPLNO as varchar2(10)), 'blank')
You may need to change the number of characters you're converting to as appropriate.
However, I don't know why you're doing this at all. By definition a NULL implies non-existence. If you want to display blank in order to confer non-existence this is something that you should be doing with your presentation layer rather than the database.
it wont work because oracle wants every row should be in the same type otherwise you cannot run functions on that column, you have cast ouac_type_id to be varchar as below;
select nvl(cast(enrol.OUAC_APPLNO as varchar2(10)), 'blank') REGTYP
select nvl(TO_CHAR(enrol.OUAC_APPLNO), 'blank') REGTYP
In an sql where condition there is a value like below
select * from tabl
where
code not between 'A00' and 'B99'
how does this work? till now i was thinking it works only with numeric and date
The same way as ORDER BY works on varchar values.
Every char has its ASCII code and sort order, so every value can be compared by its ASCII code.
The BETWEEN operator will treat these as varchars, and apply its comparison rules accordingly:
BETWEEN returns TRUE if the value of test_expression is greater than or equal to the value of begin_expression and less than or equal to the value of end_expression.
SQL uses a list of the ASCII codes to determine which to sort where
and in what order.