Microsoft Tools Front-Ending ORACLE

Maggie Shapland, Computing Service, University of Bristol
email address: Maggie.Shapland@bristol.ac.uk

Introduction

This article discusses exchanging data between ORACLE, Access, Excel and Word. It gives optimisation tips and timing of various queries, and describes how to check check the statements being passed. It also gives a list of ORACLE error messages encountered.

At the University there are about 4000 PC, over 700 with Access installed (1250 with Excel). New users start with Access and transfer to Oracle if they have large databases, have complex applications, want to use C, or want to share their data. They are accustomed to the Microsoft tools and build their own applications, only calling for help at the design stage or if they get problems. They often fight shy of SQL despite the fact that Access has a very prominent SQL button.

I have installed Oracle on many PCs and several departmental Suns, and though these users are happy with SQL, they are not always too happy with SQL*FORMS 3, especially now they are used to a windows interface and tend to try to use a mouse by mistake. Many still only have 4Mb machines (or smaller), and upto 6 months ago there were not many 16Mb machines capable of running the ORACLE windows tools, so for reasons of a familiar interface plus machine constraints, ODBC provides a good solution. There is also a limit of how many packages I can support virtually single-handed and neither do I have the disk space to hold them.

Hardware and software requirements

It is possible for Microsoft Access and Excel to access ORACLE databases, as long as they have SQL*Net and the correct connectivity drivers loaded. I used:

Performance is slow on a 4Mb machine, so it is recommended that an 8Mb machine is used (performance increased 8 fold). I used a 4Dx33 with 16Mb and compressed disk.

Architecture

Two-tier system (Oracle. ODBC driver sends SQL directly to ORACLE):

Application (Access 15Mb disc space, min 4Mb memory)
|
ODBC Driver Manager (ODBC.DLL)
|
ORACLE Driver (SQORA.DLL)
|
ORACLE Call Interface (OCI) Layer (ORA6WIN.DLL)
|
SQL*NET TCP/IP For Windows Driver (SQLTCP.DLL, SQLTCP1.DLL)
|
Network Software (PC-NFS Winsock MPCNFS4.DLL)
|
SQL*Net Listener on remote machine
|
ORACLE Server

The Application provides an Application Program Interface (API) between client and Driver Manager

The ODBC Driver manager directs ODBC calls to the correct driver (ORACLE) using the Service Provider Interface (SPI)

The ORACLE Driver processes ODBC function calls, connects to the data source, translates SQL, retrieves the result set and returns it to the application

The OCI layer is the router (eg t for tcp/ip)

SQL*NET enables transfer of requests, data, status, errors and connects to the server using the tcp socket

The Network Software transports the data stream over the network

Note that Access can not be used as a front-end to an ORACLE database on your PC through ODBC because the DOS version is not a multi-task server

Setting up data sources from the ODBC Control Panel.

To add a data source to the ODBC Data Sources dialog box, its ODBC driver must already be installed on your machine.

The control string specifies the network details when logging in. The syntax for the connect_string for TCP/IP is:

net_prefix:hostname:system_id
where net_prefix is 't' for tcp/ip, 'b' for netbios, 'p' for named pipes, 'd' for DECNET, 's' for SPX; hostname is to be found in \NFS\HOSTS; and system_id is the name of the remote ORACLE database. The hostname can also give the IP address explicitly eg t:137.123.44:sid

The general syntax for running an application program from the command line is:

application username/pwd@connect_string
\windows\odbc.ini holds the information on each data source setup.

Using Microsoft Access with Oracle data.

There are 2 options to access Oracle data: create an external link or use import/export

Attaching data means that you are using an external link to the data at its source. Creating external links to Oracle tables keeps the Access view up-to-date, avoids duplication of data, and does not require extra storage space within the Access database. Attached tables are slower to access than locally stored tables, and their design can not be changed.

Depending on the data source, a bold right arrow and a symbol prefixes the name of the attached table. dBase tables show a bold 'dB', ORACLE tables a globe If you look at the design of the table and show the properties you can see the source of the table.

Editing and updating attached Oracle tables within Microsoft Access is very easy. The only condition is that the Oracle table must have a unique index. If this does not exist on the Oracle table, for example if you are looking at an Oracle view, then you can create a unique index within Access that Oracle is not aware of, by using a data-definition query.

Sending Access data to ORACLE

