We turned Paramcheck off to resolve the above error. I then found TSQLStoredProc wasn't returning string ptOutput parameters. Number parameters were fine.
ptInputOutput had the same issue, Further research found assigning a string value to the parameter, even the ptOutput one, before executing the proc, caused it to return twice as many characters as supplied. If the value property on the parameter is set at design time I get that many +1 characters back.
Our workaround was to just supply as many characters as we expected to get back at most. Not really handy.
On this demo I use a tnsname to test. The button click creates a dynamic stored proc, which works as expected. Then it sets the param values on the fixed proc with paramcheck turned off.
The output is
dbcodeOpen Connection
Create Dynamic StoredProc
Open dynamic StoredProc
Dynamic Proc pAge = 23
Dynamic Proc pOutName = MyNameIsBob
Dynamic Proc pInOutName = MyNameIsBob
Open fixed StoredProc
fixed Proc pAge = 23
fixed Proc pOutName = MyN
fixed Proc pInOutName = MyName
Code: Select all
CREATE TABLE BOB(
Age NUMBER(4),
Name VARCHAR2(100)
);
Insert Into Bob Values (23,'MyNameIsBob');
Commit;
CREATE OR REPLACE PROCEDURE BobDetailGet
(
pName IN Bob.Name%TYPE,
pAge OUT Bob.Age%TYPE,
pOutName OUT Bob.Name%TYPE,
pInOutName IN OUT Bob.Name%TYPE
)
AS
BEGIN
SELECT Age, Name, Name
INTO pAge,pOutName,pInOutName
FROM Bob
WHERE Name = pName;
END;
/
Code: Select all
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 299
ClientWidth = 635
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Memo1: TMemo
Left = 280
Top = 40
Width = 313
Height = 225
Lines.Strings = (
'Memo1')
TabOrder = 0
end
object btnGetUserDetail: TButton
Left = 64
Top = 79
Width = 89
Height = 25
Caption = 'btnGetUserDetail'
TabOrder = 1
OnClick = btnGetUserDetailClick
end
object sqlConn: TSQLConnection
ConnectionName = 'Devart Oracle'
DriverName = 'DevartOracle'
LoginPrompt = False
Params.Strings = (
'DataBase=wwn3136'
'UseQuoteChar=False'
'DriverName=DevartOracle'
'Password=password1'
'Oracle TransIsolation=ReadCommitted'
'User_Name=envision'
'LongStrings=True'
'EnableBCD=False'
'FetchAll=False'
'UseUnicode=False'
'UnicodeEnvironment=False')
Connected = True
Left = 40
Top = 16
end
object sprBobDetailGet: TSQLStoredProc
MaxBlobSize = -1
ParamCheck = False
Params = <
item
DataType = ftWideString
Precision = 2000
Name = 'PNAME'
ParamType = ptInput
end
item
DataType = ftFMTBcd
Precision = 34
Name = 'PAGE'
ParamType = ptOutput
Size = 34
end
item
DataType = ftString
Precision = 2000
Name = 'POUTNAME'
ParamType = ptOutput
Size = 2000
Value = 'aw'
end
item
DataType = ftWideString
Precision = 2000
Name = 'PINOUTNAME'
ParamType = ptInputOutput
Size = 2000
end>
SQLConnection = sqlConn
StoredProcName = 'BobDetailGet'
Left = 144
Top = 16
end
end
Code: Select all
unit testproc;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, DBXDevartOracle, Data.FMTBcd,
Vcl.StdCtrls, Data.SqlExpr, Data.DB;
type
TForm1 = class(TForm)
sqlConn: TSQLConnection;
Memo1: TMemo;
btnGetUserDetail: TButton;
sprBobDetailGet: TSQLStoredProc;
procedure btnGetUserDetailClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btnGetUserDetailClick(Sender: TObject);
var
proc: TSQLStoredProc;
param: TParam;
begin
memo1.Lines.Clear;
memo1.Lines.Add('Open Connection');
SQLConn.Open;
memo1.Lines.Add('Create Dynamic StoredProc');
proc := TSQLStoredProc.Create(nil);
try
proc.SQLConnection := SQLConn;
proc.StoredProcName := 'BobDetailGet';
memo1.Lines.Add('Open dynamic StoredProc');
try
proc.ParamByName('pName').AsString := 'MyNameIsBob';
proc.ExecProc;
param := proc.ParamByName('pAge');
memo1.Lines.Add('Dynamic Proc pAge = '+param.AsString);
param := proc.ParamByName('pOutName');
memo1.Lines.Add('Dynamic Proc pOutName = '+param.AsString);
param := proc.ParamByName('pInOutName');
memo1.Lines.Add('Dynamic Proc pInOutName = '+param.AsString);
except
on e:exception do begin
Memo1.Lines.Add('Exception: '+e.Message);
end;
end;
finally
FreeAndNil(Proc);
end;
memo1.Lines.Add('Open fixed StoredProc');
try
sprBobDetailGet.ParamByName('pName').AsString := 'MyNameIsBob';
// sprBobDetailGet.ParamByName('pOutName').AsString := 'ab';
sprBobDetailGet.ParamByName('pInOutName').AsString := 'aw';
sprBobDetailGet.ExecProc;
param := sprBobDetailGet.ParamByName('pAge');
memo1.Lines.Add('fixed Proc pAge = '+param.AsString);
param := sprBobDetailGet.ParamByName('pOutName');
memo1.Lines.Add('fixed Proc pOutName = '+param.AsString);
param := sprBobDetailGet.ParamByName('pInOutName');
memo1.Lines.Add('fixed Proc pInOutName = '+param.AsString);
except
on e:exception do begin
Memo1.Lines.Add('Exception: '+e.Message);
end;
end;
end;
end.