T-SQL, Вставить в с MAX() + 1 в подзапросе не увеличивается, альтернативы?

У меня есть запрос, где мне нужно "пакет" вставлять строки в таблицу с первичным ключом без идентификатора.

--TableA
--PK int (Primary key, no-identity)
--CustNo int
INSERT INTO TableA (PK,CustNo)
  SELECT (SELECT MAX(PK)+1 AS PK FROM TableA), CustNo
  FROM Customers

(упрощенный пример - пожалуйста, не комментируйте возможные проблемы concurrency: -))

Проблема заключается в том, что она не увеличивает PK "для каждой" обработанной строки, и я получаю нарушение первичного ключа.

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

(выполняется стандартный SQL Server 2008)

Ответ 1

Declare @i int;

Select @i = max(pk) + 1 from tablea;

INSERT INTO TableA (PK, custno)
Select row_number() over(order by custno) + @i  , CustNo
FROM Customers

Ответ 2

+1 Майклу Буэну, но у меня есть одно предложение:

Таблица "tablea" может быть пустой, поэтому мы должны написать:

Select @i = isnull(max(pk),0) + 1 from tablea;

Это предотвратит ошибку null при попытке использовать этот код.

Ответ 3

Проблема, которую вы видели, состоит в том, что все они получают одинаковый номер строки, max (PK) +1 одинаковый для каждой строки.

Попробуйте преобразовать его в Max(PK) + Row_number()

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

Ответ 4

Вы можете:

;with T(NPK, CustNo) as (
  select row_number() over (order by CustNo), CustNo from Customers
)
insert into TableA (PK, CustNo)
  select NPK, custno from T
order by CustNo 

Ответ 5

У меня есть предложение для вас приятель, лучше практика SQL говорит использовать SEQUENCE, и угадайте, что, очень легко сделать это человек, просто скопируйте и вставьте мой:

CREATE SEQUENCE SEQ_TABLEA AS INTEGER     НАЧАТЬ С 1     INCREMENT BY 1     MAXVALUE 2147483647     MINVALUE 1     НЕТ ЦИКЛА

и используйте вот так:

INSERT INTO TableA (PK, CustNo) VALUES (SEQ_TABLEA.NEXTVAL, 123)

Надеюсь, что этот совет поможет вам!