#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
? Если столбец идентификаторов в SQLint
, в отличие от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);