You can import and export data in a number of different database formats and from spreadsheets and text files. Downloading the tables enable more speedy access to the data but will become out-of-date in Access if subsequently modified in Oracle.

Note that if you use spaces in an Access field name and you are exporting to Word or ORACLE, that spaces will automatically be replaced by underscores.

Accessing Oracle data from Excel version 5

Sending Excel data to ORACLE

To embed an Excel object in another application, use Copy and Paste Special. This can not be used for ORACLE.

If you select Save As from the File menu, you will have to save in comma delimitered format to mailmerge into Word or import into ORACLE. Access can import Excel spreadsheets.

Accessing ORACLE data from Excel version 4

Use the QE.XLA add in, then from the Data menu choose Activate Q+E. You must then use SQL to construct your query.

Using Word For Windows with Oracle data

There is no ODBC link for Word For Windows 2. You can only insert Excel worksheets into a Word document. Use Copy and Paste Special between Microsoft applications. Access data has to be incorporated using mailmerge.

Word for Windows version 6 does provide an ODBC link

You will get a General Protection Fault if you try to insert ORACLE data with the Microsoft ODBC driver. This is a problem due to the Winsock driver and may be got round using PSNFS4 or 3rd party ODBC software.

Points to note:

Data Definition

Attaching an Oracle table to Access
Oracle type maps to Access type
number(1-4,0) number(integer)
number(5-9,0) number(long integer)
number(10-15,0) number(double)
number(16-38) text
number(1-15,n) number(double)
number(16-38) text
float number(double)
date date/time
char(n) text(n)
raw(n) binary(n)
long memo
longraw OLE object

Exporting an Access table to ORACLE

Access type maps to Oracle type
yes/no number(5,0)
number(byte) number(5,0)
number(integer) number(5,0)
number(long integer) number(10,0)
number(single) float
number(double) float
currency float
date/time date
counter number(10,0)
text(n) char(20)
memo long
OLE object long raw

If the conversion fails, the value is treated as null- which should not happen very often since Jet chooses text when no other Jet type has a large enough value range.

The list only includes those tables that the Oracle ID has access to. Oracle system (public) tables such as User_tables and Session_roles are also excluded unless the Show System Options box is ticked within the View/ Options menu. Trying to view the Oracle system tables in Access can cause an ODBC fail with the message: ORA-01741 - illegal zero-length identifier.

Data Entry

Queries

Updating

Access Basic

Security

Access and Excel deal with password security to external databases in opposite ways.

Microsoft Access provides a check box for the 'Save login ID and password locally' which is unchecked by default, but which the user can change, giving the potential consequence of NO security. Encrypting the database is another option to protect the passwords.

When you query ORACLE from Excel, you are taken into MS-QUERY, where you are asked for your ORACLE id and password. You then select the table(s) to query, and when you have the data you require, you then select 'Return data to Excel'.

The important thing is the next box which appears. By default, an item 'Keep query definition' is checked. If you leave this checked then the query definition, along with the information needed to re-connect to ORACLE, ie the userid and password, is saved with the spreadsheet.

This means that if you call up the sheet at some later date, and select 'Get external data', you will not be asked for your ORACLE id and password, and the query you used to select the data on the spreadsheet will be used to re-query the database. and enable you to update the data on the spreadsheet with the revised data in the database. The problem of course, is that it offers NO security.

The way to plug this loophole is to remember to uncheck the box marked 'Keep query definition' when you return the data to the spreadsheet. This will of course mean that when you wish to update the data, you will have to provide all the information (login id/password and query) again.

Locking and sharing data

Optimising performance

Access is optimised to return answers as quickly as possible; as soon as the first screenful of results is available it will be painted. Result sets are stored in memory. While you are inactive, the result set is populated in the background to allow faster operations when you become active again. You can control how quickly this idle-time population occurs using MSysConf described below. Automatic idle-time population does not apply to snapshots and dynaset objects in Access Basic- ORACLE may hold a lock on that row.

Config (2 byte integer not allowed null),
chValue (varchar 255),
nValue (4 byte integer)
Comments (varchar 255).
chValue and Comments are reserved for future use and contents ignored:

config nvalue meaning and effect
1010 do not allow local storage of login ID
1011 do allow local storage of login ID (default)
102ddelay in seconds between each chunk of results
(default 10). Increase will decrease network traffic
but increase read-lock time on server
103n number of rows to fetch (default 100)

