Вопрос по sql, sql-server – Выберите последнюю строку в таблице SQL

6

Можно ли вернуть последний ряд таблицы в MS SQL Server. Я использую поле автоматического увеличения для идентификатора, и я хочу получить последнее добавленное, чтобы присоединить его к чему-то еще. Любая идея?

Вот код:

const string QUERY = @"INSERT INTO Questions (ID, Question, Answer, CategoryID, Permission) " 
                   + @"VALUES (@ID, @Question, @Answer, @CategoryID, @Permission) "; 

using (var cmd = new SqlCommand(QUERY, conn)) 
{ 
    cmd.Parameters.AddWithValue("@Question", question); 
    cmd.Parameters.AddWithValue("@Answer", answer); 
    cmd.Parameters.AddWithValue("@CategoryID", lastEdited);
    cmd.Parameters.AddWithValue("@Permission", categoryID);
    cmd.ExecuteNonQuery(); 
}

Ваш Ответ

7   ответов
1

но поищите предложение OUTPUT оператора INSERT. Вы можете захватить ряд строк с этим предложением

-1

SELECT *
FROM table_name
WHERE IDColumn=(SELECT max(IDColum) FROM table_name)
небезопасно в параллельной среде ......
19

added to join it with something else.

Ключ здесь & quot;just added& Quot ;. Если у вас есть несколько разных пользователей, одновременно обращающихся к БД, я не думаю, что вы хотите, чтобы пользователь А извлек запись, созданную пользователем Б. Это означает, что вы, вероятно, хотите использоватьscope_identity() функция, чтобы получить этот идентификатор, вместо того, чтобы сразу же выполнить запрос к таблице.

В зависимости от контекста вам также может понадобиться@@identity (будет включать триггеры) илиident_current('questions') (ограничено конкретной таблицей, но не конкретной областью действия). Ноscope_identity() почти всегда правильно использовать.

Вот пример:

DECLARE @NewOrderID int

INSERT INTO TABLE [Orders] (CustomerID) VALUES (1234)

SELECT @NewOrderID=scope_identity()

INSERT INTO TABLE [OrderLines] (OrderID, ProductID, Quantity) 
    SELECT @NewOrderID, ProductID, Quantity
    FROM [ShoppingCart]
    WHERE CustomerID=1234 AND SessionKey=4321

Основываясь на опубликованном вами коде, вы можете сделать что-то вроде этого:

// don't list the ID column: it should be an identity column that sql server will handle for you
const string QUERY = "INSERT INTO Questions (Question, Answer, CategoryID, Permission) " 
                   + "VALUES (@Question, @Answer, @CategoryID, @Permission);"
                   + "SELECT scope_identity();"; 

int NewQuestionID;
using (var cmd = new SqlCommand(QUERY, conn)) 
{ 
    cmd.Parameters.AddWithValue("@Question", question); 
    cmd.Parameters.AddWithValue("@Answer", answer); 
    cmd.Parameters.AddWithValue("@CategoryID", lastEdited);
    cmd.Parameters.AddWithValue("@Permission", categoryID);
    NewQuestionID = (int)cmd.ExecuteScalar(); 
}

Смотрите мой ответ на другой вопрос здесь:
получить новый идентификатор записи SQL

Проблема состоит в том, что вы, вероятно, захотите, чтобы последующие операторы SQL были в одной транзакции. Вы можете сделать это с помощью клиентского кода, но я считаю, что хранить все это на сервере будет чище. Вы можете сделать это, создав очень длинную строку sql, но я предпочитаю хранимую процедуру на этом этапе.

Я тоже не фанат.AddWithValue() метод & # x2014; Я предпочитаю явно определять типы параметров & # x2014; но мы можем оставить это на другой день.

Наконец, сейчас немного поздно, но я хочу подчеркнуть, что действительно лучше попытаться сохранить все это на БД. Можно выполнять несколько операторов в одной команде sql, и вы хотите уменьшить количество обращений к базе данных, которые вам нужно совершить, и объем данных, которые вам нужно передавать между базой данных и вашим приложением. Это также облегчает правильное оформление транзакций и позволяет сохранять атомарность там, где они должны быть.

