Home > Enterprise >  Cannot convert a varchar value of 100 into number under a grade column in Oracle SQL
Cannot convert a varchar value of 100 into number under a grade column in Oracle SQL

Time:02-18

I have a column entitled "Grade" and defined as VARCHAR2(3); however when I have a grade value of '100' the system under Oracle SQL cannot read this value as integer and I am not able to set up the below case condition:

WHEN CAST(GRADE as varchar(3)) between '93' and '100' then 4.3 

Update:

I am getting a 0 score for the 100 value instead of 4.3

Select CRSE_NUMB,
       Grade,
       CASE 
       WHEN CAST(GRADE as varchar(3)) between '93' and '100' then 4.3 
       WHEN Grade < '60' then 0.0
       WHEN Grade = '60' then 1.0
       WHEN Grade between '61' and '62' then 1.3
       WHEN Grade between '79' and '82' then 3.3
       WHEN Grade between '83' and '86' then 3.7
       WHEN Grade between '87' and '92' then 4.0
       WHEN TO_NUMBER(Grade DEFAULT NULL ON CONVERSION error) between '93' and '100' then 4.3 
       else null
       end as Score
from   SWBGRDE
group by CRSE_NUMB, Grade

CodePudding user response:

Use TO_NUMBER():

WHEN TO_NUMBER(grade) BETWEEN 93 AND 100 THEN 4.3

If you have non-numeric data in your grade column, and are on Oracle 12 or later, you can use:

WHEN TO_NUMBER(grade DEFAULT NULL ON CONVERSION ERROR) BETWEEN 93 AND 100 THEN 4.3

If you compare using strings then the comparison is done on substrings of successively increasing lengths so it will compare if the first character of GRADE is between a minimum of '9' and a maximum of '1' which will never be true.


For example, from Oracle 12 you can use:

SELECT grade,
       CASE
       WHEN TO_NUMBER(grade DEFAULT NULL ON CONVERSION ERROR) < 93 THEN 1
       WHEN TO_NUMBER(grade DEFAULT NULL ON CONVERSION ERROR) BETWEEN 93 AND 100 THEN 4.3
       END AS score
FROM   table_name

Or, in earlier versions, you can look for a non-numeric character:

SELECT grade,
       CASE
       WHEN REGEXP_LIKE(grade, '\D') THEN NULL
       WHEN TO_NUMBER(grade) < 93 THEN 1
       WHEN TO_NUMBER(grade) BETWEEN 93 AND 100 THEN 4.3
       END AS score
FROM   table_name

Then, for the sample data:

CREATE TABLE table_name (grade VARCHAR2(3));

INSERT INTO table_name (grade)
SELECT TO_CHAR(90   LEVEL) FROM DUAL CONNECT BY LEVEL <= 10 UNION ALL
SELECT 'AAA' FROM DUAL;

Outputs:

GRADE SCORE
91 1
92 1
93 4.3
94 4.3
95 4.3
96 4.3
97 4.3
98 4.3
99 4.3
100 4.3
AAA null

db<>fiddle here


Regarding your update:

Do not compare numbers as strings - compare them as numbers and use TO_NUMBER everywhere:

Select CRSE_NUMB,
       Grade,
       CASE 
       WHEN TO_NUMBER(Grade DEFAULT NULL ON CONVERSION ERROR) < 60 then 0.0
       WHEN TO_NUMBER(Grade DEFAULT NULL ON CONVERSION ERROR) = 60 then 1.0
       WHEN TO_NUMBER(Grade DEFAULT NULL ON CONVERSION ERROR) <= 62 then 1.3
       WHEN TO_NUMBER(Grade DEFAULT NULL ON CONVERSION ERROR) <= 82 then 3.3
       WHEN TO_NUMBER(Grade DEFAULT NULL ON CONVERSION ERROR) <= 86 then 3.7
       WHEN TO_NUMBER(Grade DEFAULT NULL ON CONVERSION ERROR) <= 92 then 4.0
       WHEN TO_NUMBER(Grade DEFAULT NULL ON CONVERSION ERROR) <= 100 then 4.3 
       else null
       end as Score
from   SWBGRDE
group by CRSE_NUMB, Grade

If appropriate, you can just specify the top end of the range and let the CASE expression short-circuit to the first match.

CodePudding user response:

Don't use quote around 93 and 100:

SELECT CASE WHEN CAST(100 as varchar(3)) between 93 and 100 then 4.3 END FROM DUAL

But since you are using number I am not sure why you are casting it to varchar. Any particular reason?

  • Related