ADO не передает первое значение параметра - PullRequest
2 голосов
/ 10 февраля 2020

Я использую объект ADO Command для генерации параметризованных запросов к SQL Серверу.

Если я генерирую и предоставляю несколько параметров, все параметры передаются значения - кроме первого .

Если вы представляете запрос вроде:

SELECT ?, ?, ?, ?, ?

И используйте объект команды ADO для предоставления значений параметров:

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, чтобы увидеть, что значение первого параметра равно нулю:

enter image description here

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

Я пробовал с ним разные типы, в разных запросах, в разных порядках. Это всегда первый параметр, который отказывается передавать на сервер базы данных.

И я могу подтвердить, что параметр имеет значение перед вызовом Execute:

command.Parameters[0].Value

Что я делаю не так?

  • Клиент: Windows Vista, Windows 7, Windows 10
  • Поставщик OLEDB: SQLOLEDB, SQLNCLI11, MSOLEDB SQL
  • Сервер: SQL Сервер 2000, SQL Сервер 2005, SQL Сервер 2008 R2, SQL Сервер 2012, SQL Север 2017
  • Компилятор : Delphi 5, Delphi XE6, Delphi 10,3 Electri c 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.

Чтение бонуса

1 Ответ

3 голосов
/ 10 февраля 2020

Вы должны использовать EmptyParam вместо Null в вашем операторе cmd.Execute (который является аргументом Parameters).

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

См .: Метод выполнения (команда ADO)

EmptyParam должен быть совместим с необязательным параметром ole. Вы также можете использовать OleVariant(cmd).Execute в своем примере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...