Re-write to_char function - oracle

When I use to_char function, It's know as internal_function in EP, and Index can't work in this column. Are there any way to re-write it? I don't want to create a function based index
This is my predicates code.
TO_CHAR(createdate,'dd-mm-yyyy') = TO_CHAR(systimestamp,'dd-mm-yyyy')
Many thanks.

Yes, this is exactly the reason we must use purely the date column on one side and a trunc(sysdate) like expression on the other instead of TO_CHAR while doing date comparisions.
where createdate >= trunc(sysdate)
and createdate < trunc(sysdate) + 1

Related

DATE queries using BETWEEN on oracle view

i have a problem with a date parameter query using 'between' operator in oracle view, when i do this query :
SELECT *
FROM MY_VIEW
WHERE STATUS = 'Active'
AND CHECKER_DATE BETWEEN to_date(sysdate - 1, 'DD-MON-YY') AND to_date(sysdate, 'DD-MON-YY');
it does not give me the records (actualy i have any record on that date).
I try using 'in' operator, but still not give me the records.
Please throw some information for this.
*checker_date defined as date
Your first error is to call to_date() on a value that is already a DATE. to_date() expects a VARCHAR value, so sysdate will be first converted to VARCHAR and will then immediately be converted back to a DATE value which it was to begin with.
You probably want
AND CHECKER_DATE BETWEEN trunc(sysdate) - 1 AND trunc(sysdate)
Most probably this will still not give you want you want as that would not include rows from "today". trunc(sysdate) means "today at midnight" and any row that was created today after midnight will not be included. With date/time values (and Oracle's DATE type does contain a time, despite the name) it's better to not use BETWEEN, but explicit range operators instead:
AND CHECKER_DATE >= trunc(sysdate) - 1
AND CHECKER_DATE < trunc(sysdate) + 1
trunc(sysdate) + 1 is tomorrow at midnight, so any value that is (strictly) smaller than that is "today".
All the above assumes that CHECKER_DATE is defined as DATE or TIMESTAMP
You can try:
SELECT *
FROM MY_VIEW
WHERE STATUS = 'Active'
AND CHECKER_DATE BETWEEN trunc(sysdate - 1) AND trunc(sysdate);
Oracle advises against using to_date for date. Also trunc is here because Trunc removes the time component.
may be records are not 'Active' or 'Active' a not-existing value in one of the reference tables if any and trunc(sysdate -1) and trunc(sysdate) would help

Query sysdate against field in SQL Developer

SELECT LAST_MAINTAIN, PLANE_ID
FROM PLANE
WHERE MONTHS BETWEEN(
(TO_DATE('sysdate', 'MM/DD/YYYY'),
TO_DATE('LAST_MAINTAIN', 'MM/DD/YYYY')))
>24;
I am trying to select Last_Maintain, a date field, from the Plane table and return results that have 2 years between today's date and the last maintenance. Does anyone know what is wrong? I have a feeling I am using months between incorrectly but I'm not sure. Thanks
Edit: Adjusted location of sysdate and Last_Maintain, still erroring out saying I'm missing a parentheses (right), even though I went through all my parentheses without seeing one missing.
Edit2: Tried out
SELECT *
FROM plane
WHERE MONTHS BETWEEN (sysdate, last_maintain ) > 24;
Still telling me I need more parentheses.
Edit3: Problem is resolved, here is the final code that worked:
SELECT *
FROM plane
WHERE MONTHS_BETWEEN (sysdate, last_maintain) > 24;
Don't call to_date on a date. to_date converts a string to a date. It would only make sense to pass a string to to_date.
sysdate is a function that returns a date. That is very, very different from a literal string sysdate
You probably want
SELECT *
FROM plane
WHERE months_between( sysdate, last_maintain ) > 24
MONTHS_BETWEEN returns the result as first - second, so in your case, all values are < 0. Put sysdate first.
From Oracle doc:
"If date1 is earlier than date2, then the result is negative"

Dynamic order by date data type in Oracle using CASE

My code in the stored procedure:
SELECT * FROM
my_table ir
WHERE
--where clause goes here
ORDER BY
CASE WHEN p_order_by_field='Id' AND p_sort_order='ASC' THEN IR.ID end,
CASE WHEN p_order_by_field='Id' AND p_sort_order='DESC' THEN IR.ID end DESC,
CASE WHEN p_order_by_field='Date' AND p_sort_order='ASC' THEN TO_CHAR(IR.IDATE, 'MM/dd/yyyy') end,
CASE WHEN p_order_by_field='Date' AND p_sort_order='DESC' THEN TO_CHAR(IR.IDATE, 'MM/dd/yyyy') end DESC;
Problem is that sorting is done based on the char, which comes out wrong for the date case. CASE statement, however, won't allow any other datatype other than char. So what is the solution in this case? I need to be able to pass the p_order_by_field into the stored procedure.
Thanks
Should be simple - just use ISO date format in your case:
TO_CHAR(IR.IDATE, 'yyyy-mm-dd')
and you should be fine.
Another problem could occure when you want to sort on the date difference (let say number of days between two days).
For example such a sort would return number 13 (days) before 9 (days).
The solution is that you concatenate length of date difference and the difference itself:
length(trunc(date2) - trunc(date1)) || to_char(date2 - date1)

Date comparison in Oracle 11g

I'm new to Oracle 11g & I have a question about a query.
I have a table dummy which has created_date column of type Date.
I want a query which will return all the records where created_date + 7 days is less than today's date.
What type of query in Oracle 11g accomplishes this?
Oracle lets you use + for date arithmetic, so
where table.created_date >= sysdate
and table.created_date < sysdate + 7
will find rows between exactly now and exactly now plus 7 days.
If you don't want to include the time component, you can use the trunc() function
where trunc(table.created_date) >= trunc(sysdate)
and trunc(table.created_date) < trunc(sysdate) + 7
I think rejj's solution will give you the records between now and seven days in the future. From your description, it sounds like you probably want those records within the past seven days. I'd do this as:
WHERE created_date <= SYSDATE
AND created_date >= SYSDATE - 7
This may be more clear, and is equivalent:
WHERE created_date BETWEEN SYSDATE AND (SYSDATE - 7)
Be aware that using TRUNC() will cause the optimizer to bypass any indexes you have on created_date, unless you have a functional index defined.
Using INTERVAL constants can make date arithmetic clearer, as in
SELECT *
FROM DUMMY
WHERE CREATED_DATE >= TRUNC(SYSDATE) - INTERVAL '7' DAY
Share and enjoy.

DATEDIFF (in months) in linq

select col1,col2,col3 from table1
where(DATEDIFF(mm, tblAccount.[State Change Date], GETDATE()) <= 4
I want to convert this sql query to LINQ. but I dont know any DateDiff alternative in LINQ. can you please suggest me?
You're looking for SqlMethods.DateDiffMonth.
EDIT: In EF4, use SqlFunctions.DateDiff.
Putting aside your original question for a moment, in your query you use:
where(DATEDIFF(mm, tblAccount.[State Change Date], GETDATE()) <= 4
This query would always cause a full table scan, since you're comparing the result of a function call against a constant. It would be much better if you calculate your date first, then compare your column value against the calculated value, which would allow SQL to use an index to find the results instead of having to evaluate every record in your table.
It looks like you're trying to retrieve anything within the past 4 months, so in your application code, try calculating the date that you can compare against first, and pass that value into your Linq2Entities expression:
DateTime earliestDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(-4);
var results = from t in context.table1
where t.col3 >= earliestDate
select t;
In EF6, the class to use is DbFunctions. See, for example, DbFunctions.DiffMonths.
I solved this problem in another manner: I calculated the date from code:
theDate = Date.Now.AddMonths(-4)
And in EF change the condition:
tblAccount.[State Change Date] < theDate

Resources