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

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?

Related

Issue querying date from oracle.

I understand that querying a date will fail as its comparing a string to date and that can cause an issue.
Oracle 11.2 G
Unicode DB
NLS_DATE_FORMAT DD-MON-RR
select * from table where Q_date='16-Mar-09';
It can be solved by
select * from table where trunc(Q_date) = TO_DATE('16-MAR-09', 'DD-MON-YY');
What I don't get is why this works.
select* from table where Q_date='07-JAN-08';
If anyone can please elaborate or correct my mindset.
Thanks
Oracle does allow date literals, but they depend on the installation (particularly the value of NLS_DATE_FORMAT as explained here). Hence, there is not a universal format for interpreting a single string as a date (unless you use the DATE keyword).
The default format is DD-MM-YY, which seems to be the format for your server. So, your statement:
where Q_date = '07-JAN-08'
is interpreted using this format.
I prefer to use the DATE keyword with the ISO standard YYYY-MM-DD format:
where Q_Date = DATE '2008-01-07'
If this gets no rows returned:
select * from table where Q_date='16-Mar-09';
but this does see data:
select * from table where trunc(Q_date) = TO_DATE('16-MAR-09', 'DD-MON-YY');
then you have rows which have a time other than midnight. At this point in the century DD-MON-RR and DD-MON-YY are equivalent, and both will see 09 as 2009, so the date part is right. But the first will only find rows where the time is midnight, while the second is stripping the time off via the trunc, meaning the dates on both sides are at midnight, and therefore equal.
And since this also finds data:
select* from table where Q_date='07-JAN-08';
... then you have rows at midnight on that date. You might also have rows with other times, so checking the count with the trunc version might be useful.
You can check the times you actually have with:
select to_char(q_date, 'YYYY-MM-DD HH24:MI:SS') from table;
If you do want to make sure you catch all times within the day you can use a range:
select * from table where
q_date >= date '2009-03-16'
and q_date < date '2009-03-17';
Quick SQL Fiddle demo.
Although it sounds like you're expecting all the times to be midnight, which might indicate a data problem.

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

Equals(=) vs. LIKE for date data type