The optimiser uses statistics based on number of records in a table, location, indexes etc. A query is compiled each time it is modified. If a significant number of rows have been added to your table since last compiled, it should be recompiled to update the statistics.

Snapshots and Dynasets

Microsoft distinguish between snapshots (query selects the selected columns of each qualifying row) and dynasets (query selects only the primary key columns of each qualifying row and must use a separate query to fetch the data. Thus data can be refreshed quickly with a dynaset, whereas a snapshot, which caches the entire data set cannot be refreshed except by complete reexecution of the query. A snapshot is a nonupdatable, unchanging view of the data and is obtained by changing the form's 'Allow Updating' property to "No tables" (or by not creating an ORACLE index)

The cache size for dynasets (not snapshots or pass-through queries) can be altered by CacheStart, CacheSize, FillCache properties).

Pass-through queries are populated on demand as rows are requested for faster ope and less traffic.

Asynchronous Queries

JET executes ODBC queries asynchronously (The ODBC driver returns control back to the application while the function is still executing). Access makes full use of this facility because it brings back a couple of screenfulls and then enables the execution to be cancelled, or switch to another Windows task. JET asks the server if the query is finished every M millisceconds (500 by default, is changed by altering AsyncRetryInterval in msaccess.ini)

JET will automatically cancel a long-running query after a default time of 60 seconds (QueryTimeout in msaccess.ini, or ODBC Timeout propery of an individual query)

Queries

Forms

Local Processing

The SQL that Jet sends to an ODBC driver is generated according to the SQL grammar defined by ODBC. This is then translated into the appropriate server SQL

Example VICTIM------->>FRACTURE

ORACLE: select victim.* from victim,fracture
where victim.vno=fracture.vno(+)

ORACLE: select assault_district,count(vno) "row summary",
sum(decode(sex,'m',1,0)) m,sum(decode(sex,'f',1,0)) f
from victim
group by assault_district

Timing

The same 10 column table was opened in datasheet mode from the Table icon when it was stored locally and attached remotely. The time (in seconds) was taken from pressing the icon to showing the first 12 records. Note that once the table has been accessed that it is quicker to open it again in the session. Note also the difference on a 4Mb machine if network software is in memory. Thus, it is advisable to only include RTM and RNMNIS if attaching files over the network, particularly when using a smaller machine.

Operation540 Row Table
local Sun
4Mb 4Mb
+nw
8Mb 8Mb
+nw
16Mb 4Mb 8Mb 16Mb
open table8 172221001512
again48 <1 <1 <1 4542
serial search 917 <1 <1 <1 145325
create and open
10 field form
6010015153 377154

The following operations aim to compare timing carried out on large tables both remotely and locally. The times shown (in seconds) are to show the first page of results when run from the design so also includes compile time and when Windows has been restarted. I also show performance monitor (FASTQ.MDA) lapsed time but it was not always consistent. A pass-through query takes 10 seconds to connect and login (this was not included in the following results).

Operation 20206 Row Table 540 Row Table
remotelocal remotelocal
import (from)60060
attach25n/a25n/a
open 93123
to end 801451
find on p key901251
find on index >90025502
find on all fields >90010513027
null on non-index field231272
create+open form7343
open master-detail form14551
-do-with 152 row listbox 185
create+open report 9585
order icon on index22040
order icon on nonindex 221041

Operation 20206 row table
remote local
runrestart perfor passthru runrestperf
order SQL on index (dyn) 1726404510
-do- omit pkey (snap) 22433510
order SQL on nonindex 175539341218
-do- omit p key 22533917
search= p.key 190110
search=index all col 2100110
search=index 2 col 2101210
search=non-index all col 14175520
search=non-index 2 col 175620
index between 2101210
index like 'A%' 3112210
index like '%y' 6205220
> 4202210
> nonindex 91654213
not in 4133210
max pkey 180110
max nonindex 60117
max index 61245110
count(*) 4137411
outer join with local 647061n/a574
outer join with remote 455238n/a334231
not exists with local 5123n/a330
not exists with remote 82174>600>609
inner join with local 505950n/a120
inner join with remote 202219n/a283524
equals with local 506049n/a574
equals with remote 4053554172517
graph 51---83-
crosstab 626959122521
group by 1218991310
iif 4133210

