cx_Oracle.DatabaseError: ORA-01843: not a valid month - sql

select distinct sko.CONTENTId,
sko.HELPDESKID,
sko.SEGMENTID,
som.SUBMITTED_FOR_NAME,
sko.SUBMITTEDDATE,
to_date(sko.LASTMODIFIEDDATE, 'DD-MM-RR')
from sky_know_obj sko
join sky_object_mass som
on sko.CONTENTId = som.CONTENTId
where sko.LASTMODIFIEDDATE > date'2019-11-03'
and sko.LASTMODIFIEDDATE <= date'2019-12-03'
This is my oracle sql query. i am running it in python. when I run this in the Oracle SQL Developer then it is giving results but whenever I tried to execute it in the pycharm the following error is occuring:
cx_Oracle.DatabaseError: ORA-01843: not a valid month
when I run
select * from nls_session_parameters;
this in oracle sql developer then its showing
NLS_DATE_FORMAT = DD-MM-RR

As you apply TO_DATE to LASTMODIFIEDDATE column and it fails, it seems that not all values have valid month in that column which means that its datatype isn't date but varchar2.
SQL Developer doesn't return all rows, but the first 50 (or so). If your query scans the whole table, or rows that weren't displayed initially, then it'll fail. Try to navigate to the last row in returned record set in SQL Developer to see what happens.
On the other hand, if column's datatype is date, then don't to_date it; there's no point in doing that.
Also, you shouldn't rely on database's settings. Take control over your data and don't specify string when meaning date. Use date literal, e.g.
where lastmodifieddate > date '2019-11-03' -- instead of '03-11-19'

Related

ORACLE QUERY to pass date as variable in TOAD

