I'm very new to using Oracle (I'm using TOAD 11.6), I would like to turn this code into something that would work in Oracle, how do I do it?!
declare #yesterday datetime
set #yesterday = (select cast(cast(getdate() as varchar(12)) as datetime)-1)
select *
from my_table
where disp_cret_dt >= #yesterday
Thanks in advance!!
I think you're after:
select *
from my_table
where disp_cret_dt >= trunc(sysdate-1);
That's assuming that disp_cret_dt is of datatype DATE or TIMESTAMP.
In Oracle, differences between two dates (which includes the time) are always returned as the number of days difference - and it can contain fractions of a day (eg. today at 12 noon - today at midnight = 0.5).
SYSDATE is Oracle's way of returning the current date+time.
TRUNC(dt, level) is the way you can truncate the date to whichever level you like - the default is day (which will just reset the time to midnight - 00:00), but you could do month (takes it back to the first of the month), hours etc etc.
Below is an equivalent code for oracle
declare yesterday date;
begin
select to_char(sysdate-1,'dd/mm/yyyy hh:mi:ss') into yesterday from dual;
select * into var1,var2..varn from my_table
where disp_cret_dt>=yesterday;
end;
1.Dual is temporary table in oracle which contains one column named as dummy with data type of varchar2(1). For more Refer here.
2.The SELECT INTO clause of SQL is used to retrieve one row or set of columns from the Oracle database. The SELECT INTO is actually a standard SQL query where the SELECT INTO clause is used to place the returned data into predefined variables.
If you want to return three items you have to define three variables in our pl/sql block with respective data types after applying these changes to above code it looks
declare
yesterday date;
v_item1 number;
v_item2 varchar2(11);
v_item3 date;
begin
select to_char(sysdate-1,'dd/mm/yyyy hh:mi:ss') into yesterday from dual;
select item1, item2,item3 into v_item1,v_item2,v_item3 from my_table
where disp_cret_dt>=yesterday;
Dbms_output.put_line('Item1: '||v_item1||'Item2: '||v_item2||'Item3: '||v_item3);--Displaying values
end;
Note: In the above code if your select query will returns more than one row for each yesterday value then it will throws an error. Because at a time a variable will holds one value. In that scenario we have to choose collections in oracle for more Refer here.
if you want to have "yesterday" in a seperate variable because you use it more than once in your code, assign "sysdate-1" to it:
declare
yesterday date := trunc(sysdate - 1);
begin
select * from my_table where disp_cret_dt >= yesterday;
end;
Related
I am using SAP BODS and I am trying to fetch data from an ORACLE server using SQL query transormation. Now The table has a column named latest_changed_date which is a datetime column. I only want yesterday and current day data from that table. Now since the column is datetime, I need to convert it to date, but when I am using to_date function I get the following error.
SELECT *
FROM ABC.TEST
WHERE TO_DATE(LATEST_CHANGED_DATE) = TO_DATE(SYSDATE-1)
The database error message is
ORA-01843: not a valid month
I tried giving date format in TO_DATE condition as below:
SELECT *
FROM ABC.TEST
WHERE TO_DATE(LATEST_CHANGED_DATE,'YYYY-MM-DD') >= TO_DATE(SYSDATE-1,'YYYY-MM-DD')
Here I got the error:
date format picture ends before converting entire input string
I used trunc function also and again got either:
not a valid month
or
inconsistent datatypes: expected NUMBER got DATE
Below is a sample data for the column. I just need data for current and day before data from the column.
Update: I think the main issue is that I am not able to determine the proper datatype for the column in the source table and currently I don't have an option to determine that.
Rather than trying to implicitly cast your dates to strings and convert them back using TO_DATE( string_value, format_model ) you can use TRUNC() to truncate SYSDATE to the start of the day:
SELECT *
FROM ABC.TEST
WHERE LATEST_CHANGED_DATE >= TRUNC( SYSDATE-1 )
this will work:
SELECT *
FROM ABC.TEST
where sysdate-LATEST_CHANGED_DATE<=sysdate-(sysdate-2);
for example take this:
ALTER SESSION SET NLS_DATE_FORMAT = ' DD-MON-YYYY HH24:MI:SS';
SELECT * FROM d061_dates ;
03-DEC-2018 17:44:38
25-AUG-2018 17:44:42
30-AUG-2018 17:44:46
01-DEC-2018 17:44:49
02-DEC-2018 17:46:31
SELECT * FROM d061_dates
where sysdate-a<=sysdate-(sysdate-2);
03-DEC-2018 17:44:38
02-DEC-2018 17:46:31
you have to take sysdate minus on both sides to get comparision by a number which is less than equal to 2 to get day and day before yesterday and its giving the correct output.
thank you!!!!!!!!!!!!!
In Oracle 12, if I create a very simple table, TEST_TABLE, with a single varchar2(128) column 'name' and populate that column with lots of strings of '20170831', and my sysdate shows:
SELECT sysdate FROM dual;
29-SEP-17
then why does this SQL query return 0 rows:
SELECT TO_DATE(name,'YYYYMMDD'),
TO_DATE(TRUNC(SYSDATE),'DD-MM-YYYY')
FROM TEST_TABLE
WHERE TO_DATE(name,'YYYYMMDD') < TO_DATE(TRUNC(SYSDATE),'DD-MM-YYYY');
(This is a very simplified example of a problem I'm facing in my partition maintenance script and have not been able to solve for the last week).
Thank you in advance for any assistance related to the above query.
Midnight(time part is 00:00:00.000):
SELECT TO_DATE(name,'YYYYMMDD'), TRUNC(SYSDATE)
FROM TEST_TABLE
WHERE TO_DATE(name,'YYYYMMDD') <= TRUNC(SYSDATE);
You could also try:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
Just don't apply a to_date() to an already date field, this because, it will implicitly convert that date into varchar and then apply the to_date() function to it, for example your query part TO_DATE(TRUNC(SYSDATE),'DD-MM-YYYY') is interpreted like this:
TO_DATE(TO_CHAR(TRUNC(SYSDATE)),'DD-MM-YYYY')
TO_CHAR(TRUNC(SYSDATE)) is getting a char something like: '31-AUG-17', and that is not in 'DD-MM-YYYY' format.
And because of that, TO_DATE(TRUNC(SYSDATE),'DD-MM-YYYY') gets something like this: 29/09/0017 and your filter goes FALSE and gets no results.
I would like to write a stored procedure that inserts some data into a table from another table (table b). But does one date from table b at a time. The date range is given as parameters in the stored procedures
Is my logic correct? I would really appreciate some tips
CREATE OR REPLACE PROCEDURE database_name.test(start_date,end_date)
-- declare parameters convert dates into numbers
BEGIN FOR i in start_date..end_date LOOP INSERT INTO SOME_TABLE SELECT
* FROM OTHER_TABLE WHERE date = i END LOOP
END database_name.test;
Is there a reason that you need a loop? I would think that you'd just want
INSERT INTO destination_table
SELECT *
FROM source_table
WHERE source_table.date_column BETWEEN p_start_date AND p_end_date;
What you really need is not clear (from my point of view). If you need to create some dates list, you could use the following query to generate a list a dates between the begin date [bgin_d] and the end date [end_d]:
WITH dtes AS (SELECT SYSDATE bgin_d, SYSDATE + 30 end_d FROM DUAL)
SELECT bgin_d + LEVEL
FROM dtes
CONNECT BY bgin_d <= end_d;
I have a table that has a StartDate and EndDate field, and also a ton of other fields. I need to break out each record by all the days between and including StartDate & EndDate into another table that looks exactly like the original except it has a CurrentDate field and 2 calculated fields. The CurrentDate field is the current date between StartDate and EndDate that I'm interating on.
My question is, since there are a ton of fields in this, is there any easy way from within my stored proc, to insert the entire row the cursor is currently on AND this 1 new column, without having to list out every single row in the insert statement? It's so tedious.
If your source and destination tables fit this profile:
Destination table columns are the same as your source table's columns, and
The new destination column is at the end
... then you could do something like this:
INSERT INTO dest_table
SELECT Source_Table.*, new_value
FROM Source_Table
WHERE Source_Table.PKValue = cursor.PKValue
If it's a case of your cursor resembling the destination table, something like this may work but note I haven't tested it:
CREATE PROCEDURE whatever IS
destRow dest_table%ROWTYPE;
CURSOR fromSourceTable IS
SELECT <your existing select list>, NULL AS new_value
FROM <the rest of your cursor query>;
BEGIN
FOR destRow IN fromSourceTable LOOP
destRow.new_value = <the split date>;
INSERT INTO dest_table VALUES destRow;
END LOOP;
END whatever;
I'm going out on a limb with the NULL AS new_value. If you have trouble try CAST(NULL AS DATE) AS new_value instead, and if you still have trouble try something like SYSDATE AS new_value. Again, this isn't tested but if you think it's promising and have trouble implementing I'd be happy to test it.
It's easy enough to densify the data in a single SQL statement. Assuming that you know a reasonable minimum and maximum range for your begin_date and end_date (I'll assume Jan 1, 2000 - Dec 31, 2020 for the moment but you can obviously adjust that)
WITH all_days AS (
SELECT date '2000-01-01' + level dt
FROM dual
CONNECT BY level <= date '2020-12-31' - date '2000-01-01'
)
SELECT <<list of colums from your table>>,
all_days.dt current_date
FROM your_table actual
JOIN all_days ON (actual.begin_date <= all_days.dt AND
actual.end_date >= all_days.dt)
If you don't want to hard-code the starting and ending dates, you can fetch them from your table as well. That just requires that you hit the table a second time which will generally be less efficient.
I am new to oracle, I have to create a function that returns current date and time.
I am using this to return date;
SELECT CURRENT_DATE FROM dual;
Thanx
CURRENT_DATE returns the date and time of the session. SYSDATE returns the date and time of the database. These values may be different because we can change our session's timezone using ALTER SESSION. You probably ought to be using SYSDATE because it returns a consistent value, although without knowing your business context it is hard to be certain.
From your question I suspect you don't realise that Oracle date pseudo-columns include a time element. Try this:
alter session set nls_date_format='dd-mon-yyyy hh24Lmi:ss'
/
select current_date from dual
/
select sysdate from dual
/
There is not a lot of point in wrapping one of those pseudo-columns in your own user-defined function. The one time I seriously considered it was to make it easier to inject times into some automated unit tests. But I never convinced myself that this facility would justify not using the standard approach.
edit
The solution in the accepted answer works but has a lot of unnecessary baggage. All that additional PL/SQL runs 2-3 times slower than a straight select sysdate from dual;. It is true that these are very small differences in absolute terms - milliseconds, if that. But in a busy system with lots of calls to getSysdate() all those milliseconds could add up to a big chunk of time. A better solution would be to replace all that code with a plain return sysdate; This is slightly slower than calling sysdate directly but only by a little.
Expanding on dpbradley's comment, I have knocked up a function which allows us to substitute a different clocktime from the database, for the purposes of testing. I am storing my alternate datetime in the CLIENT_INFO namespace in the default context; if I were implementing this in a production system I would build a dedicated user defined context for it.
So here is my take on the getSysdate() function...
SQL> create or replace function myGetSysdate
2 ( p_alt_date in varchar2 := null )
3 return date is
4 begin
5 if p_alt_date is null then
6 return sysdate;
7 else
8 return to_date(sys_context('userenv', p_alt_date)
9 , 'dd-mon-yyyy hh24:mi:ss');
10 end if;
11 end;
12 /
Function created.
SQL>
Here is how we set the alternate datetime...
SQL> exec dbms_application_info.set_client_info('01-DEC-2010 12:12:12')
PL/SQL procedure successfully completed.
If no parameter is passed it returns sysdate (the default and preferred option).
SQL> select getsysdate from dual
2 /
GETSYSDATE
-----------------
05-JAN-2010 16:25
SQL>
If we pass a context namespace when we call the function we get the alternate datetime....
SQL> select mygetsysdate('CLIENT_INFO') from dual
2 /
MYGETSYSDATE('CLI
-----------------
01-DEC-2010 12:12
SQL>
As an actual function you could do:
create or replace function getSysdate
return date is
l_sysdate date;
begin
select sysdate
into l_sysdate
from dual;
return l_sysdate;
end;
/
Which you could test in SQLPlus as:
TEST>select getSysdate() from dual;
GETSYSDATE
----------
2010-01-04
Not sure why you would want this versus just having sysdate in your code. The Oracle date datatype includes the time portion.
try:
SELECT TO_CHAR(CURRENT_DATE, 'DD-MON-YYYY HH:MI:SS') FROM dual;
if you need it in a certain format. More options here:
http://www.psoug.org/reference/date_func.html
The most simple, I suppose:
SELECT SESSIONTIMEZONE, CURRENT_TIMESTAMP FROM DUAL;