First, I am aware that this question has been posted generally Equals(=) vs. LIKE.
Here, I query about date type data on ORACLE database, I found the following, when I write select statment in this way:
SELECT ACCOUNT.ACCOUNT_ID, ACCOUNT.LAST_TRANSACTION_DATE
FROM ACCOUNT
WHERE ACCOUNT.LAST_TRANSACTION_DATE LIKE '30-JUL-07';
I get all rows I'm looking for. but when I use the sign equal = instead :
SELECT ACCOUNT.ACCOUNT_ID, ACCOUNT.LAST_TRANSACTION_DATE
FROM ACCOUNT
WHERE ACCOUNT.LAST_TRANSACTION_DATE = '30-JUL-07';
I get nothing even though nothing is different except the equal sign. Can I find any explanation for this please ?
Assuming LAST_TRANSACTION_DATE is a DATE column (or TIMESTAMP) then both version are very bad practice.
In both cases the DATE column will implicitly be converted to a character literal based on the current NLS settings. That means with different clients you will get different results.
When using date literals always use to_date() with(!) a format mask or use an ANSI date literal. That way you compare dates with dates not strings with strings. So for the equal comparison you should use:
LAST_TRANSACTION_DATE = to_date('30-JUL-07', 'dd-mon-yy')
Note that using 'MON' can still lead to errors with different NLS settings ('DEC' vs. 'DEZ' or 'MAR' vs. 'MRZ'). It is much less error prone using month numbers (and four digit years):
LAST_TRANSACTION_DATE = to_date('30-07-2007', 'dd-mm-yyyy')
or using an ANSI date literal
LAST_TRANSACTION_DATE = DATE '2007-07-30'
Now the reason why the above query is very likely to return nothing is that in Oracle DATE columns include the time as well. The above date literals implicitly contain the time 00:00. If the time in the table is different (e.g. 19:54) then of course the dates are not equal.
To workaround this problem you have different options:
use trunc() on the table column to "normalize" the time to 00:00
trunc(LAST_TRANSACTION_DATE) = DATE '2007-07-30
this will however prevent the usage of an index defined on LAST_TRANSACTION_DATE
use between
LAST_TRANSACTION_DATE between to_date('2007-07-30 00:00:00', 'yyyy-mm-dd hh24:mi:ss') and to_date('2007-07-30 23:59:59', 'yyyy-mm-dd hh24:mi:ss')
The performance problem of the first solution could be worked around by creating an index on trunc(LAST_TRANSACTION_DATE) which could be used by that expression. But the expression LAST_TRANSACTION_DATE = '30-JUL-07' prevents an index usage as well because internally it's processed as to_char(LAST_TRANSACTION_DATE) = '30-JUL-07'
The important things to remember:
Never, ever rely on implicit data type conversion. It will give you problems at some point. Always compare the correct data types
Oracle DATE columns always contain a time which is part of the comparison rules.
You should not compare a date to a string directly. You rely on implicit conversions, the rules of which are difficult to remember.
Furthermore, your choice of date format is not optimal: years have four digits (Y2K bug?), and not all languages have the seventh month of the year named JUL. You should use something like YYYY/MM/DD.
Finally, dates in Oracle are points in time precise to the second. All dates have a time component, even if it is 00:00:00. When you use the = operator, Oracle will compare the date and time for dates.
Here's a test case reproducing the behaviour you described:
SQL> create table test_date (d date);
Table created
SQL> alter session set nls_date_format = 'DD-MON-RR';
Session altered
SQL> insert into test_date values
2 (to_date ('2007/07/30 11:50:00', 'yyyy/mm/dd hh24:mi:ss'));
1 row inserted
SQL> select * from test_date where d = '30-JUL-07';
D
-----------
SQL> select * from test_date where d like '30-JUL-07';
D
-----------
30/07/2007
When you use the = operator, Oracle will convert the constant string 30-JUL-07 to a date and compare the value with the column, like this:
SQL> select * from test_date where d = to_date('30-JUL-07', 'DD-MON-RR');
D
-----------
When you use the LIKE operator, Oracle will convert the column to a string and compare it to the right-hand side, which is equivalent to:
SQL> select * from test_date where to_char(d, 'DD-MON-RR') like '30-JUL-07';
D
-----------
30/07/2007
Always compare dates to dates and strings to strings. Related question:
How to correctly handle dates in queries constraints
The date field is not a string. Internally an implicit conversion is made to a string when you use =, which does not match anything because your string does not have the required amount of precision.
I'd have a guess that the LIKE statement behaves somewhat differently with a date field, causing implicit wildcards to be used in the comparison that eliminates the requirement for any precision. Essentially, your LIKE works like this:
SELECT ACCOUNT.ACCOUNT_ID, ACCOUNT.LAST_TRANSACTION_DATE
FROM ACCOUNT
WHERE ACCOUNT.LAST_TRANSACTION_DATE BETWEEN DATE('30-JUL-07 00:00:00.00000+00:00') AND DATE('30-JUL-07 23:59:59.99999+00:00');

character_length Teradata SQL Assistant

I have to run column checks for data consistency and the only thing that is throwing off my code is checking for character lengths for dates between certain parameters.
SEL
sum(case when ( A.date is null or (character_length(A.date) >8)) then 1 else 0 end ) as Date
from
table A
;
The date format of the column is YYYY-MM-DD, and the type is DA. When I run the script in SQL Assistant, I get an error 3580 "Illegal use of CHARACTERS, MCHARACTERS, or OCTET_LENGTH functions."
Preliminary research suggests that SQL Assistant has issues with the character_length function, but I don't know how to adjust the code to make it run.
with chareter length are you trying to get the memory used? Becuase if so that is constant for a date field. If you are trying to get the length of the string representation i think LENGTH(A.date) will suffice. Unfortanatly since teradata will pad zeros on conversions to string, I think this might always return 10.
UPDATE :
Okay so if you want a date in a special 'form' when you output it you need to select it properly. In teradata as with most DBs Date are not store in strings, but rather as ints, counting days from a given 'epoch' date for the database (for example the epoch might be 01/01/0000). Each date type in teradata has a format parameter, which places in the record header instructions on how to format the output on select. By default a date format is set to this DATE FROMAT 'MM/DD/YYYY' I believe. You can change that by casting.
Try SELECT cast(cast(A.date as DATE FORMAT 'MM-DD-YYYY') as CHAR(10)) FROM A. and see what happens. There should be no need to validate the form of the dates past a small sample to see if the format is correct. The second cast forces the database to perform the conversion and use the format header specified. Other wise what you might see is the database will pass the date in a date form to SQL Assitant and sql assitant will perform the conversion on the application level, using the format specified in its own setting rather then the one set in the database.

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')