Упакованная функция Oracle не работает через связанный сервер SQL Server 2008 R2 - PullRequest
1 голос
/ 11 февраля 2012

У меня есть следующая перегруженная функция в пакете oracle (10g).

function fnDaysFromNowToDate(dd_mon_yyyy date) return number is days number;
    --d2 varchar2(11):=to_char(sysdate,ddf);
Begin
   dbms_output.put_line( 'd='|| to_date(dd_mon_yyyy,'dd-mon-yyyy'));
   dbms_output.put_line( 's='|| to_date(sysdate,'dd-mon-yyyy'));
    return    trunc(dd_mon_yyyy-trunc(sysdate));

  --return 1;
  end;
  --- overload for varchar
  function fnDaysFromNowToDate(dd_mon_yyyy varchar2) return number is days number;
  Begin
   dbms_output.put_line( 'd='|| to_date(dd_mon_yyyy,'dd-mon-yyyy'));
   dbms_output.put_line( 's='|| to_date(sysdate,'dd-mon-yyyy'));
    return    trunc(to_date(dd_mon_yyyy,'dd-mon-yyyy')-trunc(sysdate));
  end;

И оба они отлично работают при выполнении в Oracle Sql Developer, например,

select t$stdt,to_char(t$tdat,'dd-Mon-YYYY') t$tdat, t$cuno,T$CPGS,T$QANP,T$DISC 
   from baan.ttdsls031020 
       where 
       trim(t$cuno)        =   '000811' 
      and pkgUtils.fnDaysFromNowToDate(to_char(t$tdat,'dd-Mon-YYYY')) >  1
        and t$qanp           =   pkgPriceWorx.fndefaultQanp 
      and trim(t$cpgs)  =   '1AM00';

но когда я выполняю тот же запрос через связанный SQL-сервер с помощью поставщика OraOLEDB.Oracle

select * from openquery(hades,"
select t$stdt,to_char(t$tdat,'dd-Mon-YYYY') t$tdat, t$cuno,T$CPGS,T$QANP,T$DISC 
   from baan.ttdsls031020 
       where 
       trim(t$cuno)        =   '000811' 
      and pkgUtils.fnDaysFromNowToDate(to_char(t$tdat,'dd-Mon-YYYY')) >  1
        and t$qanp           =   pkgPriceWorx.fndefaultQanp 
      and trim(t$cpgs)  =   '1AM00'
       ");

, выдаются следующие ошибки

Поставщик OLE DB "OraOLEDB.Oracle" для связанного сервера "hades "вернуло сообщение
ORA-01861: литерал не соответствует строке формата
ORA-06512: в« SAAP.PKGUTILS », строка 29». Поставщик OLE DB «OraOLEDB.Oracle» для связанного сервера «hades» вернулсообщение "ORA-01861: литерал не соответствует строке формата ORA-06512: в" SAAP.PKGUTILS ", строка 29". Поставщик данных SqlClient .Net: сообщение 7320, уровень 16, состояние 2, строка 3, невозможно выполнить запрос "выберитеt $ stdt, to_char (t $ tdat, 'dd-Mon-YYYY') t $ tdat, t $ cuno, T $ CPGS, T $ QANP, T $ DISC из baan.ttdsls031020, где trim (t $ cuno) = '000811 'и pkgUtils.fnDaysFromNowToDate (to_char (t $ tdat,' dd-Mon-YYYY '))> 1 и t $ qanp = pkgPriceWorx.fndefaultQanp и trim (t $ cpgs) = '1AM00' 'для поставщика OLE DB "OraOLEDB.Oracle" для связанных серверов "hades". *

Есть идеи, почему такое поведение?

Ответы [ 2 ]

1 голос
/ 23 марта 2012

В моем случае мне нужно было использовать trunc (sysdate).

Мне нужно было вызвать функцию оракула со связанного сервера SQL Server 2005. Я создал связанный сервер и могу запросить его, но в тот момент, когда я вызываю функцию оракула, у меня появляются разные ошибки, такие как Поставщик OLE DB «OraOLEDB.Oracle» для связанного сервера «BAN23» вернул сообщение «ORA-01841: (полный) год должен быть в диапазоне от -4713 до +9999, а не 0».

Поставщик OLE DB "OraOLEDB.Oracle" для связанного сервера "BAN23" вернул сообщение "ORA-01861: литерал не соответствует строке формата".

Я пробовал разные типы запросов, такие как выбрать * из открытого запроса (BAN23, 'ВЫБЕРИТЕ contab.fu_icaro_tasas (' 'current_date' ',' 'USD' ',' 'COP' ') FROM dual')

select * from openquery (BAN23, 'SELECT contab.fu_icaro_tasas (' 'sysdate' ',' 'USD' ',' 'COP' ') FROM dual')

select * from openquery (BAN23, 'SELECT contab.fu_icaro_tasas (to_date (current_date,' 'DD-MM-YYYY' '),' 'USD' ',' 'COP' ') FROM dual') выберите * из открытого запроса (BAN23, 'ВЫБЕРИТЕ contab.fu_icaro_tasas (to_date (sysdate,' 'DD-MM-YYYY' '),' 'USD' ',' 'COP' ') FROM dual')

Мое решение было добавить trunc (sysdate) или trunc (current_date)

select * from openquery (BAN23, 'SELECT contab.fu_icaro_tasas (trunc (current_date),' 'USD' ',' 'COP' ') FROM dual')

Этот последний запрос работает очень хорошо.

1 голос
/ 12 февраля 2012

Я не думаю, что хорошей практикой является перегрузка функции plsql, которая получает Date, с помощью функции, которая получает varchar2, поскольку oracle много раз автоматически приводил varchar2 к Date в соответствии с NLS_DATE_FORMAT, которая может варьироваться в зависимости от среды ,

В любом случае, вы не должны запускать "to_char (t $ tdat, 'dd-Mon-YYYY')", если t $ tdat равен varchar2, потому что тогда oracle сначала приведёт ваш varchar2 к дате (потому что to_char получает дату как параметр) в соответствии с NLS_DATE_FORMAT.
Вы также не должны использовать to_date для дат (из того же резонанса)

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

function do_things(d date) return number is

begin

dbms_output.put_line('d=' || to_char(d, 'dd-mon-yyyy'));
dbms_output.put_line('s=' || to_char(sysdate, 'dd-mon-yyyy'));

return trunc(d - trunc(sysdate));

end do_things;


function fnDaysFromNowToDate(dd_mon_yyyy date) return number is
days number;
begin
--d2 varchar2(11):=to_char(sysdate,ddf);Begin dbms_output.put_line( 'd='|| to_date(dd_mon_yyyy,'dd-mon-yyyy'));

dbms_output.put_line('function gets date');
days := do_things(dd_mon_yyyy);
return days;

end fnDaysFromNowToDate;
--return 1; end; --- overload for varchar


function fnDaysFromNowToDate(dd_mon_yyyy varchar2) return number is
days number;
Begin
dbms_output.put_line('function gets varchar2');
days := do_things(to_date(dd_mon_yyyy, 'dd-mon-yyyy'));
return days;

end fnDaysFromNowToDate;
...