Сбои Oracle PL/SQL, ссылка на базу данных и гетерогенные службы: ORA-02070: база данных MSAccessODBC64bit не поддерживает TO_NUMBER в этом контексте

Я использую гетерогенные услуги Oracle (HS). У меня есть ссылка на базу данных таблицы Microsoft Access с именем employee, Из соединения Oracle с использованием SQL*Plus я могу описать столбцы и типы данных таблицы (desc employee). Я также могу выбрать из удаленной таблицы и получить записи.

Однако при использовании анонимного блока я получаю сообщение об ошибке Oracle:

ORA-02070: database MSAccessODBC64 does not support TO_NUMBER in this context

MSAccessODBC64 мой настроенный ODBC DSN в Windows 7.

Код:

declare
   my_record_position number := 60109;
   my_record employee@MSAccessODBC64bit%rowtype;
begin
   select
      *
   into
      my_record
   from
      eemployee@MSAccessODBC64bit ---->> When I remove the database link, it works
   where
      staff_number = my_record_position ---->> when I remove the where clause, it works
   order by
      staff_number asc;
   dbms_output.put_line(my_record.staff_number);
end;
/

Ошибка:

   declare
      *
   ERROR at line 1:
   ORA-02070: database MSAccessODBC64 does not support TO_NUMBER in this context
   ORA-06512: at line 5

Есть ли какая-то проблема или опция, необходимая для работы HS? Что я пропускаю?

Когда я использую переменную подстановки, она работает и отображает employeeid,

define emp = 60109;
declare
   my_record_position number := 60109;
   my_record employee@MSAccessODBC64bit%rowtype;
begin
   select
      *
   into
      my_record
   from
      employee@MSAccessODBC64bit
   where
      staff_number = &emp
   order by
      staff_number asc;
   dbms_output.put_line('emp=' || my_record.staff_number);
end;
/
emp=60109

PL/SQL procedure successfully completed.

===========initMSAccessODBC64bit.ora for ODBC==============

# This is a sample agent init file that contains the HS parameters that are
# needed for the Database Gateway for ODBC

#
# HS init parameters
#
HS_DESCRIBE_CACHE_HWM   = 4000
HS_FDS_CONNECT_INFO     = MSAccessODBC64bit
HS_FDS_TRACE_LEVEL      = DEBUG
HS_OPEN_CURSORS         = 50
HS_RPC_FETCH_REBLOCKING = ON
HS_RPC_FETCH_SIZE       = 10000
HS_FDS_FETCH_ROWS       = 100
HS_TRANSACTION_MODEL    = READ_ONLY

#This was supposed to fix ORA-02070: database MSAccessODBC64bit does not
#support TO_number in this context
#This didn't work
#EnableWCharSupport      = 0 

2 ответа

Решено! Службы Oracle HS и ODBC ограничены по объему и использованию в терминах операторов SQL, которые могут быть выполнены. Обходной путь должен использовать виртуальный пакет DBMS_HS_PASSTHROUGH. Это позволит вам отправлять запросы в удаленную базу данных, используя переменную pl/sql и переменные связывания. Пример ниже является заменой вышеуказанного кода.

Пример:

declare
   v_cursor           BINARY_INTEGER;
   my_record_position number := 1234;
   my_record          employees@MSAccessODBC64bit%rowtype;
   my_empid           employees.empid@MSAccessODBC64bit%type;
begin
   v_cursor := DBMS_HS_PASSTHROUGH.open_cursor@MSAccessODBC64bit;
   DBMS_HS_PASSTHROUGH.parse@MSAccessODBC64bit
      (
      v_cursor,
      'select * from employee where empid = ' || my_record_position 
      || 'order by empid asc'
      );
   WHILE DBMS_HS_PASSTHROUGH.fetch_row@MSAccessODBC64bit(v_cursor) > 0
   LOOP
      DBMS_HS_PASSTHROUGH.get_value@MSAccessODBC64bit(v_cursor, 1,my_record.empid);
      dbms_output.put_line('empid=' || my_record.empid);
   end loop;
end;
/

Ошибка указывает на то, что это сравнение -

staff_number = my_record_position

- сравнивает разнородные типы данных, что приводит к автоматической попытке запрашивающей СУБД преобразовать один или оба типа данных в типы данных, которые можно сравнивать. Например, вы не можете напрямую сравнить CHAR к NUMBER; один должен быть CAST к другому - который TO_NUMBER наводит на мысль, что происходит.

TO_NUMBER это специфичная для Oracle функция, которую Access не поддерживает. Вы, вероятно, можете обойти это, добавив пару CAST на ваш запрос, например -

CAST (staff_number AS INT) = CAST (my_record_position AS INT)

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

Другие вопросы по тегам