【问题标题】:ADO not passing first parameter valueADO 不传递第一个参数值
【发布时间】:2020-05-25 08:58:14
【问题描述】:

我正在使用 ADO Command 对象来生成针对 SQL Server 的参数化查询。

如果我生成并提供多个参数,则传递所有参数值 - 第一个除外

如果您想像这样的查询:

SELECT ?, ?, ?, ?, ?

并使用 ADO Command 对象提供参数值:

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);

可以使用Profiler查看第一个参数值为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

我用不同的类型、不同的查询、不同的顺序尝试过它。拒绝提供给数据库服务器的始终是 first 参数。

而且我可以在调用 Execute 之前确认参数确实有值:

command.Parameters[0].Value

我做错了什么?

  • 客户端: Windows Vista、Windows 7、Windows 10
  • OLEDB 提供程序: SQLOLEDB、SQLNCLI11、MSOLEDBSQL
  • 服务器: SQL Server 2000、SQL Server 2005、SQL Server 2008 R2、SQL Server 2012、SQL Sever 2017
  • 编译器:Delphi 5、Delphi XE6、Delphi 10.3 Electric Boogaloo

CMRE

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.

阅读奖励

【问题讨论】:

  • 您为什么不使用 TADOxxxx 组件?

标签: sql-server delphi oledb ado


【解决方案1】:

您应该在cmd.Execute 语句(即Parameters 参数)中使用EmptyParam 而不是Null

cmd.Execute({out}recordsAffected, EmptyParam, adExecuteNoRecords);

见:Execute Method (ADO Command)

EmptyParam 应该与可选的 ole 参数兼容。 您也可以在示例中使用OleVariant(cmd).Execute

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-24
    • 2020-03-16
    • 2019-03-26
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    相关资源
    最近更新 更多