The joins were performed with a 6021 row table.

Effect of MSysConf

I used equijoin (result 6049 rows) and not exists (result 14173 rows), both dynasets

delay records retrieved
10,1001,500
equals first page4242
equals last page4242
not exists first page1010
not exists last page4235

Debugging

1. To see SQL statements sent to an ODBC data source

Microsoft Jet engine traces and records the Access Basic function and the SQL statements sent to an ODBC source in ACCESS\SQLOUT.TXT. This file is never overwritten, so do not leave tracing on indefinitely

SQLAllocEnv(phenv5F3F0000);
SQLAllocConnect(henv5F3F0000, phdbc52770000);
SQLSetConnectOption(hdbc52770000, 103, 00000014);
SQLDriverConnect(hdbc52770000, hwnd3CB8, "DSN=cse;DBQ=T:sun:sid;UID=SCOTT;PWD=*****", 41, szConnStrOut, 0, pcbConnStrOut, 0);
SQLGetInfo(hdbc52770000, 9, rgbInfoValue, 2, pcbInfoValue);
SQLGetInfo(hdbc52770000, 6, rgbInfoValue, 100, pcbInfoValue);
:
SQLGetStmtOption(hstmt57A70000, 4, pvParam);
SQLSetStmtOption(hstmt57A70000, 4, 00000001);
SQLError(henv5F3F0000, hdbc52770000, hstmt57A70000, szSqlState, pfNativeError, szErrorMsg, 8192, pcbErrorMsg);
SQLError(henv5F3F0000, hdbc52770000, hstmt57A70000, szSqlState, pfNativeError, szErrorMsg, 8133, pcbErrorMsg);
SQLExecDirect(hstmt57A70000, "SELECT Config, nValue FROM MSysConf", -3);
SQLError(henv5F3F0000, hdbc52770000, hstmt57A70000, szSqlState, pfNativeError, szErrorMsg, 8192, pcbErrorMsg);
:
SQLExecDirect(hstmt57A70000,"SELECT DEPTNO,DNAME,LOC FROM SCOTT.DEPT",-3);
SQLFetch(hstmt57A70000);
SQLGetData(hstmt57A70000, 1, 5, rgbValue, 256, pcbValue);
SQLGetData(hstmt57A70000, 2, 1, rgbValue, 256, pcbValue);
SQLGetData(hstmt57A70000, 3, 1, rgbValue, 256, pcbValue);
SQLFetch(hstmt57A70000);
SQLGetData(hstmt57A70000, 1, 5, rgbValue, 256, pcbValue);
SQLGetData(hstmt57A70000, 2, 1, rgbValue, 256, pcbValue);
SQLGetData(hstmt57A70000, 3, 1, rgbValue, 256, pcbValue);
:
SQLFreeStmt(hstmt57A70000, 0);
SQLFreeStmt(hstmt57A70000, 1);
SQLDisconnect(hdbc52770000);
SQLFreeConnect(hdbc52770000);
SQLFreeEnv(henv5F3F0000);

2. To trace calls to ODBC functions:

output will go into SQL.LOG by default

Error numbers are all user-defined (given in ODBC Programmers Handbook)

SQLExecDirect: SELECT Config, nValue FROM MSysConf
SQLExecDirect: SELECT DEPTNO ,DNAME ,LOC FROM SCOTT.DEPT

3. To see what Oracle does

or

The last gives briefer output (still pretty long!) and shows the SQL that Oracle tries to do with any error messages

