SQL Server: вставьте следующий доступный int - PullRequest
6 голосов
/ 31 января 2011

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

Так как мне вставить следующий доступный номер?

Я пробовал это:

INSERT INTO mytable (serial_no) VALUES ( (SELECT MAX(serial_no)+1 FROM mytable))

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

РЕДАКТИРОВАТЬ: Эта таблица используется в готовом продукте, поэтому я не могу изменить дизайн и сделать столбец serial_no автоматическим приращением.

Ответы [ 4 ]

9 голосов
/ 31 января 2011

Вы можете улучшить параллелизм записи с помощью подсказок блокировки

INSERT INTO mytable (serial_no, value)
SELECT MAX (serial_no)+1, @value 
FROM mytable WITH (ROWLOCK, XLOCK, HOLDLOCK)

Если производительность не важна, попробуйте TABLOCKX вместо ROWLOCK, XLOCK

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

DECLARE @retry bit
SET @retry = 1

WHILE @Retry = 1
BEGIN
    BEGIN TRY
        INSERT INTO mytable (serial_no, value)
        SELECT MAX (serial_no)+1, @value 
        FROM mytable WITH (ROWLOCK, XLOCK, HOLDLOCK)

        SET @Retry = 0
    END TRY
    BEGIN CATCH
        IF ERROR_NUMBER() <> 2627  --PK violation
            RAISERROR ('blah', 16, 1)
    END CATCH
END

или перейти к столбцу IDENTITY и сделать это правильно ...

2 голосов
/ 31 января 2011

Ошибка может быть исправлена ​​путем сброса ЗНАЧЕНИЙ

INSERT INTO mytable (serial_no, value)

SELECT MAX(serial_no)+1 ,
@value 
FROM mytable)

Но это плохая идея.На MAX (serial_no) +1 есть условие гонки (например, две вставки получают одинаковое значение для Max (Serial_no).

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

0 голосов
/ 31 января 2011

Попробуйте без ЗНАЧЕНИЙ:

INSERT INTO mytable (serial_no) SELECT MAX(serial_no)+1 FROM mytable
0 голосов
/ 31 января 2011
INSERT INTO mytable (serial_no) SELECT MAX(serial_no)+1 FROM mytable
...