Подтвердить что ты не робот

Как вставить запись и вернуть вновь созданный идентификатор с помощью одного SqlCommand?

Я использую объект SqlCommand для вставки записи в таблицу с помощью автогенерированного первичного ключа. Как написать текст команды, чтобы я получил вновь созданный идентификатор, когда я использую метод ExecuteScalar()?

4b9b3361

Ответ 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;
    }

Я бы рекомендовал использовать хранимую процедуру, но это для модульного тестирования нашего репозитория.