Output sent to ORAWIN\TCPNNN.NNN
osntra recv 26 bytes:
00 16 01 00 01 02 01 00 |........|
49 42 4d 50 43 2f 4d 53 |IBMPC/MS|
44 4f 53 2d 36 2e 30 2e |DOS-6.0.|
30 00 00 00 00 00 00 00 |0.......|
osntra recv 36 bytes:
00 20 01 00 01 02 00 53 |. .....S|
75 6e 2d 53 50 41 52 43 |un-SPARC|
2f 53 75 6e 4f 53 2d 34 |/SunOS-4|
2e 30 2e 78 2d 36 2e 30 |.0.x-6.0|
2e 32 39 00 00 00 00 00 |.29.....|
:
53 43 4f 54 54 2f 74 69 |SCOTT/ti|
67 65 72 4d 53 2d 57 49 |gerMS-WI|
4e 44 4f 57 53 20 50 43 |NDOWS PC|
4f 72 61 55 73 65 72 31 |OraUser1|
32 34 36 33 3a 30 31 44 |2463:01D|
3a 5c 57 49 4e 44 4f 57 |:\WINDOW|
53 5c 73 79 73 74 65 6d |S\system|
5c 4b 52 4e 4c 33 38 36 |\KRNL386|
2e 45 58 45 00 00 00 00 |.EXE....|
:
osntra recv 39 bytes:
00 23 01 00 03 03 05 01 |.#......|
01 01 01 1b 53 45 4c 45 |....SELE|
43 54 20 2a 20 46 52 4f |CT * FRO|
4d 20 53 45 53 53 49 4f |M SESSIO|
4e 5f 52 4f 4c 45 53 00 |N_ROLES.|
osntra recv 72 bytes:
00 44 01 00 04 00 02 03 |.D......|
ae 00 00 01 01 01 0e 00 |........|
02 00 00 00 00 00 00 00 |........|
00 00 00 00 05 00 00 28 |.......(|
4f 52 41 2d 30 30 39 34 |ORA-0094|
32 3a 20 74 61 62 6c 65 |2: table|
20 6f 72 20 76 69 65 77 | or view|
20 64 6f 65 73 20 6e 6f | does no|
74 20 65 78 69 73 74 0a |t exist.|
:
osntra recv 47 bytes:
00 2b 01 00 03 03 0a 01 |.+......|
01 01 01 23 53 45 4c 45 |...#SELE|
43 54 20 43 6f 6e 66 69 |CT Confi|
67 2c 20 6e 56 61 6c 75 |g, nValu|
65 20 46 52 4f 4d 20 4d |e FROM M|
53 79 73 43 6f 6e 66 00 |SysConf.|
osntra recv 72 bytes:
00 44 01 00 04 00 02 03 |.D......|
ae 00 00 01 01 01 1b 00 |........|
02 00 00 00 00 00 00 00 |........|
00 00 00 00 0a 00 00 28 |.......(|
4f 52 41 2d 30 30 39 34 |ORA-0094|
32 3a 20 74 61 62 6c 65 |2: table|
20 6f 72 20 76 69 65 77 | or view|
20 64 6f 65 73 20 6e 6f | does no|
74 20 65 78 69 73 74 0a |t exist.|
:
osntra recv 63 bytes:
00 3b 01 00 04 00 02 03 |.;......|
eb 00 00 01 01 01 1b 03 |........|
02 00 00 01 00 00 00 00 |........|
00 00 00 00 0b 00 00 1f |........|
4f 52 41 2d 30 31 30 30 |ORA-0100|
33 3a 20 6e 6f 20 73 74 |3: no st|
61 74 65 6d 65 6e 74 20 |atement |
70 61 72 73 65 64 0a 00 |parsed..|
:
osntra recv 55 bytes:
00 33 01 00 03 03 10 01 |.3......|
01 01 01 2b 53 45 4c 45 |...+SELE|
43 54 20 44 45 50 54 4e |CT DEPTN|
4f 20 2c 44 4e 41 4d 45 |O ,DNAME|
20 2c 4c 4f 43 20 20 46 | ,LOC F|
52 4f 4d 20 53 43 4f 54 |ROM SCOT|
54 2e 44 45 50 54 20 00 |T.DEPT .|
:
osntra recv 203 bytes:
00 c7 01 00 06 02 03 00 |........|
02 03 4c 01 30 03 05 2a |..L.0..*|
00 00 00 e7 68 00 00 df |....h...|
68 00 00 d7 68 03 05 10 |h...h...|
00 00 00 cf 68 00 00 c7 |....h...|
68 00 00 bf 68 03 05 0f |h...h...|
00 00 00 b7 68 00 00 af |....h...|
68 00 00 a7 68 07 02 31 |h...h..1|
30 00 0a 41 43 43 4f 55 |0..ACCOU|
4e 54 49 4e 47 00 08 4e |NTING..N|
45 57 20 59 4f 52 4b 00 |EW YORK.|
07 02 32 30 00 08 52 45 |..20..RE|
53 45 41 52 43 48 00 06 |SEARCH..|
44 41 4c 4c 41 53 00 07 |DALLAS..|
02 33 30 00 05 53 41 4c |.30..SAL|
45 53 00 07 43 48 49 43 |ES..CHIC|
41 47 4f 00 07 02 34 30 |AGO...40|
00 0a 4f 50 45 52 41 54 |..OPERAT|
49 4f 4e 53 00 06 42 4f |IONS..BO|
53 54 4f 4e 00 07 02 39 |STON...9|

Installation files and machine settings

Use the Access Add-in manager to uninstall wizards, builders and other unwanted add-ins to reduce memory consumption. Avoid running large applications such as Word, ECSMAIL, Excel at the same time as Access to avoid using memory particularly on a 4Mb machine.

Make sure windows virtual memory swap file setting plus available RAM is not less than 25 MB (defragment and delete unwanted files). Access requires a minumum of 6Mb RAM.

Use 32 bit access (set from 386 Enhanced icon on the Control Panel)- had little effect

oracle.ini

[ORACLE]
ORACLE_HOME=C:\ORAWIN
NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1
TCP_VENDOR=WINSOCK
TCP_SERVICES_FILE=C:\NFS\SERVICES
RDBMS70=C:\ORAWIN\RDBMS70
PRO15=C:\ORAWIN\PRO15
TCP_HOSTS_FILE=C:\NFS\HOSTS

win.ini (The following lines are added by the SQL*NET TCP/IP installer:)
[ORACLE]
ORA_CONFIG=D:\WINDOWS\ORACLE.INI

config.sys (The following lines are altered by you if necessary:)

FILES=60
BUFFERS=40
BREAK=ON

win.bat (to keep the autoexec.bat file clean:)

ECHO OFF
CALL C:\BAT\PUSHENV
PATH %PATH%;D:\ACCESS;C:\ORAWIN\BIN
C:\BIN\SHARE.EXE /L:500
D:\WINDOWS\SMARTDRV.EXE
C:\NFS\RTM {not needed with PCNFSPRO
c:\NFS\rnmnis {not needed with PCNFSPRO
set config=D:\windows\ORACLE.INI
D:\WINDOWS\WIN %1 %2
c:\NFS\rnmnis /u
C:\NFS\RTM /U
C:\BAT\POPENV

nfs\services (The following line is added:)

ORASRV 1525/TCP

Add a space and a carriage return to the end of the orasrv entry to avoid SQL*NET incorrectly parsing the SERVICES file

nfs\hosts

137.222.12.33 mjs
137.222.12.1 x

An example of what might be in this file. It does not need to be changed. x is the name of the computer on the network, mjs is my unique name as a user of the network.

msaccess.ini

[ODBC]
QueryTimeout=100
LoginTimeout=100
TraceSQLMode=1
[ISAM]
MaxBuffersize=4096 (2048 if 8Mb, 512 if 4Mb. default 512)

Other ini files of interest: ODBC.INI; ODBCINST.INI; ODBCISAM.INI; MSQUERY.INI; VSL.INI; PCNFSWIN.INI

ORACLE error messages

The following section explains what to do when you encounter various error messages from ORACLE Server through the ODBC ORACLE driver. ORACLE RDBMS Error Messages and codes Manual gives details of error codes and course of action, but the following numbers are not listed. Typing on the sun:

oerr ora nnnn

where nnnn is the error code also gives details of ORACLE error numbers.

* ORA-0942 could not execute table, could not find linked table, table or view does not exist

* ORA-1002 Fetch out of sequence

* ORA-1017 Invalid username and passwd

* ORA-3114 not connected to ORACLE

* ORA-03121 No interface driver connected -- function not performed

* ORA-6105 NETTCP: remote host is unknown (or driver not capable)

* ORA-6106 NETTCP: socket creation failure

* ORA-6107 NETTCP: ORACLE network server not found

* ORA-6108 NETTCP: connect to host failed

* ORA-6114 NETTCP: lookup failure

* ORA-06120 NETTCP: network driver not loaded

* ORA-6122 Connection setup failure

* ORA-6136 NETTCP error during connection handshake

* ORA-9124

* ORA-9241 Message not found; product = RDBMS; facility = ORA; language = NULL

* ORA-9301 Local kernel only supported in standard mode

ODBC error messages

The following section explains what to do when you encounter various ODBC error messages.

* Unknown string resource

* IM003 Driver specified by data source could not be loaded

* ODBC.DLL Data source not found and no default driver specified