Как вставить запись и вернуть вновь созданный идентификатор, используя один SqlCommand? - PullRequest
48 голосов
/ 01 декабря 2008

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

Ответы [ 9 ]

74 голосов
/ 01 декабря 2008
INSERT INTO YourTable(val1, val2, val3 ...) 
VALUES(@val1, @val2, @val3...);
SELECT SCOPE_IDENTITY();

Не забывайте точки с запятой в конце каждого оператора.

25 голосов
/ 01 декабря 2008

Добавьте следующую строку в конец запроса Sql ...

SELECT SCOPE_IDENTITY()

А затем используйте метод ExecuteScalar для объекта SqlCommand ...

var rowCount = command.ExecuteScalar()
16 голосов
/ 01 декабря 2008
insert into Yourtable()  
values()  
SELECT SCOPE_IDENTITY()

Я только что выполнил тест и убедился, что точки с запятой необязательны с использованием SQL Server 2005 с пакетом обновления 2 (SP2) и .Net 3.5

5 голосов
/ 01 декабря 2008

Добавьте выходной параметр к объекту команды, а затем установите значение для нового идентификатора в хранимой процедуре.

Хранимая процедура:

@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());
2 голосов
/ 01 декабря 2008

Не используйте @@ IDENTITY, каким бы простым это ни казалось. Может возвращать неверные значения.

SELECT SCOPE_IDENTITY()

представляется очевидным выбором.

2 голосов
/ 01 декабря 2008

Сразу после ввода stmt используйте

SELECT CAST(scope_identity() AS bigint) ---- incase you have a return result as int64

Это вернет созданный столбец id / identity.

1 голос
/ 02 февраля 2017

Если ваш идентификатор - Guid, то я нашел это решение лучшим:

INSERT INTO YourTable (val1, val2, val3) 
OUTPUT inserted.id 
VALUES (@val1, @val2, @val3)

Спасибо @ Скотт Айви

Полная демонстрация:

    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;
    }

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

1 голос
/ 01 декабря 2008

Хотя мне нравится ответ Дейва Маркля (и я вижу, что вы тоже это сделали, поскольку вы отметили его как свой ответ), этот метод может завершиться неудачей, если у вас есть триггеры в базе данных, которые проверяют операции 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" )
1 голос
/ 01 декабря 2008

прямо из джакузи :

Если вы используете MS SQL, вы можете использовать «SELECT @@ IDENTITY as Value» после вставки, чтобы получить последний сгенерированный идентификатор

и

@@IDENTITY и SCOPE_IDENTITY возвращают последнее значение идентификатора, сгенерированное в любой таблице в текущем сеансе. Однако SCOPE_IDENTITY возвращает значение только в пределах текущей области; @@IDENTITY не ограничен конкретной областью применения.

Редактировать: Как указано в комментариях, вы всегда должны использовать SCOPE_IDENTITY, а не @@IDENTITY.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...