I got this when taking over maintenance of some legacy code that called a stored procedure in a :
--------------------------- Debugger Exception Notification --------------------------- Project LegacyProject.exe raised exception class Exception with message 'Need Oracle 8 Call Interface'. --------------------------- Break Continue Help ---------------------------
The problem with finding more information about this, is that there are virtual no hits on Oracle 8 Call Interface, OCI 8 or Oracle Call Interface 8.
A good document is [WayBack] OCI: Introduction and Upgrading (found via [Archive.is] “OCI 7” – Google Search), but it never mentions 8, only these terms occur:
- release 7.x OCI
- OCI release 7
- OCI version 7
- Oracle release 7 OCI
- Release 8.0 of the OCI
- 7.x OCI
- Later OCI
- Post-release 7.x OCI
The error happens on the first instance of at least an [Archive.is] TOraStoredProc
Class or [Archive.is] TOraPackage Class
that prepares or executes a stored procedure.
One problem is that this is an instance of a plain [WayBack] Exception Class , not a [WayBack] EDatabaseError Class or [Archive.is] EDAError
Class.
What it means is that the UseOCI7
sub-property was set to True
in your TOraSession
property Options
:
- [Archive.is] TOraSession Class
- [Archive.is] TOraSession.Options Property
- [Archive.is] TOraSessionOptions.UseOCI7 Property
var MainOraSession: TOraSession; begin MainOraSession := TOraSession.Create(Self); MainOraSession.Name := 'MainOraSession'; MainOraSession.Username := 'ExammpleUser'; MainOraSession.Server := 'ExampleTnsName'; MainOraSession.LoginPrompt := False; MainOraSession.Options.UseOCI7 := True;
One thing to remember is that an
TOraSession
instance does not allow you to get to the underlyingTOCIConnection
instance, which does allow setting NLS information directly; see for instance the error at [WayBack] Not connected to oracle error – Devart Forums and old code at [WayBack] OraClasses.pas … | source code search engine and [WayBack] Ora.pas in … | source code search engine; UniDac is relatively similar [WayBack] UniDAC v3.7 …:OraClassesUni.pas (another explanation is in [WayBack] Setting the Client Info for the TOraAlerter extra session – Devart Forums).This is because the underlying connection can be both
OCI
andDirect
depending on theTOraSession.Options.Direct
value: [WayBack] About Connection.Ping method when Direct Mode – Devart Forums.
After the first occurrence, you will not get this error again, you get way more spurious errors, especially on stored procedures in packages, where the stored procedure has 2 or more parameters. There you get errors like this one for TOraStoredProc
:
ORA-06550: line 2, column 36: PLS-00103: Encountered the symbol ":" when expecting one of the following: ( - + case mod new not null <an identifier> <a double-quoted delimited-identifier> <a bind variable> continue avg count current exists max min prior sql stddev sum variance execute forall merge time timestamp interval date <a string literal with character set specification> <a number> <a single-quoted SQL string> pipe <an alternatively-quoted string literal with character set speci.
When logging using a [Archive.is] TOraSQLMonitor
Class instance (use the [Archive.is] TCustomDASQLMonitor.OnSQL
Event with the [Archive.is] TOnSQLEvent
Procedure Reference signature) you can get the underlying information of the TOraStoredProc
(see the example code below that raises this):
Class:Ora.TOraStoredProc;Component:sprSetNls;Flag:tfQPrepare,Text:Prepare: begin SYS.DBMS_SESSION.SET_NLS(:PARAM, :VALUE); end; :PARAM(VARCHAR[22],IN)='NLS_NUMERIC_CHARACTERS' :VALUE(VARCHAR[4],IN)=''.,''
It fails equally when doing any DBMS_APPLICATION_INFO
calls, for which the .NET version of ODAC has a special [WayBack] SetDbmsApplicationInfo Method in the [WayBack] OracleConnection Class. Too bad the Delphi version omits that.
When using TOraPackage
, you can get different errors, like for instance this EDatabaseError
:
Exception class EDatabaseError with message 'Parameter 'VALUE' not found'.
It basically means that through OCI, the parameter list could not be obtained, so the error is caught on the Delphi side instead of the Oracle side.
Using a TOraPackage
is easier at design time, as it allows you to select the [Archive.is] TOraPackage.PackageName
Property property using the underlying TOraSession
. Somehow a TOraStoredProc
does not allow you to select the [Archive.is] TOraStoredProc.StoredProcName
Property at design time.
Related:
- [WayBack] Huz’s Website – Easy Software: EZDML is a small tool which helps you to create data models quickly. It’s simple and fast, with EZDML you can create a table within few seconds.
- [WayBack] Introducing the Oracle Call Interface
- “Need Oracle 8 Call Interface” – Google Search
–jeroen
Example code that raises the ORA-06550
/PLS-00103
combo
Full code (since you need a session too):
var MainOraSession: TOraSession; DbmsSessionSetNlsOraStoredProc: TOraStoredProc; begin MainOraSession := TOraSession.Create(Self); try MainOraSession.Name := 'MainOraSession'; MainOraSession.Username := 'FOO'; MainOraSession.Server := 'BAR'; MainOraSession.LoginPrompt := False; MainOraSession.Options.UseOCI7 := True; MainOraSession.Open(); DbmsSessionSetNlsOraStoredProc := TOraStoredProc.Create(Self); try DbmsSessionSetNlsOraStoredProc.Name := 'DbmsSessionSetNlsOraStoredProc'; DbmsSessionSetNlsOraStoredProc.StoredProcName := 'SYS.DBMS_SESSION.SET_NLS'; DbmsSessionSetNlsOraStoredProc.Session := MainOraSession; DbmsSessionSetNlsOraStoredProc.Debug := True; with DbmsSessionSetNlsOraStoredProc.ParamData.Add do begin DataType := ftString; Name := 'PARAM'; ParamType := ptInput; Value := nil; end; with DbmsSessionSetNlsOraStoredProc.ParamData.Add do begin DataType := ftString; Name := 'VALUE'; ParamType := ptInput; Value := nil; end; DbmsSessionSetNlsOraStoredProc.ParamByName('PARAM').AsString := sParam; DbmsSessionSetNlsOraStoredProc.ParamByName('VALUE').AsString := sValue; DbmsSessionSetNlsOraStoredProc.Prepare(); DbmsSessionSetNlsOraStoredProc.ExecProc(); finally DbmsSessionSetNlsOraStoredProc.Free(); end; finally MainOraSession(); end; end;
The below code (add a similar session) will also crash, but with a different error Exception class EDatabaseError with message 'Parameter 'VALUE' not found'.
:
var DbmsSessionOraPackage: TOraPackage; begin DbmsSessionOraPackage := TOraPackage.Create(Self); try DbmsSessionOraPackage.Name := 'DbmsSessionOraPackage'; DbmsSessionOraPackage.Debug := True; DbmsSessionOraPackage.Session := dbSession; DbmsSessionOraPackage.PackageName := 'SYS.DBMS_SESSION'; DbmsSessionOraPackage.ExecProcEx('SET_NLS', ['PARAM', 'NLS_NUMERIC_CHARACTERS', 'VALUE', '''.,''']); finally DbmsSessionOraPackage.Free(); end; end;
Using TOraSqlMonitor
The below piece of code saved me way too many times; just define EnableTOraSqlMonitor
to enable it.
If you want you can output to [Archive.is] DBMonitor instead of using [WayBack]OutputDebugString
.
- [Archive.is] TDATraceFlag Enumeration
- [Archive.is] TMonitorOption Enumeration
- [WayBack] TOraSession.Debug Property
procedure TSessionDataModule.DataModuleCreate(Sender: TObject); begin {$ifdef EnableTOraSqlMonitor} FOraSQLMonitor := TOraSQLMonitor.Create(Self); FOraSQLMonitor.Name := Name + '_OraSQLMonitor'; FOraSQLMonitor.TraceFlags := [tfQPrepare, tfQExecute, tfQFetch, tfError, tfStmt, tfConnect, tfTransact, tfBlob, tfService, tfMisc, tfParams, tfObjDestroy, tfPool]; FOraSQLMonitor.OnSQL := OraSQLMonitor_OnSQL; {$endif EnableTOraSqlMonitor} end; procedure TSessionDataModule.DataModuleDestroy(Sender: TObject); begin {$ifdef EnableTOraSqlMonitor} FOraSQLMonitor.Free(); FOraSQLMonitor := nil; {$endif EnableTOraSqlMonitor} end; procedure TSessionDataModule.OraSQLMonitor_OnSQL(Sender: TObject; Text: string; Flag: TDATraceFlag); var Name: string; Line: string; begin // https://www.devart.com/sdac/docs/devart.dac.tdatraceflag.htm // TDATraceFlag = (tfQPrepare, tfQExecute, tfQFetch, tfError, tfStmt, tfConnect, tfTransact, tfBlob, tfService, tfMisc, tfParams, tfObjDestroy, tfPool); if Assigned(Sender) then begin Name := Sender.QualifiedClassName; if Sender is TComponent then Name := Format('%s;Component:%s', [Name, TComponent(Sender).Name]); end else Name := 'nil'; Line := Format('Class:%s;Flag:%s,Text:%s', [Name, TEnum.GetName(Flag), Text]); OutputDebugString(PChar(Line)); end;
For my own reference: [WayBack] How to set OCI Unicode environment use in 9.2.5? – Devart Forums
Please send me results of the following queries:
CODE: SELECT ALL
SELECT USERENV ('language') from dual; SELECT * FROM V$NLS_PARAMETERS;
and:
- [Archive.is] ODAC for Delphi – Components List
- [Archive.is] Unicode Character Data
- [WayBack] Oracle Package Wizard
- [Archive.is] Working With Oracle Stored Procedures
- [Archive.is] Stored Procedures – General Information
- [Archive.is] Using Stored Procedures via the TOraStoredProc Class
- [Archive.is] Using Package Procedures
- [Archive.is] Deployment
–end–