PLSQL Invalid Month - oracle

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.

Related

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.

Determining input datatype Oracle/PLSQL

I am writing a PLSQL 'INSTEAD OF INSERT' Trigger whereby the ID field (GID) can be inserted as either a string or a number. If the GID value is a string I would like to attempt to convert that into the correct GID (number) otherwise if a number is input the script will continue.
The part I am struggling with here is determining the datatype of ':New.CHART_GID' - is this possible in PLSQL? I can't check for chars in the string as the string may only contain numbers in some instances.
Thanks.
You can use TRANSLATE to check if there is something other as numbers:
CREATE OR REPLACE TRIGGER trigger_name
INSTEAD OF INSERT
ON table_name
FOR EACH ROW
DECLARE
vGID INTEGER;
...... other things
BEGIN
IF :New.CHART_GID is not null AND TRANSLATE(:New.CHART_GID,'0123456789',' ') is null THEN
vGID := TO_NUMBER(:New.CHART_GID);
.... do what you want with number
ELSE
... do what you want with not number
END IF;
.... other things
END;
CHART_GID have to be varchar2 in the view
I realise what I was trying to achieve was actually not possible. The solution for me was actually to join the Chart_no into the view and insert into either that field of the GID. If I input a Chart_no the GID field would be automatically populated and the same for if I input a GID.

ORA-01722: invalid number for Number datatype in 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);

sqlloader date conversion: inconsistent data type

Am trying to load some data to an Oracle database using SQLLoader but I keep getting the errors ORA-00932: inconsistent datatypes: expected DATE got NUMBER or expecting char got date
The date comes in the format of e.g. 20130815 and it is to be stored into a database with a column of type Date.
The logic should be that if someone passes an invalid date a null or say an invalid month in the date string e.g. 20131301, then I want to insert a default date e.g. 19990101.
Here is the SQLLoader code I have so far:
COLUMN_DOB DATE 'YYYYMMDD' "CASE:COLUMN_DOB WHEN 'isdate(:COLUMN_DOB)=1' THEN :COLUMN_DOB ELSE to_date('19000101', 'YYYYMMDD') END",,
The immediate issue is that you're calling to_date() on the fixed value. The then part is returning the original string value of the date from the file; the else is returning a date; which leads to the 'expecting char got date' message.
If you remove the to_date() part then it will load all the values as 1900-01-01, because you have the case statement wrong. You're comparing the :COLUMN_DOB value with the string 'isdate(:COLUMN_DOB)=1'. It isn't calling the function, it's a fixed string, and your date field is never going to exactly match that text. So the case always goes into the else and gets the fixed value. You also seem to be mixing up the two forms of case statement.
So it should be:
... "CASE WHEN isdate(:COLUMN_DOB)=1 THEN :COLUMN_DOB ELSE '19000101' END"
Which, assuming you've built an isdate() function - since that is not an Oracle built-in - with a default format mask, something like this one based on an AskTom version:
create or replace function isdate (p_string in varchar2,
p_fmt in varchar2 := 'YYYYMMDD')
return number as
l_date date;
begin
if l_date is null then
return 0;
end if;
l_date := to_date(p_string, p_fmt);
return 1;
exception
when others then
return 0;
end;
/
... will put in valid dates as supplied, and invalid dates as 1900-01-01. The null check also means nulls will be inserted as 1900-01-01; it's perhaps simpler to have it here than to try to handle that separately in the control file.
You could maybe simplify it further by having a function that tries to convert the string and returns a date, and just calling that in the control file, without the date mask or the case statement. That approach is covered in that AskTom link too.
Personally I'd probably prefer to see the column left null rather than giving it a magic number. It isn't impossible to have someone with a valid DOB of 1900-01-01.
If you are creating a new function anyway, you could do this instead:
create or replace function my2date(p_str in varchar2) return date is
begin
return to_date(nvl(p_str, '19000101'), 'YYYYMMDD');
exception
when others then -- just about acceptable here
return date '1900-01-01';
end;
/
which you can execute from SQL*Plus, SQL Developer, Toad or whatever client you're using. And then you control file would have:
COLUMN_DOB "my2date(:COLUMN_DOB)"
I don't think there's a way of doing this without using a function. If you used an external table instead then you could use an anonymous block to do the conversion I suppose, but if you're stuck with SQL*Loader then I believe a function is the only way to stop a bad date causing the whole row to be rejected.

How to change character set of the XMLTYPE variable?

I'm currently having non-utf-8 DB but I need to produce XMLType variable with utf-8 encoding. I'm having a workaround but there seems to be bug in the Oracle, see the following link:
https://forums.oracle.com/forums/thread.jspa?messageID=10238641
...and Oracle Support bug: 7698684
The bug causes random
ORA-1482: unsupported character set
ORA-6512: at "SYS.XMLTYPE", line 107
First of all I'm getting XMLType with dbms_xmlgen package. That XMLType is encoded with DB character set.
To convert it to utf-8 character set I do like this:
I convert XMLType variable to BLOB variable with getBlobVal method using NLS_CHARSET_ID
('UTF8') as parameter
I convert BLOB variable back to XMLType with XMLType constructor method using BLOB variable as first parameter and NLS_CHARSET_ID
('UTF8') as second parameter. This causes random error :(
Does anybody know any alternative solution for this?
l_xml := dbms_xmlgen.getXMLType(l_ctx);
l_xml_b := l_xml.getBlobVal(C_UTF8_CHARSET_ID);
l_xml := XMLType(l_xml_b, C_UTF8_CHARSET_ID);
I managed to do this with convert function. It was not possible to convert the whole xml document (even the clob value of it) but only element values.
This was not working (XMLType constructor fails):
l_xml := XMLType(convert(l_xml.getClobVal, 'UTF8'));
So I had to put convert to the query string (this is just an example):
select dbms_xmlgen.getXMLType(
q'{select convert('รค', 'UTF8') myValue from dual}')
from dual
Finally I made a function which reads dictionary and loops through all columns of the given table/view and generates select statement string where all columns are converted separately to UTF8. This string can then be passed as parameter to the dbms_xmlgen.newContext function.

Resources