How to schedule a job in SQL Developer - oracle-sqldeveloper

I would like to schedule a procedure to run at specificic hours, three times a day: at 12:00, 16:00 and 18:30.
Is there any way to create such a job (using standard SQL Developer job wizard)?
I scheduled a job, by setting BYHOUR = 12,16,18 and BYMINUTE = 0,30, but then it starts six times a day, which is not exactly what I want.
Thanks in advance for tips!

The simplest way, if you don't want to create two jobs, is to create two schedules instead. You can do this through the Schedules->New Schedule context menu item, or from a worksheet:
begin
dbms_scheduler.create_schedule(schedule_name => 'sched_1',
repeat_interval => 'FREQ=MINUTELY;BYHOUR=12,16;BYMINUTE=0');
dbms_scheduler.create_schedule('sched_2',
repeat_interval => 'FREQ=MINUTELY;BYHOUR=18;BYMINUTE=30');
end;
/
Then in the job wizard, set 'Repeat Interval' to SCHED_1,SCHED_2. Of course, you might want to use more meaningful names...
You can check when the combined schedule will run - after the current time - with something like this:
set serveroutput on;
declare
start_date timestamp with time zone;
return_date_after timestamp with time zone;
next_run_date timestamp with time zone;
begin
start_date := cast(sysdate as timestamp with time zone);
for i in 1 .. 8 loop
return_date_after := nvl(next_run_date, start_date);
dbms_scheduler.evaluate_calendar_string(
calendar_string => 'sched_1,sched_2',
start_date => start_date,
return_date_after => return_date_after,
next_run_date => next_run_date);
dbms_output.put_line('Will run at: '
|| to_char(next_run_date, 'YYYY-MM-DD HH24:MI:SS'));
end loop;
end;
/
Will run at: 2014-04-08 16:00:18
Will run at: 2014-04-08 18:30:18
Will run at: 2014-04-09 12:00:18
Will run at: 2014-04-09 16:00:18
Will run at: 2014-04-09 18:30:18
Will run at: 2014-04-10 12:00:18
Will run at: 2014-04-10 16:00:18
Will run at: 2014-04-10 18:30:18

Related

Postgres generate date series with exactly 100 steps

Lets say we have the dates
'2017-01-01'
and
'2017-01-15'
and I would like to get a series of exactly N timestamps in between these dates, in this case 7 dates:
SELECT * FROM
generate_series_n(
'2017-01-01'::timestamp,
'2017-01-04'::timestamp,
7
)
Which I would like to return something like this:
2017-01-01-00:00:00
2017-01-01-12:00:00
2017-01-02-00:00:00
2017-01-02-12:00:00
2017-01-03-00:00:00
2017-01-03-12:00:00
2017-01-04-00:00:00
How can I do this in postgres?
Possibly this can be useful, using the generate series, and doing the math in the select
select '2022-01-01'::date + generate_series *('2022-05-31'::date - '2022-01-01'::date)/15
FROM generate_series(1, 15)
;
output
?column?
------------
2022-01-11
2022-01-21
2022-01-31
2022-02-10
2022-02-20
2022-03-02
2022-03-12
2022-03-22
2022-04-01
2022-04-11
2022-04-21
2022-05-01
2022-05-11
2022-05-21
2022-05-31
(15 rows)
WITH seconds AS
(
SELECT EXTRACT(epoch FROM('2017-01-04'::timestamp - '2017-01-01'::timestamp))::integer AS sec
),
step_seconds AS
(
SELECT sec / 7 AS step FROM seconds
)
SELECT generate_series('2017-01-01'::timestamp, '2017-01-04'::timestamp, (step || 'S')::interval)
FROM step_seconds
Conversion to function is easy, let me know if have trouble with it.
One problem with this solution is that extract epoch always assumes 30-days months. If this is problem for your use case (long intervals), you can tweak the logic for getting seconds from interval.
You can divide the difference between the end and the start value by the number of values you want:
SELECT *
FROM generate_series('2017-01-01'::timestamp,
'2017-01-04'::timestamp,
('2017-01-04'::timestamp - '2017-01-01'::timestamp) / 7)
This could be wrapped into a function if you want to avoid repeating the start and end value.

I got one problem in SQL,i need to get start of next minute value

