Reputation: 256581
I'm using an ADO Command object to generate parameterized queries against SQL Server.
If i generate and supply multiple parameters, all the parameter values are passed - except the first one.
If you imagine a query like:
SELECT ?, ?, ?, ?, ?
And use the ADO Command object to supply parameter values:
command.Parameters.Append(command.CreateParameter('', adInteger, adParamInput, 0, 1);
command.Parameters.Append(command.CreateParameter('', adInteger, adParamInput, 0, 2);
command.Parameters.Append(command.CreateParameter('', adInteger, adParamInput, 0, 3);
command.Parameters.Append(command.CreateParameter('', adInteger, adParamInput, 0, 4);
command.Parameters.Append(command.CreateParameter('', adInteger, adParamInput, 0, 5);
You can use Profiler to see the first parameter value is null:
exec sp_executesql N'SELECT @P1, @P2, @P3, @P4, @P5',N'@P1 int,@P2 int,@P3 int,@P4 int,@P5 int',NULL,2,3,4,5
I've tried it with different types, in different queries, in different orders. It's always the first parameter that refuses to be supplied to the database server.
And i can confirm that the parameter does have a value before calling Execute:
command.Parameters[0].Value
What am i doing wrong?
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
ActiveX,
ComObj,
ADOint,
Variants;
procedure Main;
var
cs: string;
cn: Connection;
cmd: Command;
p: _Parameter;
recordsAffected: OleVariant;
begin
cs := 'Provider=SQLOLEDB;Data Source=screwdriver;User ID=frog;Password=hunter2';
cn := CoConnection.Create;
WriteLn('Connecting to database...');
cn.Open(cs, '', '', Integer(adConnectUnspecified));
cmd := CoCommand.Create;
cmd.CommandType := adCmdText;
cmd.CommandText := 'IF ? IS NULL RAISERROR(''It was null'', 16, 1);';
cmd.Parameters.Append(cmd.CreateParameter('', adinteger, adParamInput, 0, 1));
cmd.Set_ActiveConnection(cn);
WriteLn('Executing command');
cmd.Execute({out}recordsAffected, Null, adExecuteNoRecords);
end;
begin
try
CoInitialize(nil);
Main;
WriteLn('Success');
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
end;
end;
WriteLn('Press enter to close...');
ReadLn;
end.
Upvotes: 2
Views: 343
Reputation: 21232
You should use EmptyParam
instead of Null
in your cmd.Execute
statement (which is the Parameters
argument).
cmd.Execute({out}recordsAffected, EmptyParam, adExecuteNoRecords);
See: Execute Method (ADO Command)
The EmptyParam
should be compatible with an Optional ole parameter.
You could also use OleVariant(cmd).Execute
in your example.
Upvotes: 3