简体   繁体   中英

Using a variable for a date range in Oracle SQL Developer

How can I alter the code below to get a date range as opposed to one day? Code 1 works, code 2 doesn't (I'm using Oracle SQl Developer)

CODE 1

DEFINE date1 = '01-JUN-17' 
SELECT * 
FROM   op_all_appointments OP 
WHERE  OP.ATTENDANCE_DTTM = '&&date1'

I tried the below, but it doesn't work? It returns data for the 1st June 2017 only

CODE 2

DEFINE date1 between '01-JAN-17' and '30-JUN-17'
SELECT * 
FROM   op_all_appointments OP 
WHERE  OP.ATTENDANCE_DTTM = '&&date1'

Thank you

If you looked at the output you got carefully, for your second define you would see:

SP2-0135: symbol date1 between '01-jan-17' and '30-jun-17' is UNDEFINED

so that command isn't actioned, your first define is still in effect, and you therefore still see the data for your first single date.

You could do it one go with:

DEFINE date1 = between '01-JAN-17' and '30-JUN-17'

which adds in the missing = which caused that SP error; your query woudl then change to:

...
WHERE  OP.ATTENDANCE_DTTM = &&date1

without an equals sign, and without quotes around the substitution variable.

But as this is relying on implicit conversion and your NLS settings, really you would need to do:

DEFINE date1 = between to_date('01-JAN-17', 'DD-MON-RR', 'NLS_DATE_LANGUAGE=''ENGLISH''') and to_date('30-JUN-17', 'DD-MON-RR', 'NLS_DATE_LANGUAGE=''ENGLISH''')

or more simply using date literals:

DEFINE date1 = between date '2017-01-01' and date '2017-06-30'

It would probably be neater to use two variables:

DEFINE date1 = 2017-01-01
DEFINE date2 = 2017-06-30

...
WHERE  OP.ATTENDANCE_DTTM between date '&&date1' and date '&&date2'

It's also worth noting that if your column has times other than midnight - as the DTTM suggests - you will miss any data on the last day of the range, ie anything after midnight on 2017-06-30. It's generally safer with a range to do:

DEFINE date1 = 2017-01-01
DEFINE date2 = 2017-07-01

...
WHERE  OP.ATTENDANCE_DTTM >= date '&&date1'
AND    OP.ATTENDANCE_DTTM < date '&&date2'

and you could the same range comparison in a single substitution variable if you really wanted to.

You might also want to consider using bind variables instead of substitution variables - though then you can't use date literals, but should still stick to a language-independent format and use to_date() with an explicit format mask; eg:

var date1 varchar2(10);
var date2 varchar2(10);
exec :date1 := '2017-01-01';
exec :date2 := '2017-07-01';

...
WHERE  OP.ATTENDANCE_DTTM >= to_date(:date1, 'YYYY-MM-DD')
AND    OP.ATTENDANCE_DTTM < to_date(:date2, 'YYYY-MM-DD')

... which you can't do in a single variable (with plain SQL anyway).

This is what you should be doing

SELECT * 
FROM   op_all_appointments OP 
WHERE  OP.ATTENDANCE_DTTM between date '2017-01-01' and date '2017-06-30'

If you want to use CTE

WITH data AS
    (SELECT DATE '2017-01-01' date1,
            DATE '2017-06-30' date2
    FROM dual
    )
SELECT *
FROM dual,
    data
WHERE sysdate BETWEEN data.date1 AND data.date2;
DEFINE date1 = 'between ''01-JAN-17'' and ''30-JUN-17'''
SELECT * 
FROM   op_all_appointments OP 
WHERE  OP.ATTENDANCE_DTTM  '&&date1'

OR (try both)

DEFINE date1 = 'between ''01-JAN-17'' and ''30-JUN-17'''
SELECT * 
FROM   op_all_appointments OP 
WHERE  OP.ATTENDANCE_DTTM  &&date1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM