Я использую объект SqlCommand для вставки записи в таблицу с помощью автогенерированного первичного ключа. Как написать текст команды, чтобы я получил вновь созданный идентификатор, когда я использую метод ExecuteScalar()?
Как вставить запись и вернуть вновь созданный идентификатор с помощью одного SqlCommand?
Ответ 1
INSERT INTO YourTable(val1, val2, val3 ...)
VALUES(@val1, @val2, @val3...);
SELECT SCOPE_IDENTITY();
Не забывайте точки с запятой в конце каждого утверждения.
Ответ 2
Добавьте следующую строку в конец запроса Sql...
SELECT SCOPE_IDENTITY()
И затем используйте метод ExecuteScalar для объекта SqlCommand...
var rowCount = command.ExecuteScalar()
Ответ 3
insert into Yourtable()
values()
SELECT SCOPE_IDENTITY()
Я только что проверил и проверил, что полуколоны являются необязательными с использованием SQL Server 2005 SP2 и .Net 3.5
Ответ 4
Добавьте выходной параметр в объект команды, а затем установите значение в новый идентификатор в хранимой процедуре.
Сохраненная процедура:
@ID AS INT OUTPUT
[Insert Command]
SET @ID = SCOPE_IDENTITY()
.NET:
cmd.CommandText = "stored_procedure";
SqlParameter pID = new SqlParameter("ID", DBType.Int32, 4);
pID.Direction = ParameterDirection.Output;
cmd.ExecuteScalar();
int id = Convert.ToInt32(cmd.Parameters["ID"].Value.ToString());
Ответ 5
Сразу же после вашей вставки stmt используйте
SELECT CAST(scope_identity() AS bigint) ---- incase you have a return result as int64
Это вернет созданный столбец id/identity.
Ответ 6
Не используйте @@IDENTITY, каким бы простым это ни казалось. Он может возвращать неправильные значения.
SELECT SCOPE_IDENTITY()
представляется очевидным выбором.
Ответ 7
Прямо из Whirlpool:
Если вы используете MS SQL, вы можете использовать "SELECT @@IDENTITY as Value" после своей вставки, чтобы получить последний сгенерированный идентификатор
и
@@IDENTITY
иSCOPE_IDENTITY
вернуть последнее значение идентификации, сгенерированное в любой таблице текущего сеанса. ОднакоSCOPE_IDENTITY
возвращает значение только в пределах текущей области;@@IDENTITY
не ограничивается определенной областью.
Изменить: Как указано в комментариях, вы всегда должны использовать SCOPE_IDENTITY
, а не @@IDENTITY
.
Ответ 8
Хотя мне нравится ответ Dave Markle (и я вижу, что вы тоже это сделали, поскольку вы отметили его как ваш ответ), этот метод может выйти из строя, если у вас есть триггеры на ваша база данных, в которой проверяются операции CUD, и ваша таблица аудита имеют столбец IDENTITY. Он вернет значение идентификатора таблицы аудита, а не таблицу, в которую вы только что вставили, поскольку фактическая таблица аудита произошла после.
В этом случае можно использовать более общий метод, который будет работать в обоих случаях независимо от любого аудита. Это немного более многословно, но вы получаете то, за что платите.
Пример:
@"DECLARE @tmp AS TABLE ( id int )
INSERT INTO case
(
caseID,
partID,
serialNumber,
hardware,
software,
firmware
)
OUTPUT Inserted.ID into @tmp
VALUES
(
@caseID,
@partItemID,
@serialNumber,
@hardware,
@software,
@firmware
)
Select ID from @tmp" )
Ответ 9
Если ваш идентификатор является Guid, то я нашел это решение лучшим:
INSERT INTO YourTable (val1, val2, val3)
OUTPUT inserted.id
VALUES (@val1, @val2, @val3)
Спасибо @Scott Ivey
Полная демонстрация:
internal static Guid InsertNote(Note note)
{
Guid id;
using (
var connection =
new SqlConnection(ConfigurationManager.ConnectionStrings["dbconn"].ConnectionString))
{
connection.Open();
using (
var command =
new SqlCommand(
"INSERT INTO Notes ([Title],[Text]) " +
"OUTPUT inserted.id " +
$"VALUES ('{title}','{text}');", connection))
{
command.CommandType = CommandType.Text;
var reader = command.ExecuteReader();
reader.Read();
id = reader.GetGuid(reader.GetOrdinal("id"));
}
connection.Close();
}
return id;
}
Я бы рекомендовал использовать хранимую процедуру, но это для модульного тестирования нашего репозитория.