2010-06-23 3 views
4

У меня есть таблица, которая используется для хранения инкрементирующего числового идентификатора (типа INT). Он содержит одну строку. ID увеличивается с помощью запроса:Сохраненная процедура, возвращающая результат UPDATE

UPDATE TOP(1) MyTable 
WITH(TABLOCKX) 
SET NextID = NextID + 1 

Я хотел бы, чтобы переместить это в хранимую процедуру, которая возвращает значение, которое было в колонке NextID перед тем он был увеличен, но не уверен, как это сделать с помощью OUTPUT. Любая помощь будет оценена по достоинству.

+0

Я гость, вы не можете использовать [личность] (http://msdn.microsoft.com/en-us/library/aa933196% 28SQL.80% 29.aspx). –

+0

@Grzegorz Не вариант в этом случае. Иногда мне нужно установить значение на произвольное число - либо в программном обеспечении вручную в студии управления sql. –

ответ

3

для SQL Server 2005+, попробуйте:

CREATE PROCEDURE dbo.Get_New_My_Table_ID 
    @current_id INT = NULL OUTPUT -- Declared OUTPUT parameter 
AS 
BEGIN TRANSACTION 

UPDATE TOP(1) MyTable WITH(TABLOCKX) 
    SET NextID = NextID + 1 
    OUTPUT DELETED.NextID 

COMMIT TRANSACTION 

RETURN 0 
GO 

результаты OUTPUT не нужны чтобы войти в фактическую таблицу, это может быть набор результатов.

тест это:

declare @MyTable table (NextID int) 
INSERT INTO @MyTable VALUES (1234) 


SELECT 'BEFORE',* FROM @MyTable 

PRINT '------------<<<<UPDATE>>>>---------' 
UPDATE TOP(1) @MyTable 
    SET NextID = NextID + 1 
    OUTPUT DELETED.NextID 
PRINT '------------<<<<UPDATE>>>>---------' 

SELECT 'AFTER',* FROM @MyTable 

ВЫВОД:

(1 row(s) affected) 
     NextID 
------ ----------- 
BEFORE 1234 

(1 row(s) affected) 

------------<<<<UPDATE>>>>--------- 
NextID 
----------- 
1234 

(1 row(s) affected) 

------------<<<<UPDATE>>>>--------- 
     NextID 
----- ----------- 
AFTER 1235 

(1 row(s) affected) 
+0

Спасибо KM. Это подходит для меня.Поскольку запрос проще (и предположительно более эффективен), чем у Тома, я принял ваш ответ. –

2

Возможно, вы захотите добавить некоторые проверки ошибок и т. Д. Я также предположил, что таблица является таблицей с одной строкой.

CREATE PROCEDURE dbo.Get_New_My_Table_ID 
    @current_id INT = NULL OUTPUT -- Declared OUTPUT parameter 
AS 
BEGIN 
    BEGIN TRANSACTION 

    SELECT 
     @current_id = COALESCE(next_id, 0) 
    FROM 
     dbo.My_Table WITH (TABLOCK, HOLDLOCK) 

    UPDATE dbo.My_Table 
    SET next_id = @current_id + 1 

    COMMIT TRANSACTION 
END 
GO 

Для использования хранимой процедуры:

DECLARE @my_id INT 

EXEC dbo.Get_New_My_Table_ID @current_id = @my_id OUTPUT 
+0

@Tom он хочет вернуть значение * до инкремента *. –

+0

Спасибо, Том, это работает для меня. Идея использования начального выбора перед обновлением произошла со мной, но я ошибочно полагал, что HOLDLOCK нельзя использовать с TABLOCKX, поэтому я не мог видеть способ сохранить блокировку. Похоже, может. Также вы познакомили меня с заявлением COALESCE, о котором я не знал! –

+0

@Martin Правда, но я могу легко адаптировать его решение. –

3

В SQL2005 или более поздней версии предыдущие значения для обновленных значений могут быть получены, используя пункт OUTPUT.

Учитывая, что будет возвращено только одно значение, я не знаю, как это сравнивается с подходом Тома. Я подозреваю, что Том будет быстрее, так как есть дополнительное чтение, но нет накладных расходов на создание переменной таблицы. (Edit: и, конечно, мое до сих пор читать табличную переменную, как хорошо!)

CREATE PROC blah 
@OldId int OUTPUT 
AS 

DECLARE @OldIds table(NextID int); 


UPDATE TOP(1) MyTable 
WITH(TABLOCKX) 
SET NextID = NextID + 1 
OUTPUT DELETED.NextID INTO @OldIds 

SELECT @OldId = NextID 
FROM @OldIds 
+0

Спасибо Мартин. +1 для этого. Я решил принять решение Тома, потому что он избегает необходимости в временной таблице. Казалось немного проще. –

+0

@ Энди - Да, я согласен. Жаль, что '@OldId = DELETED.NextID' не работает. –

+0

Предложение 'OUTPUT' - это путь, но вы разрушили его, используя таблицу temp. 'OUTPUT' не нужно заходить в таблицу, это может быть набор результатов, см. Мой ответ. –

Смежные вопросы