Oracle sql - вычитание даты внутри функции - PullRequest
0 голосов
/ 02 марта 2012

(перенесено из предыдущего поста) - извините, если это воспринимается как повторение! Всем привет, Просто возникают некоторые проблемы с вычислениями даты и вычитанием даты из функции.

Я запутался с типами данных, которые я должен использовать, например, когда мне нужно преобразовать дату в _char. Я не уверен, иметь ли тип возвращаемого значения как varchar2 или date?

Вот функция, которая получает car_id, просматривает таблицу для этого автомобиля, извлекает дату прибытия автомобилей, сохраняет ее в переменной даты

делает то же самое с датой отъезда.

Затем преобразует обе даты в _char, выполняет вычитание и возвращает его в varchar2.

Когда я вызываю функцию, она вводит car_id в качестве параметра, затем сохраненный возвращенный результат в переменной varchar для вывода в dbms. например.

v_result := get_duration('0001')

вот функция:

DROP FUNCTION get_duration;  
CREATE FUNCTION get_duration (p_car_id number)  
RETURN varchar2 is  
v_arrive date;  
v_depart date  
v_duration varchar2(25); --not too sure about this variable choice  

begin  

select arrival, departure  
into v_arrive, v_depart
from car_info
where car_id = p_car_id;

v_duration := to_char(v_depart, 'dd-mon-yyyy hh24:mi:ss') - to_char(v_arrive, 'dd-mon-yyyy hh24:mi:ss')  
return v_duration; 
 END;  
/ 

Как вы можете видеть, я пытаюсь поместить время начала и окончания таблицы в переменные, затем минус дата окончания от даты начала.

Функция компилируется, но с предупреждением, и когда я вызываю функцию, появляется ошибка: get_duration недействителен

Любой вклад в это будет получен,

Извините, если сообщение относительно большое!

С уважением,

Даррен

Ответы [ 3 ]

2 голосов
/ 02 марта 2012

Тривиальные проблемы заключаются в том, что при определении v_depart вы пропускаете ;, а в конце строки присваиваете значение v_duration;и вы путаете имена переменных.(Вы также не согласны с типом car_info.id; вы создали его как varchar, когда он, вероятно, должен быть числом, но это скорее комментарий к вашему предыдущему вопросу).

Основная проблема в том, что вы не можете выполнить минус для двух строк, так как это ничего не значит.Вам необходимо выполнить манипуляции с исходными датами, а затем выяснить, как вы хотите вернуть результат вызывающей стороне.

Вычитание одной даты из другой дает числовое значение, которое является числом дней;неполные дни - это дроби, поэтому 0,25 - это 6 часов.С датами из вашего предыдущего квестона этот запрос:

select arrival, departure, departure - arrival as duration
from car_info
where car_id = 1;

... показывает длительность 2,125, то есть 2 дня и 3 часа.

Это не лучший способсделать это, но чтобы показать вам процесс происходящего, я буду использовать этот номер продолжительности и преобразовать его в строку довольно скучным образом:

CREATE OR REPLACE FUNCTION get_duration (p_car_id number)
RETURN varchar2 is
    v_arrive date;
    v_depart date;
    v_duration number;
    v_days number;
    v_hours number;
    v_minutes number;
    v_seconds number;
BEGIN

    select arrival, departure, departure - arrival
    into v_arrive, v_depart, v_duration
    from car_info
    where car_id = p_car_id;

    -- Days is the whole-number part, which you can get with trunc
    v_days := trunc(v_duration);
    -- Hours, minutes and seconds are extracted from the remainder
    v_hours := trunc(24 * (v_duration - v_days));
    v_minutes := trunc(60 * (v_duration - v_days - (v_hours/24)));
    v_seconds := trunc(60 * (v_duration - v_days - (v_hours/24)
        - (v_minutes/(24*60))));

    return v_days || ' days '
        || to_char(v_hours, '00') || ' hours '
        || to_char(v_minutes, '00') || ' minutes '
        || to_char(v_seconds, '00') || ' seconds';
END;
/

Function created.

show errors

No errors.

select get_duration(1) from dual;

GET_DURATION(1)
--------------------------------------------------------------------------------
2 days  03 hours  00 minutes  00 seconds

Вы можете играть с форматом чиселмаски и т. д., чтобы получить желаемый результат.

2 голосов
/ 02 марта 2012

Арифметика DATE работает с DATE, а не с VARCHAR2s:

CREATE FUNCTION get_duration (p_car_id number)  
RETURN varchar2 is  
v_arrive date;  
v_depart date  
v_duration number; --<<<

begin  

select arrival, departure  
into v_arrive, v_depart
from car_info
where car_id = p_car_id;

v_duration := v_arrive - v_depart;
return v_duration; 
 END; 

Это дает результат в днях.

0 голосов
/ 02 марта 2012

Вы не можете вычесть даты, как только вы приведете их к varchar2 (функция to_char делает это!). Вместо этого используйте v_duration := v_stop - v_start;, который даст вам результат v_duration в днях. Затем вы можете преобразовать его в часы, минуты и т. Д.

...