I need to get the start of next Minute value, that means suppose I got the output for GETDATE() is 19.11.2019 12:52:51 but I need to get 19.11.2019 12:53:00
This is my code:
DECLARE #date DATETIME
SET #date = GETDATE()
DECLARE #increase int = 1;
SELECT DATEADD(mi, #increase,#date) as nextminutedate;
You want to round the date down. One method in SQL Server is:
select dateadd(minute, 1+datediff(minute, 0, getdate()), 0)
This is a little inscrutable. The datediff() calculates the number of minutes from a time of 0 for the current date/time. The dateadd() adds this back in.
Note: This works for minutes. You might have overflow problems with seconds or milliseconds.
For this reason, I rather prefer:
select dateadd(minute, 1+datediff(minute, '2000-01-01', getdate()), '2000-01-01')
I find this is clearer in the intention.

need tsql code for time intervel and the values should go to that particular interval the original time is in epoch format

I have to add column to table.
The column value is calculated based on the column already present in the table.
I have to get time-stamp (column already present) and then group them into 5 min time-slots.
E.g: if the time is:
13:03/13:02 then it should go as 13:00;
13:53/13:52 then it should go as 13:50;
13:21 then should go as 13:20 and so on
PS: basically I have to get time stamp in epoch (UNIX time stamp)format [the table has values in epoch as well as in regular time stamp]
So what I'm seeing is that you have times and you need to round them down to the nearest 5 minute increment. Try this:
DECLARE #table TABLE (times TIME)
INSERT INTO #table
VALUES ('13:03'),
('13:02'),
('13:53'),
('13:52'),
('13:21');
SELECT times,
DATEADD(MINUTE,-DATEDIFF(MINUTE,0,times) % 5,times) five_minute_increments
FROM #table
Results:
times five_minute_increments
---------------- ----------------------
13:03:00.0000000 13:00:00.0000000
13:02:00.0000000 13:00:00.0000000
13:53:00.0000000 13:50:00.0000000
13:52:00.0000000 13:50:00.0000000
13:21:00.0000000 13:20:00.0000000
Epoch Version
DECLARE #epoch BIGINT;
--Epoch is the seconds since Jan 1,1970
SET #epoch = DATEDIFF(SECOND,'1970-01-01','2015-04-01 12:06:00.000');
SELECT CAST(DATEADD(SECOND,#epoch - (#epoch %300),'1970-01-01 00:00:00.000') AS TIME) AS epochTimes
Results:
12:05:00.0000000
create table epoch1(epoch int not null,
epoch_date as dateadd(s,epoch,'19700101'))
insert epoch1(epoch) values(1331070999)
insert epoch1(epoch) values(1331070956)
insert epoch1(epoch) values(1331071998)
insert epoch1(epoch) values(1331071999)
select DATEADD(MINUTE,-DATEDIFF(MINUTE,0,dateadd(MINUTE,epoch,'19700101')) % 5,dateadd(MINUTE,epoch,'19700101')) as human ,DATEDIFF(MINUTE, '1970-01-01 00:00:00', DATEADD(MINUTE,-DATEDIFF(MINUTE,0,dateadd(MINUTE,epoch,'19700101')) % 5,dateadd(MINUTE,epoch,'19700101'))) as timeinterval
from epoch1

T-sql IF Condition date evaluation

I have a simple question regarding T-SQL. I have a stored procedure which calls a Function which returns a date. I want to use an IF condition to compare todays date with the Functions returned date. IF true to return data.
Any ideas on the best way to handle this. I am learning t-sql at the moment and I am more familar with logical conditions from using C#.
ALTER FUNCTION [dbo].[monday_new_period](#p_date as datetime) -- Parameter to find current date
RETURNS datetime
BEGIN
-- 1 find the year and period given the current date
-- create parameters to store period and year of given date
declare #p_date_period int, #p_date_period_year int
-- assign the values to the period and year parameters
select
#p_date_period=period,
#p_date_period_year = [year]
from client_week_uk where #p_date between start_dt and end_dt
-- 2 determine the first monday given the period and year, by adding days to the first day of the period
-- this only works on the assumption a period lasts a least one week
-- create parameter to store the first day of the period
declare #p_start_date_for_period_x datetime
select #p_start_date_for_period_x = min(start_dt)
from client_week_uk where period = #p_date_period and [year] = #p_date_period_year
-- create parameter to store result
declare #p_result datetime
-- add x days to the first day to get a monday
select #p_result = dateadd(d,
case datename(dw, #p_start_date_for_period_x)
when 'Monday' then 0
when 'Tuesday' then 6
when 'Wednesday' then 5
when 'Thursday' then 4
when 'Friday' then 3
when 'Saturday' then 2
when 'Sunday' then 1 end,
#p_start_date_for_period_x)
Return #p_result
END
ALTER PROCEDURE [dbo].[usp_data_to_retrieve]
-- Add the parameters for the stored procedure here
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF monday_new_period(dbo.trimdate(getutcdate()) = getutcdate()
BEGIN
-- SQL GOES HERE --
END
Thanks!!
I assume you are working on Sql2008. See documentation of IF and CASE keywords for more details.
CREATE FUNCTION dbo.GetSomeDate()
RETURNS datetime
AS
BEGIN
RETURN '2012-03-05 13:12:14'
END
GO
IF CAST(GETDATE() AS DATE) = CAST(dbo.GetSomeDate() AS DATE)
BEGIN
PRINT 'The same date'
END
ELSE
BEGIN
PRINT 'Different dates'
END
-- in the select query
SELECT CASE WHEN CAST(GETDATE() AS DATE) = CAST(dbo.GetSomeDate() AS DATE) THEN 1 ELSE 0 END AS IsTheSame
This is the basic syntax for a T-SQL IF and a date compare.
If you are comparing just the date portion for equality you will need to use:
select dateadd(dd,0, datediff(dd,0, getDate()))
This snippet will effectively set the time portion to 00:00:00 so you can compare just dates. So in use it will look something like this.
IF dateadd(dd,0, datediff(dd,0, fn_yourFunction())) = dateadd(dd,0, datediff(dd,0, GETDATE()))
BEGIN
RETURN SELECT * FROM SOMEDATA
END
Hope that helps!

Using a variable period in an interval in Postgres

I have a relation that maintains monthly historical data. This data is added to the table on the last day of each month. A service I am writing can then be called specifying a month and a number of months prior for which to retrieve the historical data. I am doing this by creating startDate and endDate variables, and then returning data between the two. The problem I am having is that startDate is a variable number of months before endDate, and I cannot figure out how to use a variable period in an interval.
Here is what I have:
DECLARE
endDate TIMESTAMP := (DATE_TRUNC('MONTH',$2) + INTERVAL '1 MONTH') - INTERVAL '1 DAY';
startDate TIMESTAMP := endDate - INTERVAL $3 'MONTH';
I know that the line for startDate is not correct. How is this properly done?
Use this line:
startDate TIMESTAMP := endDate - ($3 || ' MONTH')::INTERVAL;
and note the space before MONTH.
Basically: You construct a string with like 4 MONTH and cast it with ::type into a proper interval.
Edit: I' have found another solution: You can calculate with interval like this:
startDate TIMESTAMP := endDate - $3 * INTERVAL '1 MONTH';
This looks a little bit nicer to me.
This code has nothing directly to do with your situation, but it does illustrate how to use variables in INTERVAL arithmetic. My table's name is "calendar".
CREATE OR REPLACE FUNCTION test_param(num_months integer)
RETURNS SETOF calendar AS
$BODY$
select * from calendar
where cal_date <= '2008-12-31 00:00:00'
and cal_date > date '2008-12-31' - ($1 || ' month')::interval;
$BODY$
LANGUAGE sql VOLATILE
COST 100
ROWS 1000;
The most readable way I have found to pass a variable time period to Postgres is similar to A.H.'s answer: by multiplying by an integer. But this can be done without a cast.
Python example (with sqlalchemy and pandas):
import pandas as pd
import sqlalchemy as sa
connection = sa.create_engine(connection_string)
df = pd.read_sql(
sa.text('''
select * from events
where
event_date between now() - (interval '1 day' * :ndays) and now()
limit 100;
'''),
connection,
params={'ndays': 100}
)
The number of days (ndays) is passed as an integer from within Python - so unintended consequences are less likely.
My approach is like this.. It gives me option to set specific date or a relative range.
create or replace function search_data(_time_from timestamptz default null, _last_interval text default null)
returns setof journal
language plpgsql as
$$
begin
return query
select *
from journal
where created >= case
when _time_from is not null
then _time_from
else now() - _last_interval::interval end;
end;
$$;
While the above accepted answer is fine, it's a little bit antiquated - requiring a bit more mental energy to read than needed if you're running on Postgres 9.4+.
Old Way (Postgres Versions < 9.4)
startDate TIMESTAMP := endDate - $3 * INTERVAL '1 MONTH';
New Way (Postgres 9.4+)
startDate TIMESTAMP := endDate - MAKE_INTERVAL(MONTHS => $3);
If you are on Postgres 9.4+, the new MAKE_INTERVAL() function seems much more readable - probably why they created it.
If you want something you can run in your editor, here are a couple of
examples (I substituted the original variable binding $3 with the number 2 for an example of 2-months prior to the current date).
SELECT CURRENT_DATE - 2 * INTERVAL '1 MONTH';
SELECT CURRENT_DATE - MAKE_INTERVAL(MONTHS => 2);