I'm new to oracle and trying to run a simple query to pass date dynamically
DEFINE startdate = TO_DATE(select TRUNC(LAST_DAY(ADD_MONTHS( max(nav_last_calc_dt) ,-1))+1) from tb);
DEFINE enddate = TO_DATE(select TRUNC(LAST_DAY(ADD_MONTHS(max(nav_last_calc_dt),0))) from tb);
begin
select Count(1)
FROM tb
WHERE DATE BETWEEN &startdate AND &enddate;
end;
I received the below error when executing using script (F5), TOAD script runner.
ORA-06550: line 4, column 78:
PL/SQL: ORA-00936: missing expression
ORA-06550: line 2, column 1:
PL/SQL: SQL Statement ignored
But when using SQL PLUS , it returned 7 as result. So I'm confused.
SQL*Plus isn't returning 7 as the result; you haven't completed the anonymous PL/SQL block, so it is showing you 7 as the next line number (as 'begin' is line 1 and 'end;' is line 6, and is waiting for input. If you enter a slash and hit return it will then execute the block; which will throw the same ORA-00936 error.
In both clients the problem is the DATE keyword - it's expecting that to be the start of a date literal, and doesn't see the rest of the literal value as it expects. That should be a column name, presumably:
WHERE nav_last_calc_dt DATE BETWEEN &startdate AND &enddate;
But the block will still fail, possibly for different reasons in the two clients; in SQL*Plus it will still get ORA-00936 because the defined value ends at the first space (which you can fix by enclosing in double quotes), and Toad may throw that error or complain that your select has no 'into' clause. (Or it might do something else; SQL Developer against 12cR1 is throwing an internal error.) The outer TO_DATE in your defined expressions is also not ideal - it will implicitly convert the date you have to a string and then convert that string back again to a real date, both using your session NLS settings; which might work, but isn't needed.
It's not clear why you are using PL/SQL there, or really why you are using a substitution variable - it's not really dynamic, it just makes the final statement a bit more obscure.
The date calculation also seems a bit complicated. It looks like you're trying to count rows from the last month with any data; and you're finding the first day of that month using add_months and last_day - which could be done more simply just by truncating the maximum date using the 'MM' date component:
select count(*)
from tb
where nav_last_calc_dt >= (select trunc(max(nav_last_calc_dt), 'MM') from tb)
Assuming the column used for the filter is `nav_last_calc_dt, and not some other column, you don't need an upper bound - you know the maximum date is in that month, so it has to be within the month.
If if was another column, with later dates, and you used between then you would exclude any values after midnight on the last day of that month. It's safer to use a full month range:
select count(*)
from tb
where some_date >= (select trunc(max(nav_last_calc_dt), 'MM') from tb)
and some_date < (select add_months(trunc(max(nav_last_calc_dt), 'MM'), 1) from tb)
which would find all values at or after midnight on the first day of the target month, and before midnight on the first day of the following month.
It might then be worth getting the maximum date once, but you could do that in a CTE or an inline view rather than via define, which wouldn't actually save you anything the way you are trying to use it - since both defined queries would be substituted into the query/block before it's executed.

PeopleSoft Query and date prompts

I have a PS Query and one of its prompts is ADM_CREATION_DT where the condition is:
This is a FROM date. All records starting from the selected date to the current date will be included in the report. Leaving this blank will default this to the current date.
I'm quite lost how to put this in the criteria.
part where Invalid datatype error happens
I think you can make a decode expression and make the date sysdate if the prompt value is empty.
decode(:1,NULL,sysdate,:1)
here are some search results for: ps query decode prompt sysdate
https://peoplesoftexperts.blogspot.com/2007/12/how-to-default-sysdate-current-date-for.html
https://it.toolbox.com/question/optional-prompt-for-date-in-ps-query-082912
http://www.psoftsearch.com/optional-prompting-ps-query/
Looking at the search results above, you may need to do a TO_CHAR on the date field. If so, I would look at other dates in the SELECT clause of the SQL generated by PS Query and use the same format they do.

Sql Query using 'Like' is giving results but using '=' does not returns any result in Oracle

The Query using LIKE :(This query when fired gives the desired result)
select * from catissue_audit_event where event_timestamp like '16-DEC-14'
But when using query with '=' results in an empty resultset
select * from catissue_audit_event where event_timestamp='16-DEC-14'
Here event_timestamp is of type Date
Strange thing is that the query runs for other dates such as:
select * from catissue_audit_event where event_timestamp='15-DEC-14'
What can be the issue? I already checked for leading and trailing spaces in the data
Output after running the first query:
In Oracle a DATE (and of course a TIMESTAMP) column contains a time part as well.
Just because your SQL client is hiding the time, doesn't mean it isn't there.
If you want all rows from a specific day (ignoring the time) you need to use trunc()
select *
from catissue_audit_event
where trunc(event_timestamp) = DATE '2014-12-16';
Be aware that this query will not use an index on the event_timestamp column.
You should also not rely on implicit data type conversion as you do with the expression event_timestamp = '16-DEC-14. That statement is going to fail if I run it from my computer because of different NLS settings. Always use a proper DATE literal (as I have done in my statement). If you don't like the unambiguous ISO date, then use to_date():
where trunc(event_timestamp) = to_date('16-12-2014', 'dd-mm-yyyy');
You should avoid using month names unless you know that all environments (which includes computers and SQL clients) where your SQL statement is executed are using the same NLS settings. If you are sure, you can use e.g. to_date('16-DEC-14', 'dd-mon-yy')
The reason why this is different is different to the solution to your issue.
The solution to your issue is to stop performing date comparisons by implicit conversion to a string. Convert your string to a date to perform a date comparison:
select * from catissue_audit_event where event_timestamp = date '2014-12-16'
I cannot stress this enough; when performing a date comparison only compare dates.
Your column EVENT_TIMESTAMP is being implicitly (this is bad) converted to a date in accordance with your NLS_DATE_FORMAT, which you can find as follows:
select * from nls_session_parameters
This governs how date-data is displayed and implicitly converted. The reason why LIKE works and and = doesn't is because your NLS_DATE_FORMAT is masking additional data. In other words, your date has a time component.
If you run the following and then re-select the data from your table you'll see the additional time component
alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss'
Thus, if you want all the data for a specific date without constraint on time you'll need to remove the time component:
select * from catissue_audit_event where trunc(event_timestamp) = date '2014-12-16'
have you tried matching the event_timestamp format example: DD-MMM-YY with the date that you are passing?

selecting data fom a view throws error

I get input as 2011/11/13 00:00:00. So I made the query as:
select * from xxcust_pfoa434p_vw
where week_ending_date = to_date(substr(:value,1,10),'YYYY/MM/DD')
The same statement gives proper result when queried against other tables. But throws error when I query this against the view xxcust_pfoa434p_vw
I have a view xxcust_pfoa434p_vw which has a column week_ending_date of date data type.
The value in that column is like 3/2/2014,12/25/2011 i.e. MM/DD/YYYY
Even
select * from xxcust_pfoa434p_vw where week_ending_date='3/2/2014'
also gives
ORA-01843: not a valid month. What is the cause for this error.
You say
"The same statement gives proper result when queried against other
tables. But throws error when I query this against the view
xxcust_pfoa434p_vw"
So clearly the problem is with the view. You also say
"[the view] has a column week_ending_date of date data type. The value
in that column is like 3/2/2014,12/25/2011 i.e. MM/DD/YYYY "
Those values would only display like that if the default date mask for you system were MM/DD/YYYY. This is easy enough to check with the query
select * from V$NLS_PARAMETERS
where parameter = 'NLS_DATE_FORMAT';
Personally, my money is on that column not being a date column. ORA-01841 always indicates oracle attempting to cast a string into a date and finding a value which doesn't fit the explicit or default format mask. Plus the so-called date '3/2/2014' lacks leading zeroes and that's suspicious too.
I think whoever wrote that view decided to fix the format of week_ending_date and so deployed TO_CHAR to present a string not a date datatype. A DESC in SQL*Plus or looking at the view TEXT in ALL_VIEWS will reveal the answer.
select * from xxcust_pfoa434p_vw
where week_ending_date=to_date('03/02/2014','MM/DD/YYYY');
Even if you see formatted date in this format - it is only a visual representation, when oracle process your query it automatically convers string given by you into its own interal representation.
It is always better to use proper SQL one YYYY-MM-DD:
for 2nd march: select * from xxcust_pfoa434p_vw where week_ending_date = to_date('2014-03-02', 'YYYY-MM-DD')
for 3rd february: select * from xxcust_pfoa434p_vw where week_ending_date = to_date('2014-02-03', 'YYYY-MM-DD')
this conforms to SQL standard and do not produce confusion between DD/MM/YYYY and MM/DD/YYYY
Just quote from standard:
There is an ordering of the significance of <datetime field>s. This
is, from most significant to least significant: YEAR, MONTH, DAY,
HOUR, MINUTE, and SECOND.
UPDATE: it is very good idea always use to_date function to specify exact format and avoid dependancy on any kind of localization settings

Updating a date in Oracle SQL table

I am trying to update a date in a SQL table. I am using Peoplesoft Oracle. When I run this query:
Select ASOFDATE from PASOFDATE;
I get 4/16/2012
I tried running this query
UPDATE PASOFDATE SET ASOFDATE = '11/21/2012';
but it is not working.
Does anyone know how I would change the date to the one desired?
This is based on the assumption that you're getting an error about the date format, such as an invalid month value or non-numeric character when numeric expected.
Dates stored in the database do not have formats. When you query the date your client is formatting the date for display, as 4/16/2011. Normally the same date format is used for selecting and updating dates, but in this case they appear to be different - so your client is apparently doing something more complicated that SQL*Plus, for example.
When you try to update it it's using a default date format model. Because of how it's displayed you're assuming that is MM/DD/YYYY, but it seems not to be. You could find out what it is, but it's better not to rely on the default or any implicit format models at all.
Whether that is the problem or not, you should always specify the date model:
UPDATE PASOFDATE SET ASOFDATE = TO_DATE('11/21/2012', 'MM/DD/YYYY');
Since you aren't specifying a time component - all Oracle DATE columns include a time, even if it's midnight - you could also use a date literal:
UPDATE PASOFDATE SET ASOFDATE = DATE '2012-11-21';
You should maybe check that the current value doesn't include a time, though the column name suggests it doesn't.
Here is how you set the date and time:
update user set expiry_date=TO_DATE('31/DEC/2017 12:59:59', 'dd/mm/yyyy hh24:mi:ss') where id=123;
If this SQL is being used in any peoplesoft specific code (Application Engine, SQLEXEC, SQLfetch, etc..) you could use %Datein metaSQL. Peopletools automatically converts the date to a format which would be accepted by the database platform the application is running on.
In case this SQL is being used to perform a backend update from a query analyzer (like SQLDeveloper, SQLTools), the date format that is being used is wrong. Oracle expects the date format to be DD-MMM-YYYY, where MMM could be JAN, FEB, MAR, etc..
Just to add to Alex Poole's answer, here is how you do the date and time:
TO_DATE('31/DEC/2017 12:59:59', 'dd/mm/yyyy hh24:mi:ss')