+1 за упоминание scope_identity () почти всегда подходит для использования.
я удивлен, что никто не упомянул identity_current, я разместил несколько ссылок и примеров
Не включайте scope_identity () в запрос. Вы запускаете его после добавления новой строки и сохраняете результат в переменной, которую затем можете использовать для создания «соединения», если это все еще требуется. Дай мне минутку, и у меня будет правка, демонстрирующая это.
Строка кода TSQl 5: SELECT @ NewOrderID = scope_identit () Должно быть: SELECT @ NewOrderID = scope_identity () буква y отсутствует.
но идентичность области возвращает меня столбец нулевых значений, я хочу, чтобы последнее не счет? только что добавил: предыдущие строки кодов были те, которые добавили эту новую строку Ahmad Farid
10

scope_identity() returns the last identity value generated in this session and this scope

ident_current() returns the last identity value generated for a particular table in any session and any scope

select ident_current( 'yourTableName' )

вернет последний идентификатор, созданный другим сеансом.

Большую часть времени вы должны использовать scope_identity () сразу после оператора вставки, например, так.

--insert statement
SET @id = CAST(SCOPE_IDENTITY() AS INT)
MSDN Link - Scope_Identity() MSDN Link - Ident_Current
Стэн, я не понизил, но все в порядке, чтобы удалить ответы!
я отредактировал свой ответ, чтобы отразить больше того, о чем просит пользователь.
+1, и я даже не знал о ident_current ().
......... буо :(
1

здесь приведен модифицированный пример того, как это сделать. (Я удалил ID из списка вставки, так как это автоинкремент - исходный пример потерпит неудачу. Я также предполагаю, что ID - это SQL int, а не bigint.)

        const string QUERY = @"INSERT INTO Questions (Question, Answer, CategoryID, Permission) "
                           + @"VALUES (@Question, @Answer, @CategoryID, @Permission);"
                           + @"SELECT @ID = SCOPE_IDENTITY();";

        using (var cmd = new SqlCommand(QUERY, conn)) 
        { 
            cmd.Parameters.AddWithValue("@Question", question); 
            cmd.Parameters.AddWithValue("@Answer", answer); 
            cmd.Parameters.AddWithValue("@CategoryID", lastEdited);
            cmd.Parameters.AddWithValue("@Permission", categoryID);
            cmd.Parameters.Add("@ID", System.Data.SqlDbType.Int).Direction = ParameterDirection.Output;
            cmd.ExecuteNonQuery();

            int id = (int)cmd.Parameters["@ID"].Value;
        }

EDITED: Я также предлагаю рассмотреть LINQ to SQL вместо ручного кодирования объектов SqlCommand - это намного лучше (быстрее кодировать, проще в использовании) для многих распространенных сценариев.

4
select top 1 * from yourtable order by id desc
Он говорит, что хочет присоединиться к «только что добавленному»; с чем-то еще после вставки, как в типичных вставках с основной деталью. Было бы очень необычно хотеть вставить случайную строку другим пользователем.
-1 это вернет последнюю вставку любым пользователем, а не последней вставкой текущего пользователя
Быть осторожен. На первый взгляд это выглядит правильно, но если вы внимательно прочитаете вопрос, с ним возникнут проблемы.
@Remus Rusanu: нигде в вопросе не было упоминания о том, что он должен возвращать последнюю вставку текущего пользователя. Но если вы думаете, что мой ответ неверен, я думаю, ваш голос был заслуженным.
Правда, но вопрос не совсем понятен. & quot; присоединение к & quot; также может означать поиск связанных записей с последней в таблице.
24

и последняя строка, которую вы получите, может быть не вашей. Вам лучше использовать SCOPE_IDENTITY (), чтобы получить последний ключ, назначенный для вашей транзакции.

+1: исправить, если клиент не начал новую транзакцию.
Отличный момент. Когда я писал, я просто читал "дай мне последний ряд". Я проигнорировал его намерение использовать его для создания ссылки на внешний ключ.
+1 за предоставление правильного решения
+1 очень хороший момент ... сейчас я хочу, чтобы люди не понизили меня, потому что я неправильно понял вопрос.
+1. Я был удивлен (и обеспокоен), что ваш был единственным ответом, который использовал это.

Похожие вопросы