ORA-01722: invalid number for Number datatype in oracle - oracle

I am trying to insert a value in KPI_DEFINITION table and i am getting amn error ORA-01722: invalid number. The error is for KPI_FREQUENCY field which NUMBER datatype and it has trying to insert value '0,5'. I think number datatype allows integer as well as float values. But still its giving an error.
Insert into RATOR_MONITORING_CONFIGURATION.KPI_DEFINITION (KPI_DEF_ID,KPI_NAME,KPI_DESC,KPI_FREQUENCY) values ('10003881','Backlog Resul11t','Backlog Result11','0,5');

In SQL numbers are not specified using single quotes.
Additionally: fractional digits are separated using a dot . not a comma. So you need to write this as:
Insert into RATOR_MONITORING_CONFIGURATION.KPI_DEFINITION
(KPI_DEF_ID,KPI_NAME,KPI_DESC,KPI_FREQUENCY)
values
('10003881','Backlog Resul11t','Backlog Result11', 0.5);
^
Here
If KPI_DEF_ID is also a number column, remove the single quotes for that value as well:
For a complete documentation on how to specify numbers or string literals, please see the manual:
https://docs.oracle.com/database/121/SQLRF/sql_elements003.htm#i139891

Possible data type for KPI_FREQUENCY in your case is number(2,1)
Modification of your insert statement
Insert into RATOR_MONITORING_CONFIGURATION.KPI_DEFINITION (KPI_DEF_ID,KPI_NAME,KPI_DESC,KPI_FREQUENCY)
values ('10003881','Backlog Resul11t','Backlog Result11',0.5);

Related

I want to export data from oracle database to csv, and I am putting a number filter on a varchar column. It thows ORA:01722 error. Please suggest

Select count(*) from table where loc between 300 to 400.
loc is a varchar column.
it is not selecting all the data
checking the count, gives ORA :01722 error
exporting the results with error.
Edit from comment:
loc contains values less than 300, more than 400, and alphanumeric like 'GT' , '3KT1'
loc is a varchar column.
[From comment] The Loc column has char type value also like GJ, 3KT1
LOC contains values which are not convertible to numbers. This matters because your WHERE clause predicates are defined as numbers, so Oracle applies an implicit to_number(loc) to the query. This is why using proper data types is best practice: it doesn't help you now but please learn the lesson, and use NUMBER columns for numeric data.
In the meantime you have several options to deal with your shonky data model.
If you're lucky enough to be using Oracle 12c R2 you can use the new VALIDATE_CONVERSION() function to exclude values of loc which can't be cast to numbers. Find out more
If you're using an earlier version of Oracle you can build your own function:
create or replace function is_number
(p_str in varchar2) return number
is
n number;
rv number;
begin
begin
n := to_number(p_str);
rv := 1;
exception
when invalid_number then
rv := 0;
end;
return rv;
end;
The weakest option would be casting the predicates to strings. where loc between '300' to '400' would include '3000', '4' and various other values you probably don't want.
Here is a LiveSQL demo (free Oracle Technet account required, alas).
Your current query is trying to compare a varchar to a number. So it tries to convert the varchar to a number on the fly. This is called implicit conversion.
You should make it compare a varchar to a varchar.
Use single quotes so that you are comparing to varchars, not numbers
Select count(*) from table where loc between '300' to '400'
Then go and read about implicit conversion
Based on the update to your question, this column is a legitimate varchar and should not be converted to a numeric data type.
However you do need to work out whether you are incorrectly storing different types of data in the same column

Oracle user defined records

