Do not call SYS.DBMS_SESSION.SET_NLS
with an instance of the [Archive.is] TOraStoredProc
Class, as under the hood, it will translate the call to 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)=''.,''
The above is a translation of the bold portions in this call (note it contains the an instantiation of an [Archive.is] TOraSession
Class as you need one; examples further down assume this session instance to exist):
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;
It will result in an Oracle error during the Prepare of the statement:
ORA-06550: line 2, column 36:
PLS-00103: Encountered the symbol ":" when expecting one of the following:
( - + case mod new not null
continue avg count current exists max min prior sql stddev
sum variance execute forall merge time timestamp interval
date pipe
In stead, take your TOraPackage
object and make a call like this:
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;
This then results in this in the SQL monitoring (note quoting quotes is different in SQL than Delphi):
Class:Ora.TOraSQL;Component:;Flag:tfQExecute,Text:begin
SYS.DBMS_SESSION.SET_NLS(:PARAM, :VALUE);
end;
:PARAM(VARCHAR[22],IN)='NLS_NUMERIC_CHARACTERS'
:VALUE(VARCHAR[4],IN)=''.,''
instead of 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)=''.,''
I am still a sort of baffled why this is a problem. But using the TOraPackage
works.
One thing to remember is that an TOraSession
instance does not allow you to get to the underlying TOCIConnection
instance, which does allow setting NLS information directly; see for instance the old code at [WayBack] OraClasses.pas in xinhaining-dianjianyiqi-tongxunchengxu | source code search engine.
This is because the underlying connection can be both OCI
and Direct
depending on the TOraSession.Options.Direct
value: [WayBack] About Connection.Ping method when Direct Mode – Devart Forums.
Other calls on SYS.DBMS_SESSION succeed
The odd thing is that single-parameter calls on SYS.DBMS_SESSION.SET_ROLE
(which can be tricky, see [WayBack] Introducing Database Security for Application Developers) work fine, so no alternative (like a plain [WayBack] SET ROLE) is needed:
var
DbmsSessionSetRoleOraStoredProc: TOraStoredProc;
begin
DbmsSessionSetRoleOraStoredProc := TOraStoredProc.Create(Self);
try
DbmsSessionSetRoleOraStoredProc.Name := 'DbmsSessionSetRoleOraStoredProc';
DbmsSessionSetRoleOraStoredProc.StoredProcName := 'SYS.DBMS_SESSION.SET_ROLE';
DbmsSessionSetRoleOraStoredProc.Session := dbSession;
with DbmsSessionSetRoleOraStoredProc.ParamData.Add do begin
DataType := ftString;
Name := 'ROLE_CMD';
ParamType := ptInput;
Value := 'EXAMPLE';
end;
DbmsSessionSetRoleOraStoredProc.ParamByName('ROLE_CMD').AsString := 'EXAMPLEROLE';
DbmsSessionSetRoleOraStoredProc.Prepare;
DbmsSessionSetRoleOraStoredProc.ExecProc;
finally
DbmsSessionSetRoleOraStoredProc.Free();
end;
end;
results in this log:
Class:Ora.TOraStoredProc;Component:StrdPSetRole;Flag:tfQExecute,Text:begin
SYS.DBMS_SESSION.SET_ROLE(:ROLE_CMD);
end;
:ROLE_CMD(VARCHAR[10],IN)='EXAMPLEROLE'
Similar for SYS.DBMS_APPLICATION_INFO
Calling anything on DBMS_APPLICATION_INFO gives you an exception.
On the .NET side of DevArt, you can use
–jeroen
Like this:
Like Loading...