Почему я продолжаю получать сообщение «Должен объявить скалярную переменную @Param1» при выполнении параметризованного запроса на C++ с использованием ADO?

Вот код.
Несколько замечаний по этому поводу. DStr — это строковый класс, который является внутренним для нашей компании. Он работает так же, как CString. Я могу подключиться к базе данных и выполнять непараметризованные запросы. Также эта вставка отлично работает, если я не использую параметры. Статус cmd->Execute вызывает исключение. Вот откуда я получаю сообщение об ошибке.

    void CEmailArchiveDatabase::TestAddUser( DStr username, DStr displayname )
{

    DStr sql = "INSERT INTO [User] (UserName, DisplayName) VALUES (@Param1, @Param2)";

    _variant_t vUser;
    _variant_t vDisp; 

    vUser.vt = VT_BSTR;
    vUser.bstrVal = username.AllocSysString();
    vDisp.vt = VT_BSTR;
    vDisp.bstrVal = displayname.AllocSysString();

    _CommandPtr cmd = NULL;
    _ConnectionPtr conn = NULL;
    _ParameterPtr prm = NULL;

    DStr connStr = "driver={SQL Server};server=DEMETER\\SQLEXPRESS;database=ExtractoMundo";

    try
    {
        conn.CreateInstance(__uuidof(Connection));
        cmd.CreateInstance(__uuidof(Command));

        if( !(conn->GetState() & adStateOpen) )
        {
            conn->ConnectionString = connStr.AllocSysString();
            conn->Open("", "", "", NULL);
            conn->CursorLocation = adUseClient;
        }   

        cmd->ActiveConnection = conn;
        cmd->CommandText = sql.AllocSysString();
        cmd->CommandType = adCmdText;

        prm = cmd->CreateParameter("@Param1", adLongVarChar, adParamInput, -1, vUser);
        cmd->Parameters->Append(prm);
        prm = cmd->CreateParameter("@Param2", adLongVarChar, adParamInput, -1, vDisp);
        cmd->Parameters->Append(prm);

        _variant_t recAff;

        cmd->Execute(&recAff, NULL, adExecuteNoRecords);

    }
    catch(_com_error &ex)
    {
        //ClearParameters();
        DStr err;
        err += PrintProviderError(conn);
        err += PrintComError(ex);
    }

    SysFreeString(vUser.bstrVal);
    SysFreeString(vDisp.bstrVal);
    SysFreeString(cmd->CommandText);
    SysFreeString(conn->ConnectionString);

}

person Jeremy Hutchinson    schedule 17.03.2009    source источник


Ответы (3)


ADO отказывается работать с именованными параметрами в динамических запросах. Вы должны либо преобразовать именованные параметры в заполнители параметров:

DStr sql = "INSERT INTO [User] (UserName, DisplayName) VALUES (?, ?)";

или вместо этого используйте хранимую процедуру. Создайте процедуру:

CREATE PROCEDURE spUserInsert
  @Param1 nvarchar(50), 
  @Param2 nvarchar(50) 
AS 
  SET NOCOUNT ON;
  INSERT INTO [User] (UserName, DisplayName) VALUES (@Param1, @Param2)
GO

и измените свой код, чтобы вызвать его:

DStr sql = "spUserInsert";
...
cmd->CommandType = adCmdStoredProcedure;
person grudolf    schedule 02.03.2010

Возможно cmd->CreateParameter(_bstr_t("Param1"), ...) ?

"@" - это специфический оператор SQL Server, он может вас смущать.

person slf    schedule 17.03.2009
comment
Я думаю, что вижу это сейчас. Попробуйте использовать adCmdStoredProc вместо adCmdText. - person slf; 18.03.2009

Вы пытались использовать adCmdStoredProc вместо adCmdText?

person slf    schedule 20.03.2009
comment
Это неправильно, потому что OP явно не использует хранимую процедуру. - person Vivian River; 09.03.2012