In Oracle PL/SQL records we can use anchor datatypes (including %TYPE and %ROWTYPE) to define the fields.
When I populate a record from a query, in my select clause I want type conversion. Is that possible using an Oracle built-in function or some other approach?
In this example scenario I am using a simple decode function to perform a conversion:
DECLARE
TYPE TEST_RECORD IS RECORD(
FIRST_NAME EMPLOYEE_MT.FIRST_NAME%TYPE,
LAST_NAME EMPLOYEE_MT.LAST_NAME%TYPE,
MARITIAL_STATUS EMPLOYEE_MT.MARITAL_STATUS%TYPE);
EMPLOYEE_NAME TEST_RECORD;
BEGIN
SELECT EMP.FIRST_NAME,
EMP.LAST_NAME,
DECODE(EMP.MARITAL_STATUS, 1, 'MARRIED', 0, 'UN-MARRIED')
INTO EMPLOYEE_NAME
FROM EMPLOYEE_MT EMP
WHERE EMP.EMPLOYEE_ID = 1;
DBMS_OUTPUT.put_line(EMPLOYEE_NAME.MARITIAL_STATUS);
END;
which gets error:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 9
You have defined your record type with the maritial_status (shouldn't that be marital_status?) field using the same data type as the table column. From your decode that appears to be a number data type. You're then trying to set the record's field value to a string, either 'MARRIED' or 'UN-MARRIED', when that field is expecting a number. Clearly neither of those strings can be converted to a number, hence the error you're getting.
If you want the record to store the string value, you'll have to define it like that - explicitly as a string, rather than using %TYPE:
DECLARE
TYPE TEST_RECORD IS RECORD(
FIRST_NAME EMPLOYEE_MT.FIRST_NAME%TYPE,
LAST_NAME EMPLOYEE_MT.LAST_NAME%TYPE,
MARITAL_STATUS VARCHAR2(10));
...
DBMS_OUTPUT.put_line(EMPLOYEE_NAME.MARITAL_STATUS);
...
You can't do that automatically using %TYPE as the data type just doesn't match. You've explicitly told Oracle that you want the field's data type to be a number, so Oracle isn't going to let you put a string in that field instead. It isn't about there not being a built-in function, it just doesn't make sense.
This also means you can't use %ROWTYPE if you're changing the data type either (unless your modified value can be implicitly converted back to the column data type).

SQLDeveloper query automatic padding CHAR field

Given the table ATABLE with a field AFIELD of type CHAR(8), and where i have a field with value "1234567 "
Why, in SQL Developer, if I query:
SELECT * FROM ATABLE WHERE AFIELD = '1234567';
It will automatically pad the missing space and return the results, and if I query with :
SELECT * FROM ATABLE WHERE AFIELD = :value;
and input the value, it wont ?
From the documentation:
Within expressions and conditions, Oracle treats text literals as though they have the data type CHAR by comparing them using blank-padded comparison semantics.
When you do WHERE AFIELD = '1234567' the text literal '1234567' is treated as char and blank-padded comparison semantics are used to compare the column value and the literal. Even though the literal doesn't have the trailing space, those semantics see them as the same, so it finds a match.
When you use a bind variable the literal you assign to it is a char, but the bind variable itself is varchar2 - even if you declare it as char, oddly, though in that case the value is blank-padded anyway:
var char_value char(8);
exec :char_value := '1234567';
var varchar2_value varchar2(8);
exec :varchar2_value := '1234567';
select dump('1234567') as d1, dump(:char_value) as d2, dump(:varchar2_value) as d3
from dual;
D1 D2 D3
------------------------------------ ------------------------------------ ------------------------------------
Typ=96 Len=7: 49,50,51,52,53,54,55 Typ=1 Len=8: 49,50,51,52,53,54,55,32 Typ=1 Len=7: 49,50,51,52,53,54,55
The text literal is data type 96 (char), while both bind variables are type 1 (varchar/varchar2); but notice the char_value bind variable has the trailing space, with length 8 and the last character as code point 32.
When you compare your char column value with a varchar2 bind variable the column value is implicitly converted from char to varchar2:
The following rules govern implicit data type conversions:
During SELECT FROM operations, Oracle converts the data from the column to the type of the target variable.
So your space-padded char(8) column value is implicitly converted to varchar2(8) to match the bind variable's data type, and then because they are varchar2 the nonpadded comparison semantics are used.
When you compare your char(8) column with the supposedly-char(8) bind variable, you're actually comparing with a padded varchar2(8) - but both the implicitly converted column value and the blank-padded bind variable are actually the same, both with the trailing space; '1234567 ' is the same as '1234567 ', so there is a match, even with nonpadded comparison semantics.
With the varchar2(8) bind variable the same thing happens, but now the bound value is not padded, and as you are using nonpadded comparison semantics to compare '1234567 ' with '1234567' - they are not the same, so there is no match, and no data is returned by the query.
As #a_horse_with_no_name said you should almost always use varchar2 rather than char. But if you must use it and are stuck with it then at least make sure you use the same data type for comparisons.
You are right
SELECT * FROM ATABLE WHERE AFIELD = :value;
does not work with CHAR as you desire.
Anyway I have noticed that the following query works as you desire:
SELECT * FROM ATABLE WHERE AFIELD = &value;
If you use &value in several places, you can use &&value (double &) the first time (and &value elsewhere),
in order to avoid to input the same value several times;
when you have to change that value, you can undefine it with:
undef value;

Cannot convert String to date in Oracle 11g

I'm trying to insert Date into table from user input but something doesn't work.
I have the following Query :
INSERT INTO DOCTORS.TREATMENTS
(START_OF_TREATMENT, END_OF_TREATMENT, DOCTORS_ID,PACIENTS_ID, DIAGNOSIS_ID)
VALUES (TO_DATE(&startdate, 'yyyy/mm/dd'), TO_DATE(&enddate, 'yyyy/mm/dd'), 3, 1, 1);
For start date I set :
2000/10/01
And for end date I set :
2000/11/01
It seem ok for me but I've got the following error :
Error report -
ORA-01858: a non-numeric character was found where a numeric was expected
ORA-06512: at "SYS.STANDARD", line 167
ORA-06512: at line 2
01858. 00000 - "a non-numeric character was found where a numeric was expected"
*Cause: The input data to be converted using a date format model was
incorrect. The input data did not contain a number where a number was
required by the format model.
*Action: Fix the input data or the date format model to make sure the
elements match in number and type. Then retry the operation.
Any one can explain to me why this error occurred.
Best regards,
Petar.
The value of the first parameter passed to TO_DATE must be a string. After substitution with the value you've given your code will look like
TO_DATE(2000/10/01, 'yyyy/mm/dd')
which fails as shown.
The solution is to put the parameter usage in single-quotes to make the substituted value a string, as in
TO_DATE('&startdate', 'yyyy/mm/dd')
This way, when &startdate is substituted you'll get
TO_DATE('2000/10/01', 'yyyy/mm/dd')
which will work as expected.
Do the same for &enddate.
Best of luck.

PLSQL Invalid Month

Why am I getting invalid month when I test this code? How does PLSQL and XML handle data types?
CURSOR c_DATA_INF is
select * from xmltable ('/' PASSING i_XML COLUMNS READING_DT DATE PATH 'DATE',
Actual NUMBER PATH 'ACTUAL',
Eligible NUMBER PATH 'ELIGIBLE'
);
begin
for d in c_DATA_INF loop
insert into table_name(READING_DT, actual, eligible)
values (to_date('d.READING_DT', 'MM/DD/YYYY'), d.ACTUAL, d.ELIGIBLE);
end loop;
end;
I'm not sure if it's incorrect in my insert statement or in my cursor.
Thanks!
You are passing d.READING_DT as string. within quotes. Please remove the quotes and try
The parameter types are invalid in to_date(DATE, "DATE FORMAT STRING");
Link to Example
Instead of passing 'd.READING_DT', remove the quotes. Pass: d.READING_DT
The error is thrown becasue Oracle does not recognize 'd.READING_DT' as a valid date/ or date string.

Resources