Функция SCOPE_IDENTITY() всегда возвращает значение NULL, если используется с параметром SQLBindParameter

#c #sql-server

Вопрос:

Я пытаюсь вставить данные в базу данных через ODBC sql server. И я хочу вернуть идентификатор этой строки, поэтому я использую SELECT SCOPE_IDENTITY(); , так как эта таблица имеет идентификатор в качестве первичного ключа и автоматическое увеличение. Функция вставки работает нормально, данные вставляются в базу данных. Но когда я использую SELECT SCOPE_IDENTITY(); их, Они возвращают значение NULL.

поэтому я стараюсь использовать чистый оператор без SQLBindParameter. SELECT SCOPE_IDENTITY(); работает отлично. У вас есть какие-нибудь советы, почему у меня возникла проблема при использовании SQLBindParameter?

Вот моя таблица в бД :

[первичный ключ] (длинный) Идентификатор (нварчар(255)) Имя (короткая) Позиция

Вот функция вставки с параметром SQLBindParameter :

 std::string name = "testname";
std::wstring ws = L"INSERT INTO [dbo].[Test] ([Name], [Position]) VALUES (?,1);";

RETCODE RetCode = SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR,
            SQL_CHAR, name.length(), 0, (SQLPOINTER)name.c_str(), name.length(), NULL);

if(RetCode != SQL_SUCCESS)
{
    HandleDiagnosticRecord(hStmt, SQL_HANDLE_STMT, RetCode);
}

RetCode = SQLExecDirect(hStmt, (SQLWCHAR*)ws.c_str(), SQL_NTS);
switch(RetCode)
{
    case SQL_SUCCESS:
    break;
    //other cases
}

SQLFreeStmt(hStmt, SQL_CLOSE);
 

Вот SELECT SCOPE_IDENTITY() код :

 std::wstring ws = L"SELECT SCOPE_IDENTITY();";
RETCODE RetCode = SQLExecDirect(hStmt, (SQLWCHAR*)ws.c_str(), SQL_NTS);
switch (RetCode)
{
    case SQL_SUCCESS:
    {
        long id= -1;
        SQLLEN indPtr;
        SQLBindCol(hStmt, 1, SQL_C_LONG, amp;id, 0, amp;indPtr);

        if (SQLFetch(hStmt) == SQL_SUCCESS)
        {
            if (indPtr != SQL_NULL_DATA)
            {
                std::cout << "Result id: " << characterId << std::endl;
            }
            else
            {
                std::cout << "Result id: NULL " << std::endl;
            }
        }
        break;
     }
     //other cases
}
SQLFreeStmt(hStmt, SQL_CLOSE);
 

Вот функция вставки без параметра SQLBindParameter :

 std::wstring ws = L"INSERT INTO [dbo].[Test] ([Name], [Position]) VALUES ('testname', 1);";

RetCode = SQLExecDirect(hStmt, (SQLWCHAR*)ws.c_str(), SQL_NTS);
switch(RetCode)
{
    case SQL_SUCCESS:
    break;
    //other cases
}

SQLFreeStmt(hStmt, SQL_CLOSE);
 

Комментарии:

1. Хотя я не умею читать C , похоже , что вы INSERT и вызов SCOPE_IDENTITY находитесь в разных пакетах/областях; поэтому область для вашей вставки уже потеряна. Вы должны возвращать значение SCOPE_IDENTITY в той же области (подсказка в названии).

2. @Larnu Спасибо за ваш ответ, я пытаюсь переместить ` ОБЛАСТЬ видимости` в регистр переключения внутри INSERT функции, но результат все тот же.

3. Вы проверили SQLRETURN результат SQLBindCol ? Если столбец идентификаторов в SQL int , в отличие от bigint , вы пробовали использовать SQL_C_INT вместо этого?

4. @AlwaysLearning Я проверил SQLRETURN SQLBindCol , результат есть SQL_SUCCESS . Я пытаюсь использовать SQL_C_SBIGINT , и результат все тот же NULL .

5.Не должно ли быть, чтобы SQLBindCol(hStmt, 0,.... столбцы начинались с 0, я думаю, и вы, вероятно, захотите сначала привести свой результат SELECT CAST(SCOPE_IDENTITY() AS int)); , потому что возврат numeric(38,0)

Ответ №1:

Решение этой проблемы заключается в использовании предложения «OUTPUT» для возврата элемента вставленного элемента вместо вызова SELECT SCOPE_IDENTITY();

таким образом, полностью sql — команда является INSERT INTO [dbo].[Test] ([Name], [Position]) OUTPUT INSERTED.[Id] VALUES (?,1);