sysdate и current_date имеют разные типы?

Документы оракула для sysdate и current_date утверждают, что они оба возвращают DATE:

Однако этот тест:

alter session set plsql_warnings = 'ENABLE:ALL';
create table test(x date);
create or replace procedure test1 authid definer is
    cursor s is select x from test where current_date > x;
begin for x in s loop null; end loop; end;
/
show errors
drop table test;
drop procedure test1;

производит этот вывод:

Errors for PROCEDURE TEST1:
LINE/COL  ERROR
3/42      PLW-07204: conversion away from column type may result in sub-optimal query plan

Использование sysdate не дает такого же предупреждения. Я подозреваю, что замена current_date на sysdate в запросах может привести к изменению плана запроса, особенно если столбцы даты проиндексированы.

редактировать:

select dump(current_date) from dual;
select dump(sysdate) from dual;

дает:

DUMP(CURRENT_DATE)
Typ=13 Len=8: 223,7,7,9,11,23,55,0

DUMP(SYSDATE)
Typ=13 Len=8: 223,7,7,9,11,23,55,0

person Alistair Bayley    schedule 08.07.2015    source источник
comment
Я бы не потерял сон из-за этого. Также обратите внимание, что, хотя они оба возвращают типы DATE (мы думаем), они потенциально не возвращают одно и то же значение. Один из них скорректирован с учетом часового пояса.   -  person OldProgrammer    schedule 09.07.2015
comment
Вы можете вывести sysdate, current_date и литерал даты, чтобы увидеть внутренние номера типов. Я ожидаю, что оптимизатор будет достаточно умен, чтобы неявно преобразовать sys/current_date в соответствии с типом столбца, а не наоборот, поэтому будет использоваться тот же план запроса. Однако достаточно легко проверить оба плана. (Или было бы, если бы у меня был доступ к БД прямо сейчас *8-)   -  person Alex Poole    schedule 09.07.2015
comment
Некоторые доказательства (без фактического теста), что планы запросов могут быть разными: community.oracle.com /thread/1049266?tstart=0   -  person Alistair Bayley    schedule 09.07.2015
comment
@алекс: DUMP(CURRENT_DATE) Typ=13 Len=8: 223,7,7,9,11,11,57,0 DUMP(SYSDATE) Typ=13 Len=8: 223,7,7,9,11,11,57,0   -  person Alistair Bayley    schedule 09.07.2015
comment
«Нормальная» дата имеет тип 12. . Так странно, что вы не получаете такого же предупреждения с sysdate. Я думаю, что видел это раньше, но не могу вспомнить, был ли способ избежать предупреждения без приведения, и это могло быть связано с версией; какую версию вы используете?   -  person Alex Poole    schedule 09.07.2015
comment
@OldProgrammer: 2 балла: (1) я нахожусь в том же часовом поясе, что и сервер (2) тип DATE не содержит информации о часовом поясе, поэтому и sysdate, и current_date возвращают одно и то же значение. И мы можем видеть это с помощью DUMP. Я не ожидал предупреждения от PL/SQL, я не могу найти ему хорошего объяснения, и у меня нет модели, с помощью которой это можно было бы объяснить. Необъяснимое и непредсказуемое поведение меня нервирует.   -  person Alistair Bayley    schedule 09.07.2015
comment
@AlexPoole select distinct version from product_component_version дает 11.2.0.2.0   -  person Alistair Bayley    schedule 09.07.2015
comment
Это предупреждение создается для любой функции даты и даже с литералами датыдважды при использовании to_date(). Только sysdate обрабатывается по-разному, что может быть связано с ошибки 9714892, 8760135 и т. д. Трудно сказать, является ли это ложным предупреждением - если выборка неверна, это может повлиять на план, я полагаю (см. также план; только sysdate имеет обозначение @!, как в filter("X"<SYSDATE@!)). не думаю, что дело именно в типах, а в специальной обработке для sysdate?   -  person Alex Poole    schedule 09.07.2015
comment
Привет, тип sysdate и current_date одинаковый, но current_date извлекает данные от вашего клиента или лучше из часового пояса сеанса. Таким образом, вы не можете легко изменить sysdate с помощью current_date.   -  person Giova    schedule 21.07.2015
comment
Привет, как сказал Алекс Пул, это предупреждение может быть связано с ошибкой 8760135. Если ваша версия ниже 11.2.0.2, попробуйте тот же запрос в 11.2.0.2.   -  person Giova    schedule 21.07.2015
comment
Это также проявляется в 11.2.0.3.5 и 12c @Giova.   -  person Ben    schedule 25.07.2015
comment
Интересно, что вы НЕ получаете предупреждение, если используете SYS.STANDARD.CURRENT_DATE вместо CURRENT_DATE.   -  person Matthew McPeak    schedule 10.08.2015


Ответы (1)


1) CURRENT_DATE возвращает текущую дату в часовом поясе сеанса. Вам действительно нужна current_date? Если нет, придерживайтесь sysdate. Это будет работать ваша процедура

2) Если вам все еще нужна CURRENT_DATE, решение приведено ниже. Сохраните значение current_date в переменной, и это решит вашу проблему. Позвольте мне, если это отвечает на ваш вопрос.

drop table test;
create table test(x date);
create or replace procedure test1 authid definer 
is
dateVar date;
cursor s is select x from test where dateVar > x;
begin 
dateVar:=current_date;
for x in s loop null; 
end loop; 
end;
/
SQL> show errors
No errors.
person Nilesh Deshpande    schedule 04.09.2015
comment
Ответ выше устранил вашу проблему? - person Nilesh Deshpande; 07.09.2015
comment
Я понимаю разницу между семантикой часового пояса current_date sysdate. В моем случае это не имеет значения, потому что и сервер, и клиент находятся в одном часовом поясе. На самом деле я рассматривал возможность рекомендации использовать current_date (стандарт ANSI) предпочтительно вместо sysdate и обнаружил, что current_date не может быть наивной заменой sysdate. - person Alistair Bayley; 07.09.2015
comment
в порядке. Процедура, которую я привел выше, работает для current_date в случае, если вы хотите использовать - person Nilesh Deshpande; 08.09.2015