1

I am using Oracle's Heterogeneous Services (HS). I have a database link to a Microsoft Access table called employee. From an Oracle connection using SQL*Plus, I can describe the table's columns and datatypes (desc employee). I can also select from the remote table and receive the records.

However, when using an anonymous block, I receive the Oracle error:

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

MSAccessODBC64 is my configured ODBC DSN in Windows 7.

The code:

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;
/

The error:

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

Is there some sort of issue or option required to make HS work? What am I overlooking?

When I use a substitution variable, it works and displays the employee id.

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 
TallTed
  • 9,069
  • 2
  • 22
  • 37
steve4321
  • 33
  • 1
  • 9
  • What happens if you comment out the `dbms_output.put_line` call? Also, what's with the error at the end which mentions `AMGBASETABLES64`? – Bob Jarvis - Слава Україні Jan 03 '17 at 00:38
  • Hi Bob, The dms_output.put_line works fine. The problem is with the HS and ODBC driver. That's the ODBC's dsn. I have to edit the question. It should have stated MSAccessODBC64bit. – steve4321 Jan 03 '17 at 01:04
  • When I use a substitution variable, it works fine. However, I cannot use a substitution variable in this algorithm. I need to use either a bind variable or a declared pl/sql variable. – steve4321 Jan 03 '17 at 01:28
  • Your second example is reading the table `employees` which is (apparently) not on the remote database. What happens if you change the second example to read from `employee@MSAccessODBC64bit`? – Bob Jarvis - Слава Україні Jan 03 '17 at 01:39
  • Hi Bob, I just fixed that... It works with the remote database when using a substitution variable. It will not work when using a pl/sql declared variable or bind variable. – steve4321 Jan 03 '17 at 01:41
  • Some other the other threads on this topic seem to point to writing data to the remote database. I'm only reading from the remote database, so that those threads don't seem to fit this issue with Heterogeneous Services and ODBC. – steve4321 Jan 03 '17 at 01:51
  • What's the data type of `staff_number` in the Access database? – Bob Jarvis - Слава Україні Jan 03 '17 at 02:52
  • Hi Bob, Thanks for the quick responses. The data type for STAFF_NUMBER is NUMBER(10) in the Access database. If I change the where clause to staff_number = 1234 (a constant) it works. If I change the where clause to staff_number = to_number('1234'), it works. But when I change the where clause to use a pl/sql variable or bind variable it fails with ORA-02070. Is it possible this is a bug with HS and ODBC? – steve4321 Jan 03 '17 at 03:24
  • I added the HS parameters to the code above. – steve4321 Jan 03 '17 at 03:43
  • I'm trying to figure out why a `TO_NUMBER` call would be inserted into the SQL passed to the ODBC database, so I was hoping knowing the column data type would help. At this point I'm fresh out of ideas - except...can you turn this block into a procedure and then call the procedure? As far as it being a bug - anything is possible, but I know from long experience that any time I think I've found a bug I'm usually right - except that the bug is usually in my thinking, not in the product. :-) (I've found two provable bugs in software over 40+ years. Not too shabby, if I do say so myself... :-) – Bob Jarvis - Слава Україні Jan 03 '17 at 04:02
  • Hi Bob, Yeah, this one's a stumper! However, I found a thread on another site that recommended using the DMBS_HS_Passthrough package. I tried it out, and it seems to work. Its takes a bit more coding, but it supports the database link and where clause. https://www.experts-exchange.com/articles/9850/Configuring-and-using-Oracle-Database-Gateway-for-ODBC.html – steve4321 Jan 03 '17 at 04:18
  • Bob, I'm going to tweak the code and post in the morning...thanks for your help. – steve4321 Jan 03 '17 at 04:19

2 Answers2

1

Solved! The HS and ODBC Oracle services are limited in scope and usage in terms of cursor sql statements that can be performed. The workaround is to use the virtual DBMS_HS_PASSTHROUGH package. This will allow you to submit queries to the remote database using pl/sql variable and bind variables. The example below is a replacement for the above code.

Example:

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;
/
steve4321
  • 33
  • 1
  • 9
0

The error indicates that this comparison --

staff_number = my_record_position

-- is comparing disparate data types, which leads to an automatic attempt by the querying DBMS to convert one or both to data types which may be compared. For instance, you cannot directly compare a CHAR to a NUMBER; one must be CAST to the other -- which the TO_NUMBER suggests is happening.

TO_NUMBER is an Oracle-specific function, which Access doesn't support. You can probably get around this by adding a couple of CASTs to your query, e.g. --

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

This adds a bit of unnecessary overhead if either is already an INT, but that may not matter for your use.

TallTed
  • 9,069
  • 2
  • 22
  • 37
  • Hi TallTed, Thanks for response, but both variables are of datatype NUMBER. Yes, the issue is with the comparison line, but the HS and ODBC service is SNAFU'd for some unknown reason. I solved the issue by using the virtual package DBMS_HS_PASSTHROUGH package. See the above answer that I just posted and the link. https://www.experts-exchange.com/articles/9850/Configuring-and-using-Oracle-Database-Gateway-for-ODBC.html – steve4321 Jan 03 '17 at 17:24